core/vsl/vsl_binary_io.h

Go to the documentation of this file.
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_

Generated on Sat Sep 6 05:06:03 2008 for core/vsl by  doxygen 1.5.1