Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

BinFile.h

Go to the documentation of this file.
00001 
00002 //
00003 // Copyright (C) 2000
00004 // Ralf Westram
00005 // Time-stamp: <Fri Dec/06/2002 06:25 MET Coder@ReallySoft.de>
00006 //
00007 // Permission to use, copy, modify, distribute and sell this software
00008 // and its documentation for any purpose is hereby granted without fee,
00009 // provided that the above copyright notice appear in all copies and
00010 // that both that copyright notice and this permission notice appear
00011 // in supporting documentation.  Ralf Westram makes no
00012 // representations about the suitability of this software for any
00013 // purpose.  It is provided "as is" without express or implied warranty.
00014 //
00015 // This code is part of my library.
00016 // You may find a more recent version at http://www.reallysoft.de/
00017 //
00019 
00020 #ifndef BINFILE_H
00021 #define BINFILE_H
00022 
00023 #ifndef __FSTREAM__
00024 #include <fstream>
00025 #endif
00026 #ifndef ERR_H
00027 #include <Err.h>
00028 #endif
00029 
00030 
00031 namespace rs {
00032     namespace file {
00033 
00035         enum BinaryFileType { BF_INPUT, BF_OUTPUT };
00036 
00037         //  ----------------------------------------------
00038         //      class BinaryFile : rs_boost::noncopyable
00039         //  ----------------------------------------------
00041         class BinaryFile : rs_boost::noncopyable {
00042         private:
00043             std::string filename;
00044             BinaryFileType type;
00045             std::fstream *file;
00046 
00047         public:
00052             BinaryFile(const std::string& filename_, BinaryFileType type_) {
00053                 filename = filename_;
00054                 type = type_;
00055                 if (type==BF_OUTPUT) {
00056                     file = new std::fstream(filename.c_str(), std::ios::binary|std::ios::out);
00057                 }
00058                 else {
00059                     assert(type==BF_INPUT);
00060                     file = new std::fstream(filename.c_str(), std::ios::binary|std::ios::in);
00061                 }
00062                 if (!file || !file->good()) throw rs::err::IOError(filename);
00063             }
00064             virtual ~BinaryFile() { if (file) delete file; }
00065 
00067             const std::string& name() const { return filename; }
00068 
00070             bool good() { return file != 0 && file->good(); }
00071 
00073             bool eof()  {
00074                 assert(type==BF_INPUT);
00075                 return file!=0 && file->eof();
00076             }
00077 
00080             void put_char(unsigned char  c) {
00081                 assert(type==BF_OUTPUT);
00082                 file->put(c);
00083             }
00084 
00087             void get_char(unsigned char& c) {
00088                 assert(type==BF_INPUT);
00089                 int i = file->get();
00090                 if (i==EOF) {
00091                     throw rs::err::Error(std::string("End of file reached (")+filename+")");
00092                 }
00093                 c = i;
00094             }
00095 
00100             void put_nat(unsigned long nat) {
00101                 assert(sizeof(nat)==4);
00102 
00103                 if (nat<=0x7f) {
00104                     put_char(nat); // bit7==0 -> 1 byte integer
00105                 }
00106                 else if (nat<=0x3FFF) {
00107                     put_char((nat>>8) | 0x80); // bit7==1 && bit6==0 -> 2 byte integer
00108                     put_char(nat & 0xFF);
00109                 }
00110                 else if (nat<=0x1FFFFF) {
00111                     put_char((nat>>16) | 0xC0); // bit7==1 && bit6==1 && bit5==0 -> 3 byte integer
00112                     put_char((nat>>8) & 0xFF);
00113                     put_char(nat & 0xFF);
00114                 }
00115                 else if (nat<=0x0FFFFFFF) {
00116                     put_char((nat>>24) | 0xE0); // bit7==1 && bit6==1 && bit5==1 && bit4==0 -> 4 byte integer
00117                     put_char((nat>>16) & 0xFF);
00118                     put_char((nat>>8) & 0xFF);
00119                     put_char(nat & 0xFF);
00120                 }
00121                 else { // sonst als 5 byte integer
00122                     put_char(0xf0);
00123                     put_char((nat>>24) & 0xFF);
00124                     put_char((nat>>16) & 0xFF);
00125                     put_char((nat>>8) & 0xFF);
00126                     put_char(nat & 0xFF);
00127                 }
00128             }
00133             void get_nat(unsigned long &i) {
00134                 unsigned char c; get_char(c);
00135 
00136                 if ((c&0x80)==0) { // 1-byte
00137                     i = c;
00138                 }
00139                 else {
00140                     if ((c&0xC0)==0x80) { // 2-byte
00141                         i = (unsigned long)(c&0x3F) << 8;
00142                     }
00143                     else {
00144                         if ((c&0xE0)==0xC0) { // 3-byte
00145                             i = (unsigned long)(c&0x1F) << 16;
00146                         }
00147                         else {
00148                             if ((c&0xF0)==0xE0) { // 4-byte
00149                                 i = (unsigned long)(c&0x0F) << 24;
00150                             }
00151                             else {
00152                                 get_char(c); i = (unsigned long)c << 24;
00153                             }
00154                             get_char(c); i = (unsigned long)c << 16;
00155                         }
00156                         get_char(c); i |= (unsigned long)c << 8;
00157                     }
00158                     get_char(c); i |= c;
00159                 }
00160             }
00161 
00164             void put_long(long i) {
00165                 // changes position of sign-bit in such manner that compression gets better.
00166                 unsigned long l;
00167                 if (i<0) {
00168                     l = (-i << 1) | 1;
00169                 }
00170                 else {
00171                     l = i << 1;
00172                 }
00173                 put_nat(l);
00174             }
00179             void get_long(long& i) {
00180                 unsigned long l;
00181                 get_nat(l);
00182                 if (l&1) {
00183                     i = -(long)(l >> 1);
00184                 }
00185                 else {
00186                     i = l >> 1;
00187                 }
00188             }
00189 
00192             void put_int(int i) { put_long(i); }
00197             void get_int(int& i) { long l; get_long(l); i=(int)l; }
00198 
00199 
00204             void write_bytes(const unsigned char *buf, std::streamsize size) {
00205                 assert(type==BF_OUTPUT);
00206                 file->write(reinterpret_cast<const char*>(buf), size);
00207             }
00212             void read_bytes(unsigned char *buf, std::streamsize size) {
00213                 assert(type==BF_INPUT);
00214                 file->read(reinterpret_cast<char *>(buf), size);
00215             }
00216 
00219             void put_string(const std::string& s) {
00220                 put_int(s.length());
00221                 write_bytes((const unsigned char *)s.data(), s.length());
00222             }
00225             void get_string(std::string& s) {
00226                 int len;
00227                 get_int(len);
00228                 unsigned char *buf = new unsigned char[len+1];
00229                 read_bytes(buf, len);
00230                 buf[len] = 0;
00231                 s = (char*)buf;
00232                 delete [] buf;
00233             }
00234         };
00235 
00240         template <class T> inline void put_binary(const T& t, BinaryFile& file) {
00241             file.write_bytes((const unsigned char*)(&t), sizeof(t));
00242         }
00243 
00248         template <class T> inline void get_binary(T& t, BinaryFile& file) {
00249             file.read_bytes((unsigned char*)(&t), sizeof(t));
00250         }
00251 
00252         template <> inline void put_binary<std::string>(const std::string& s, BinaryFile& file) { file.put_string(s); }
00253         template <> inline void get_binary<std::string>(std::string& s, BinaryFile& file)  { file.get_string(s); }
00254 
00256 
00262         class BinaryStoreable {
00263         public:
00264             BinaryStoreable() {}
00265             virtual ~BinaryStoreable() {}
00266 
00270             virtual void save(BinaryFile& out) const = 0;
00271 
00276             virtual void load(BinaryFile& in, int version) = 0;
00277         };
00278 
00279     }; // end of namespace file
00280 }; // end of namespace rs
00281 
00282 #else
00283 #error BinFile.h included twice
00284 #endif // BINFILE_H

Contact me in case of errors or questions.
This documentation is powered by Doxygen.
(C) 2000-2002 Doxygen