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 // \deprecated in favour of vcl_string version. 00288 void vsl_b_write(vsl_b_ostream& os,const char* s ); 00289 //: Read from vsl_b_istream 00290 // \deprecated in favour of vcl_string version. 00291 // \note You must preallocate enough space at \p s for expected length of string. 00292 // This function is easy to crash mith a malformed data file. 00293 void vsl_b_read(vsl_b_istream& is,char* s ); 00294 //: Print to a stream 00295 inline void vsl_print_summary(vcl_ostream& os, const char* s ) 00296 { os << s; } 00297 00298 00299 // Visual Studio .NET on a 32-bit platform can check for 64-bit 00300 // portability issues. When these warnings (/Wp64) are turn on, 00301 // passing a ptrdiff_t as an int triggers a warning. The __w64 00302 // keyword suppresses that warning here, because it's not a problem. 00303 // On a real 64-bit platform, there will presumably be an overloaded 00304 // vsl_b_write for the 64-bit integral type. We don't want to suppress 00305 // the warning (C4244) completely, because it is a useful warning. 00306 // 08/20/2003: Added macro that defines whether or not attribute needs 00307 // to be used. A new version of MS .NET compiler required this change. 00308 // Add compilers as needed. This could be moved to vcl_compiler.h. 00309 // [Nils Krahnstoever] 00310 #ifdef VCL_VC_DOTNET 00311 # define VCL_64BIT_ATTR __w64 00312 #else 00313 # define VCL_64BIT_ATTR /* */ 00314 #endif 00315 00316 //: Write to vsl_b_ostream 00317 void vsl_b_write(vsl_b_ostream& os, int VCL_64BIT_ATTR n ); 00318 //: Read from vsl_b_istream 00319 void vsl_b_read(vsl_b_istream& is, int VCL_64BIT_ATTR &n ); 00320 //: Print to a stream 00321 inline void vsl_print_summary(vcl_ostream& os, int VCL_64BIT_ATTR n ) 00322 { os << int(n); } 00323 00324 #undef VCL_64BIT_ATTR 00325 00326 //: Write to vsl_b_ostream 00327 void vsl_b_write(vsl_b_ostream& os,unsigned int n ); 00328 //: Read from vsl_b_istream 00329 void vsl_b_read(vsl_b_istream& is,unsigned int& n ); 00330 //: Print to a stream 00331 inline void vsl_print_summary(vcl_ostream& os, unsigned int n ) 00332 { os << n; } 00333 00334 //: Write to vsl_b_ostream 00335 void vsl_b_write(vsl_b_ostream& os,short n ); 00336 //: Read from vsl_b_istream 00337 void vsl_b_read(vsl_b_istream& is,short& n ); 00338 //: Print to a stream 00339 inline void vsl_print_summary(vcl_ostream& os, short n ) 00340 { os << n; } 00341 00342 //: Write to vsl_b_ostream 00343 void vsl_b_write(vsl_b_ostream& os,unsigned short n ); 00344 //: Read from vsl_b_istream 00345 void vsl_b_read(vsl_b_istream& is,unsigned short& n ); 00346 //: Print to a stream 00347 inline void vsl_print_summary(vcl_ostream& os, unsigned short n ) 00348 { os << n; } 00349 00350 //: Write to vsl_b_ostream 00351 void vsl_b_write(vsl_b_ostream& os,long n ); 00352 //: Read from vsl_b_istream 00353 void vsl_b_read(vsl_b_istream& is,long& n ); 00354 //: Print to a stream 00355 inline void vsl_print_summary(vcl_ostream& os, long n ) 00356 { os << n; } 00357 00358 //: Write to vsl_b_ostream 00359 void vsl_b_write(vsl_b_ostream& os,unsigned long n ); 00360 //: Read from vsl_b_istream 00361 void vsl_b_read(vsl_b_istream& is,unsigned long& n ); 00362 //: Print to a stream 00363 inline void vsl_print_summary(vcl_ostream& os, unsigned long n ) 00364 { os << n; } 00365 00366 #if VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG 00367 00368 //: Write to vsl_b_ostream 00369 void vsl_b_write(vsl_b_ostream& os,vxl_int_64 n ); 00370 //: Read from vsl_b_istream 00371 void vsl_b_read(vsl_b_istream& is,vxl_int_64& n ); 00372 //: Print to a stream 00373 inline void vsl_print_summary(vcl_ostream& os, vxl_int_64 n ) 00374 { 00375 #if defined(VCL_VC_6) // IMS. This Hack could be replaced by code which 00376 os << "****"; // splits the 64bit int and doesn the right thing. 00377 #else 00378 os << n; 00379 #endif 00380 } 00381 00382 //: Write to vsl_b_ostream 00383 void vsl_b_write(vsl_b_ostream& os,vxl_uint_64 n ); 00384 //: Read from vsl_b_istream 00385 void vsl_b_read(vsl_b_istream& is,vxl_uint_64& n ); 00386 //: Print to a stream 00387 inline void vsl_print_summary(vcl_ostream& os, vxl_uint_64 n ) 00388 { 00389 #if defined(VCL_VC_6) // IMS. This Hack could be replaced by code which 00390 os << "****"; // splits the 64bit int and doesn the right thing. 00391 #else 00392 os << n; 00393 #endif 00394 } 00395 00396 #endif // VXL_HAS_INT_64 00397 00398 //: Write to vsl_b_ostream 00399 // Number is saved with ANSI/IEEE Standard 754-1985 single precision. 00400 void vsl_b_write(vsl_b_ostream& os,float n ); 00401 //: Read from vsl_b_istream 00402 void vsl_b_read(vsl_b_istream& is,float& n ); 00403 //: Print to a stream 00404 inline void vsl_print_summary(vcl_ostream& os, float n ) 00405 { os << n; } 00406 00407 //: Write to vsl_b_ostream 00408 // Number is saved with ANSI/IEEE Standard 754-1985 double precision. 00409 void vsl_b_write(vsl_b_ostream& os,double n ); 00410 //: Read from vsl_b_istream 00411 void vsl_b_read(vsl_b_istream& is,double& n ); 00412 //: Print to a stream 00413 inline void vsl_print_summary(vcl_ostream& os, double n ) 00414 { os << n; } 00415 00416 00417 #endif // vsl_binary_io_h_
1.7.5.1