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 . |
(C) 2000-2002 |