00001 // This is core/vsl/vsl_binary_io.h 00002 #ifndef vsl_binary_io_h_ 00003 #define vsl_binary_io_h_ 00004 //: 00005 // \file 00006 // \brief Set of functions, and objects to perform binary IO 00007 // \author Ian Scott, Tim Cootes (Manchester) March 2001 00008 // 00009 // You should include this file if you want to do binary_io 00010 // 00011 // Also included are a set of functions 00012 // vsl_print_summary(vcl_ostream& os, bool b) 00013 // for basic types to ensure that templated classes 00014 // vsl_print_summaries can work with all types 00015 00016 #include <vcl_iosfwd.h> 00017 #include <vcl_string.h> 00018 #include <vcl_fstream.h> 00019 #include <vcl_map.h> 00020 #include <vcl_utility.h> 00021 #include <vxl_config.h> 00022 00023 //: A binary output adaptor for any vcl_ostream 00024 // Currently the main use of this is to encourage streams to be opened 00025 // in binary mode (ie. without CR/LF conversion) 00026 // 00027 // This class also provide basic support for serialisation. This allows an 00028 // object which has multiple pointers to it to be saved only once. During 00029 // reloading, the pointers can be all set up again to point to the single 00030 // object. vsl_b_ostream does not do the serialisation itself, but instead 00031 // keeps records of unique identifiers to allow the user's code to perform 00032 // serialisation safely. For instance, a smart pointer type object will have 00033 // to know how to safely save whatever it is pointing to. 00034 class vsl_b_ostream 00035 { 00036 public: 00037 //: Create this adaptor using an existing stream 00038 // The stream (os) must be open (i.e. ready to receive insertions) 00039 // so that the 00040 // IO version and magic number can be written by this constructor. 00041 // User is responsible for deleting os after deleting the adaptor 00042 vsl_b_ostream(vcl_ostream *os); 00043 00044 //: A reference to the adaptor's stream 00045 vcl_ostream& os() const; 00046 00047 //: Virtual destructor. 00048 virtual ~vsl_b_ostream() {} 00049 00050 //: Returns true if the underlying stream has its fail bit set. 00051 bool operator!() const; 00052 00053 //: Clear the stream's record of any serialisation operations 00054 // Calling this function while outputting serialisable things to stream, 00055 // will mean 00056 // that a second copy of an object may get stored to the stream. 00057 virtual void clear_serialisation_records(); 00058 00059 00060 //: Adds an object pointer to the serialisation records. 00061 // Returns a unique identifier for the object. 00062 // 00063 // \a pointer must be non-null, so you should handle null pointers separately. 00064 // 00065 // You can optionally add some user-defined integer with each record 00066 // If error checking is on, and the object pointer is null or already in the records, 00067 // this function will abort() 00068 virtual unsigned long add_serialisation_record(void *pointer, int other_data = 0); 00069 00070 //: Returns a unique identifier for the object. 00071 // Returns 0 if there is no record of the object. 00072 virtual unsigned long get_serial_number(void *pointer) const; 00073 00074 //: Set the user-defined data associated with the object 00075 // If there is no record of the object, this function will return 0. 00076 // However a retval of 0 does not necessarily imply that the object is 00077 // unrecorded. 00078 virtual int get_serialisation_other_data(void *pointer) const; 00079 00080 //: Modify the user-defined data associated with the object 00081 // If there is no record of the object, this function will abort. 00082 virtual int set_serialisation_other_data(void *pointer, int other_data); 00083 00084 //: The length of the b_stream header. 00085 // You can move to this offset from the start of the file to get to 00086 // the first real data item. 00087 static const vcl_streamoff header_length; 00088 00089 protected: 00090 //: The member stream 00091 vcl_ostream *os_; 00092 00093 // Design notes: IMS 00094 // I used to think that a pointer and class name were needed to identify an 00095 // object. This is true if class your_class{my_class A}; your_class B; 00096 // then &B = &(B.A). 00097 // However this case doesn't arise in serialisation situations, because you 00098 // can't have shared ownership of A. 00099 00100 // I could have used the pointer itself as the unique identifier, but it is 00101 // unreasonable to expect this to work cross-platform when the platforms have 00102 // different pointer sizes. 00103 00104 //: The type of the serialisation records 00105 typedef vcl_map<void *, vcl_pair<unsigned long, int>, vcl_less<void *> > 00106 serialisation_records_type; 00107 00108 //: The serialisation records 00109 // Records a pointer, a unique identifier, and an integer 00110 // (user_defined data.) 00111 serialisation_records_type serialisation_records_; 00112 00113 //: The version number of the IO scheme. 00114 static const unsigned short version_no_; 00115 }; 00116 00117 00118 //: An adapter for a vcl_ofstream to make it suitable for binary IO 00119 class vsl_b_ofstream: public vsl_b_ostream 00120 { 00121 public: 00122 //: Create this adaptor from a file. 00123 // The adapter will delete the internal stream automatically on destruction. 00124 vsl_b_ofstream(const vcl_string &filename, 00125 vcl_ios_openmode mode = vcl_ios_out | vcl_ios_trunc): 00126 vsl_b_ostream(new vcl_ofstream(filename.c_str(), mode | vcl_ios_binary)) {} 00127 00128 //: Create this adaptor from a file. 00129 // The adapter will delete the internal stream automatically on destruction. 00130 vsl_b_ofstream(const char *filename, 00131 vcl_ios_openmode mode = vcl_ios_out | vcl_ios_trunc) : 00132 vsl_b_ostream(new vcl_ofstream(filename, mode | vcl_ios_binary)) {} 00133 00134 //: Virtual destructor. 00135 virtual ~vsl_b_ofstream(); 00136 00137 00138 //: Close the stream 00139 void close(); 00140 }; 00141 00142 00143 //: An adaptor for any vcl_istream to make it suitable for binary input 00144 // Currently the main use of this is to encourage file streams to be opened 00145 // in binary mode (ie. without CR/LF conversion) 00146 // 00147 // This class also provide basic support for serialisation. During loading, 00148 // multiple pointers to one object can be all set up again to point to the 00149 // single object. vsl_b_ostream does not do the serialisation itself, but 00150 // instead keeps records of unique identifiers to allow the user's code to 00151 // perform serialisation safely. For instance, a smart pointer type object will 00152 // have to know how to safely save whatever it is pointing to. 00153 class vsl_b_istream 00154 { 00155 public: 00156 //: Create this adaptor using an existing stream. 00157 // The stream (is) must be open (i.e. ready to be read from) so that the 00158 // IO version and magic number can be read by this constructor. 00159 // User is responsible for deleting is after deleting the adaptor 00160 vsl_b_istream(vcl_istream *is); 00161 00162 //: A reference to the adaptor's stream 00163 vcl_istream & is() const; 00164 00165 //: Virtual destructor.so that it can be overloaded 00166 virtual ~vsl_b_istream() {} 00167 00168 //: Returns true if the underlying stream has its fail bit set. 00169 bool operator!() const; 00170 00171 //: Clear the stream's record of any serialisation operations 00172 // Calling this function while inputting serialisable things from a stream, 00173 // could cause errors during loading unless the records were cleared at a 00174 // similar point during output. 00175 virtual void clear_serialisation_records(); 00176 00177 //: Adds record of object's unique serial number, and location in memory. 00178 // \a pointer must be non-null, so you should handle null pointers separately. 00179 // 00180 // Adding a null pointer or one that already exists will cause the function to abort(), 00181 // if debugging is turned on; 00182 // 00183 // You can also store a single integer as other data. 00184 // Interpretation of this data is entirely up to the client code. 00185 virtual void add_serialisation_record(unsigned long serial_number, 00186 void *pointer, int other_data = 0); 00187 00188 //: Returns the pointer to the object identified by the unique serial number. 00189 // Returns 0 if no record has been added. 00190 virtual void * get_serialisation_pointer(unsigned long serial_number) const; 00191 00192 //: Returns the user defined data associated with the unique serial number 00193 // Returns 0 if no record has been added. 00194 virtual int get_serialisation_other_data(unsigned long serial_number) const; 00195 00196 //: Modify the user-defined data associated with the unique serial number 00197 // If there is no record of the object, this function will abort. 00198 virtual int set_serialisation_other_data(unsigned long serial_number, 00199 int other_data); 00200 00201 00202 //: Return the version number of the IO format of the file being read. 00203 unsigned short version_no() const; 00204 00205 protected: 00206 //: The member stream 00207 vcl_istream *is_; 00208 00209 //: The type of the serialisation records. 00210 typedef vcl_map<unsigned long, vcl_pair<void *, int>, vcl_less<unsigned long> > 00211 serialisation_records_type; 00212 00213 //: The serialisation records, 00214 // The record takes a unique identifier of the object (which would be 00215 // stored on the stream) and returns the pointer to the object, and 00216 // an other_data integer. 00217 serialisation_records_type serialisation_records_; 00218 00219 // The version number of the IO format of the file being read. 00220 unsigned short version_no_; 00221 }; 00222 00223 00224 //: An adapter for a vcl_ifstream to make it suitable for binary IO 00225 class vsl_b_ifstream: public vsl_b_istream 00226 { 00227 public: 00228 //: Create this adaptor from a file. 00229 // The adapter will delete the stream automatically on destruction. 00230 vsl_b_ifstream(const vcl_string &filename, vcl_ios_openmode mode = vcl_ios_in): 00231 vsl_b_istream(new vcl_ifstream(filename.c_str(), 00232 mode | vcl_ios_binary)) {} 00233 00234 //: Create this adaptor from a file. 00235 // The adapter will delete the stream automatically on destruction. 00236 vsl_b_ifstream(const char *filename, vcl_ios_openmode mode = vcl_ios_in): 00237 vsl_b_istream(new vcl_ifstream(filename, mode | vcl_ios_binary)) {} 00238 00239 //: Virtual destructor.so that it can be overloaded 00240 virtual ~vsl_b_ifstream(); 00241 00242 //: Close the stream 00243 void close(); 00244 }; 00245 00246 //: Write bool to vsl_b_ostream 00247 void vsl_b_write(vsl_b_ostream& os,bool b); 00248 //: Read bool from vsl_b_istream 00249 void vsl_b_read(vsl_b_istream& is,bool& b); 00250 //: Print to a stream 00251 inline void vsl_print_summary(vcl_ostream& os, bool b ) 00252 { os << b; } 00253 00254 //: Write char to vsl_b_ostream 00255 void vsl_b_write(vsl_b_ostream& os,char n ); 00256 //: Read char from vsl_b_istream 00257 void vsl_b_read(vsl_b_istream& is,char& n ); 00258 //: Print to a stream 00259 inline void vsl_print_summary(vcl_ostream& os, char n ) 00260 { os << n; } 00261 00262 //: Write signed char to vsl_b_ostream 00263 void vsl_b_write(vsl_b_ostream& os,signed char n ); 00264 //: Read signed char from vsl_b_istream 00265 void vsl_b_read(vsl_b_istream& is,signed char& n ); 00266 //: Print to a stream 00267 inline void vsl_print_summary(vcl_ostream& os, signed char n ) 00268 { os << n; } 00269 00270 //: Write to vsl_b_ostream 00271 void vsl_b_write(vsl_b_ostream& os,unsigned char n ); 00272 //: Read from vsl_b_istream 00273 void vsl_b_read(vsl_b_istream& is,unsigned char& n ); 00274 //: Print to a stream 00275 inline void vsl_print_summary(vcl_ostream& os, unsigned char n ) 00276 { os << n; } 00277 00278 //: Write to vsl_b_ostream 00279 void vsl_b_write(vsl_b_ostream& os,const vcl_string& n ); 00280 //: Read from vsl_b_istream 00281 void vsl_b_read(vsl_b_istream& is,vcl_string& n ); 00282 //: Print to a stream 00283 inline void vsl_print_summary(vcl_ostream& os, const vcl_string& n ) 00284 { os << n; } 00285 00286 //: Write to vsl_b_ostream 00287 void vsl_b_write(vsl_b_ostream& os,const char* s ); 00288 //: Read from vsl_b_istream 00289 void vsl_b_read(vsl_b_istream& is,char* s ); 00290 //: Print to a stream 00291 inline void vsl_print_summary(vcl_ostream& os, const char* s ) 00292 { os << s; } 00293 00294 00295 // Visual Studio .NET on a 32-bit platform can check for 64-bit 00296 // portability issues. When these warnings (/Wp64) are turn on, 00297 // passing a ptrdiff_t as an int triggers a warning. The __w64 00298 // keyword suppresses that warning here, because it's not a problem. 00299 // On a real 64-bit platform, there will presumably be an overloaded 00300 // vsl_b_write for the 64-bit integral type. We don't want to suppress 00301 // the warning (C4244) completely, because it is a useful warning. 00302 // 08/20/2003: Added macro that defines whether or not attribute needs 00303 // to be used. A new version of MS .NET compiler required this change. 00304 // Add compilers as needed. This could be moved to vcl_compiler.h. 00305 // [Nils Krahnstoever] 00306 #ifdef VCL_VC_DOTNET 00307 # define VCL_64BIT_ATTR __w64 00308 #else 00309 # define VCL_64BIT_ATTR /* */ 00310 #endif 00311 00312 //: Write to vsl_b_ostream 00313 void vsl_b_write(vsl_b_ostream& os, int VCL_64BIT_ATTR n ); 00314 //: Read from vsl_b_istream 00315 void vsl_b_read(vsl_b_istream& is, int VCL_64BIT_ATTR &n ); 00316 //: Print to a stream 00317 inline void vsl_print_summary(vcl_ostream& os, int VCL_64BIT_ATTR n ) 00318 { os << int(n); } 00319 00320 #undef VCL_64BIT_ATTR 00321 00322 //: Write to vsl_b_ostream 00323 void vsl_b_write(vsl_b_ostream& os,unsigned int n ); 00324 //: Read from vsl_b_istream 00325 void vsl_b_read(vsl_b_istream& is,unsigned int& n ); 00326 //: Print to a stream 00327 inline void vsl_print_summary(vcl_ostream& os, unsigned int n ) 00328 { os << n; } 00329 00330 //: Write to vsl_b_ostream 00331 void vsl_b_write(vsl_b_ostream& os,short n ); 00332 //: Read from vsl_b_istream 00333 void vsl_b_read(vsl_b_istream& is,short& n ); 00334 //: Print to a stream 00335 inline void vsl_print_summary(vcl_ostream& os, short n ) 00336 { os << n; } 00337 00338 //: Write to vsl_b_ostream 00339 void vsl_b_write(vsl_b_ostream& os,unsigned short n ); 00340 //: Read from vsl_b_istream 00341 void vsl_b_read(vsl_b_istream& is,unsigned short& n ); 00342 //: Print to a stream 00343 inline void vsl_print_summary(vcl_ostream& os, unsigned short n ) 00344 { os << n; } 00345 00346 //: Write to vsl_b_ostream 00347 void vsl_b_write(vsl_b_ostream& os,long n ); 00348 //: Read from vsl_b_istream 00349 void vsl_b_read(vsl_b_istream& is,long& n ); 00350 //: Print to a stream 00351 inline void vsl_print_summary(vcl_ostream& os, long n ) 00352 { os << n; } 00353 00354 //: Write to vsl_b_ostream 00355 void vsl_b_write(vsl_b_ostream& os,unsigned long n ); 00356 //: Read from vsl_b_istream 00357 void vsl_b_read(vsl_b_istream& is,unsigned long& n ); 00358 //: Print to a stream 00359 inline void vsl_print_summary(vcl_ostream& os, unsigned long n ) 00360 { os << n; } 00361 00362 #if VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG 00363 00364 //: Write to vsl_b_ostream 00365 void vsl_b_write(vsl_b_ostream& os,vxl_int_64 n ); 00366 //: Read from vsl_b_istream 00367 void vsl_b_read(vsl_b_istream& is,vxl_int_64& n ); 00368 //: Print to a stream 00369 inline void vsl_print_summary(vcl_ostream& os, vxl_int_64 n ) 00370 { 00371 #if defined(VCL_VC_6) // IMS. This Hack could be replaced by code which 00372 os << "****"; // splits the 64bit int and doesn the right thing. 00373 #else 00374 os << n; 00375 #endif 00376 } 00377 00378 //: Write to vsl_b_ostream 00379 void vsl_b_write(vsl_b_ostream& os,vxl_uint_64 n ); 00380 //: Read from vsl_b_istream 00381 void vsl_b_read(vsl_b_istream& is,vxl_uint_64& n ); 00382 //: Print to a stream 00383 inline void vsl_print_summary(vcl_ostream& os, vxl_uint_64 n ) 00384 { 00385 #if defined(VCL_VC_6) // IMS. This Hack could be replaced by code which 00386 os << "****"; // splits the 64bit int and doesn the right thing. 00387 #else 00388 os << n; 00389 #endif 00390 } 00391 00392 #endif // VXL_HAS_INT_64 00393 00394 //: Write to vsl_b_ostream 00395 // Number is saved with ANSI/IEEE Standard 754-1985 single precision. 00396 void vsl_b_write(vsl_b_ostream& os,float n ); 00397 //: Read from vsl_b_istream 00398 void vsl_b_read(vsl_b_istream& is,float& n ); 00399 //: Print to a stream 00400 inline void vsl_print_summary(vcl_ostream& os, float n ) 00401 { os << n; } 00402 00403 //: Write to vsl_b_ostream 00404 // Number is saved with ANSI/IEEE Standard 754-1985 double precision. 00405 void vsl_b_write(vsl_b_ostream& os,double n ); 00406 //: Read from vsl_b_istream 00407 void vsl_b_read(vsl_b_istream& is,double& n ); 00408 //: Print to a stream 00409 inline void vsl_print_summary(vcl_ostream& os, double n ) 00410 { os << n; } 00411 00412 00413 #endif // vsl_binary_io_h_
1.5.1