core/vsl/vsl_binary_io.cxx
Go to the documentation of this file.
00001 // This is core/vsl/vsl_binary_io.cxx
00002 #include "vsl_binary_io.h"
00003 //:
00004 // \file
00005 // \brief Functions to perform consistent binary IO within vsl
00006 // \author Tim Cootes and Ian Scott
00007 
00008 #include <vcl_cstddef.h>
00009 #include <vcl_cassert.h>
00010 #include <vcl_map.txx>
00011 #include <vcl_cstdlib.h> // abort()
00012 #include <vsl/vsl_binary_explicit_io.h>
00013 
00014 void vsl_b_write(vsl_b_ostream& os, char n )
00015 {
00016   os.os().write( ( char* )&n, sizeof( n ) );
00017 }
00018 
00019 void vsl_b_read(vsl_b_istream &is, char& n )
00020 {
00021   is.is().read( ( char* )&n, sizeof( n ) );
00022 }
00023 
00024 void vsl_b_write(vsl_b_ostream& os, signed char n )
00025 {
00026   os.os().write( ( char* )&n, sizeof( n ) );
00027 }
00028 
00029 void vsl_b_read(vsl_b_istream &is, signed char& n )
00030 {
00031   is.is().read( ( char* )&n, sizeof( n ) );
00032 }
00033 
00034 
00035 void vsl_b_write(vsl_b_ostream& os,unsigned char n )
00036 {
00037   os.os().write( ( char* )&n, 1 );
00038 }
00039 
00040 void vsl_b_read(vsl_b_istream &is,unsigned char& n )
00041 {
00042   is.is().read( ( char* )&n, 1 );
00043 }
00044 
00045 
00046 void vsl_b_write(vsl_b_ostream& os, const vcl_string& str )
00047 {
00048     vcl_string::const_iterator          it;
00049 
00050     vsl_b_write(os,(short)str.length());
00051     for ( it = str.begin(); it != str.end(); ++it )
00052         vsl_b_write(os,*it);
00053 }
00054 
00055 void vsl_b_read(vsl_b_istream &is, vcl_string& str )
00056 {
00057     vcl_string::iterator                it;
00058     vcl_string::size_type               length;
00059 
00060     vsl_b_read(is,length);
00061     str.resize( length );
00062     for ( it = str.begin(); it != str.end(); ++it )
00063         vsl_b_read(is,*it);
00064 }
00065 
00066 // deprecated in favour of vcl_string version.
00067 void vsl_b_write(vsl_b_ostream& os,const char *s )
00068 {
00069   int i = -1;
00070   do {
00071      i++;
00072      vsl_b_write(os,s[i]);
00073   } while ( s[i] != 0 );
00074 }
00075 
00076 // deprecated in favour of vcl_string version.
00077 // note You must preallocate enough space at \p s for expected length of string.
00078 // This function is easy to crash mith a malformed data file.
00079 void vsl_b_read(vsl_b_istream &is,char *s )
00080 {
00081   int i = -1;
00082   do {
00083     i++;
00084     vsl_b_read(is,s[i]);
00085   } while ( s[i] != 0 );
00086 }
00087 
00088 
00089 void vsl_b_write(vsl_b_ostream& os,bool b)
00090 {
00091   if (b)
00092     vsl_b_write(os, (signed char) -1);
00093   else
00094     vsl_b_write(os, (signed char) 0);
00095 }
00096 
00097 void vsl_b_read(vsl_b_istream &is,bool& b)
00098 {
00099   signed char c;
00100   vsl_b_read(is, c);
00101   b = (c != 0);
00102 }
00103 
00104 
00105 void vsl_b_write(vsl_b_ostream& os,int n )
00106 {
00107   unsigned char buf[ VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(int)) ];
00108   unsigned long nbytes = (unsigned long)vsl_convert_to_arbitrary_length(&n, buf);
00109   os.os().write((char*)buf, nbytes );
00110 }
00111 
00112 void vsl_b_read(vsl_b_istream &is,int& n )
00113 {
00114   unsigned char buf[VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(int))];
00115   unsigned char *ptr=buf;
00116   do
00117   {
00118     vsl_b_read(is, *ptr);
00119     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(int)))
00120     {
00121       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, int& )\n"
00122                << "           Integer too big. Likely cause either file corruption, or\n"
00123                << "           file was created on platform with larger integer sizes.\n";
00124       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00125       return;
00126     }
00127   }
00128   while (!(*(ptr++) & 128));
00129   vsl_convert_from_arbitrary_length(buf, &n);
00130 }
00131 
00132 
00133 void vsl_b_write(vsl_b_ostream& os,unsigned int n )
00134 {
00135   unsigned char
00136     buf[VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned int))];
00137   unsigned long nbytes = (unsigned long)vsl_convert_to_arbitrary_length(&n, buf);
00138   os.os().write((char*)buf, nbytes );
00139 }
00140 
00141 void vsl_b_read(vsl_b_istream &is,unsigned int& n )
00142 {
00143   unsigned char buf[
00144     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned int))];
00145   unsigned char *ptr=buf;
00146   do
00147   {
00148     vsl_b_read(is, *ptr);
00149     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned int)))
00150     {
00151       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, unsigned int& )\n"
00152                << "           Integer too big. Likely cause either file corruption, or\n"
00153                << "           file was created on platform with larger integer sizes.\n";
00154       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00155       return;
00156     }
00157   }
00158   while (!(*(ptr++) & 128));
00159   vsl_convert_from_arbitrary_length(buf, &n);
00160 }
00161 
00162 
00163 void vsl_b_write(vsl_b_ostream& os,short n )
00164 {
00165   unsigned char buf[VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(short))];
00166   unsigned long nbytes = (unsigned long)vsl_convert_to_arbitrary_length(&n, buf);
00167   os.os().write((char*)buf, nbytes );
00168 }
00169 
00170 void vsl_b_read(vsl_b_istream &is,short& n )
00171 {
00172   unsigned char buf[VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(short))];
00173   unsigned char *ptr=buf;
00174   do
00175   {
00176     vsl_b_read(is, *ptr);
00177 
00178     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(short)))
00179     {
00180       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, short& )\n"
00181                << "           Integer too big. Likely cause either file corruption, or\n"
00182                << "           file was created on platform with larger integer sizes.\n";
00183       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00184       return;
00185     }
00186   }
00187   while (!(*(ptr++) & 128));
00188   vsl_convert_from_arbitrary_length(buf, &n);
00189 }
00190 
00191 void vsl_b_write(vsl_b_ostream& os, unsigned short n )
00192 {
00193   unsigned char buf[
00194     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned short))];
00195   unsigned long nbytes = (unsigned long)vsl_convert_to_arbitrary_length(&n, buf);
00196   os.os().write((char*)buf, nbytes );
00197 }
00198 
00199 void vsl_b_read(vsl_b_istream &is, unsigned short& n )
00200 {
00201   unsigned char buf[
00202     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned short))];
00203   unsigned char *ptr=buf;
00204   do
00205   {
00206     vsl_b_read(is, *ptr);
00207     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned short)))
00208     {
00209       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, unsigned short& )\n"
00210                << "           Integer too big. Likely cause either file corruption, or\n"
00211                << "           file was created on platform with larger integer sizes.\n";
00212       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00213       return;
00214     }
00215   }
00216   while (!(*(ptr++) & 128));
00217   vsl_convert_from_arbitrary_length(buf, &n);
00218 }
00219 
00220 
00221 void vsl_b_write(vsl_b_ostream& os,long n )
00222 {
00223   unsigned char buf[VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(long))];
00224   unsigned long nbytes = (unsigned long)vsl_convert_to_arbitrary_length(&n, buf);
00225   os.os().write((char*)buf, nbytes );
00226 }
00227 
00228 void vsl_b_read(vsl_b_istream &is,long& n )
00229 {
00230   unsigned char buf[VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(long))];
00231   unsigned char *ptr=buf;
00232   do
00233   {
00234     vsl_b_read(is, *ptr);
00235     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(long)))
00236     {
00237       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, long& )\n"
00238                << "           Integer too big. Likely cause either file corruption, or\n"
00239                << "           file was created on platform with larger integer sizes.\n";
00240       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00241       return;
00242     }
00243   }
00244   while (!(*(ptr++) & 128));
00245   vsl_convert_from_arbitrary_length(buf, &n);
00246 }
00247 
00248 void vsl_b_write(vsl_b_ostream& os,unsigned long n )
00249 {
00250   unsigned char buf[
00251     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned long))];
00252   unsigned long nbytes = (unsigned long)vsl_convert_to_arbitrary_length(&n, buf);
00253   os.os().write((char*)buf, nbytes );
00254 }
00255 
00256 void vsl_b_read(vsl_b_istream &is,unsigned long& n )
00257 {
00258   unsigned char buf[
00259     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned long))];
00260   unsigned char *ptr=buf;
00261   do
00262   {
00263     vsl_b_read(is, *ptr);
00264     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned long)))
00265     {
00266       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, unsigned long& )\n"
00267                << "           Integer too big. Likely cause either file corruption, or\n"
00268                << "           file was created on platform with larger integer sizes.\n";
00269       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00270       return;
00271     }
00272   }
00273   while (!(*(ptr++) & 128));
00274   vsl_convert_from_arbitrary_length(buf, &n);
00275 }
00276 
00277 #if VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG
00278 
00279 void vsl_b_write(vsl_b_ostream& os, vxl_int_64 n )
00280 {
00281   unsigned char buf[VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vxl_int_64))];
00282   unsigned long nbytes = (unsigned long)vsl_convert_to_arbitrary_length(&n, buf);
00283   os.os().write((char*)buf, nbytes );
00284 }
00285 
00286 void vsl_b_read(vsl_b_istream &is,vxl_int_64& n )
00287 {
00288   unsigned char buf[VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vxl_int_64))];
00289   unsigned char *ptr=buf;
00290   do
00291   {
00292     vsl_b_read(is, *ptr);
00293     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vxl_int_64)))
00294     {
00295       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, vxl_int_64& )\n"
00296                << "           Integer too big. Likely cause either file corruption, or\n"
00297                << "           file was created on platform with larger integer sizes.\n";
00298       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00299       return;
00300     }
00301   }
00302   while (!(*(ptr++) & 128));
00303   vsl_convert_from_arbitrary_length(buf, &n);
00304 }
00305 
00306 void vsl_b_write(vsl_b_ostream& os, vxl_uint_64 n )
00307 {
00308   unsigned char buf[
00309     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vxl_uint_64))];
00310   unsigned long nbytes = (unsigned long)vsl_convert_to_arbitrary_length(&n, buf);
00311   os.os().write((char*)buf, nbytes );
00312 }
00313 
00314 void vsl_b_read(vsl_b_istream &is,vxl_uint_64& n )
00315 {
00316   unsigned char buf[
00317     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vxl_uint_64))];
00318   unsigned char *ptr=buf;
00319   do
00320   {
00321     vsl_b_read(is, *ptr);
00322     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vxl_uint_64)))
00323     {
00324       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, vxl_uint_64& )\n"
00325                << "           Integer too big. Likely cause either file corruption, or\n"
00326                << "           file was created on platform with larger integer sizes.\n";
00327       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00328       return;
00329     }
00330   }
00331   while (!(*(ptr++) & 128));
00332   vsl_convert_from_arbitrary_length(buf, &n);
00333 }
00334 
00335 #endif // VXL_HAS_INT_64
00336 
00337 #if 0
00338 // When the macro is ready, this test will be
00339 // #if ! VCL_PTRDIFF_T_IS_A_STANDARD_TYPE
00340 
00341 void vsl_b_write(vsl_b_ostream& os, vcl_ptrdiff_t n )
00342 {
00343   unsigned char buf[
00344     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vcl_ptrdiff_t))];
00345   unsigned long nbytes = vsl_convert_to_arbitrary_length(&n, buf);
00346   os.os().write((char*)buf, nbytes );
00347 }
00348 
00349 void vsl_b_read(vsl_b_istream &is, vcl_ptrdiff_t& n )
00350 {
00351   unsigned char buf[
00352     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vcl_ptrdiff_t))];
00353   unsigned char *ptr=buf;
00354   do
00355   {
00356     vsl_b_read(is, *ptr);
00357     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vcl_ptrdiff_t)))
00358     {
00359       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, vcl_ptrdiff_t& )\n"
00360                << "           Integer too big. Likely cause either file corruption, or\n"
00361                << "           file was created on platform with larger integer sizes\n"
00362                << "           and represents a very large data structure.\n";
00363       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00364       return;
00365     }
00366   }
00367   while (!(*(ptr++) & 128));
00368   vsl_convert_from_arbitrary_length(buf, &n);
00369 }
00370 #endif // 0
00371 
00372 #if 0
00373 // When the macro is ready, this test will be
00374 // #if ! VCL_SIZE_T_IS_A_STANDARD_TYPE
00375 
00376 void vsl_b_write(vsl_b_ostream& os, vcl_size_t n )
00377 {
00378   unsigned char buf[
00379     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vcl_size_t))];
00380   unsigned long nbytes = vsl_convert_to_arbitrary_length(&n, buf);
00381   os.os().write((char*)buf, nbytes );
00382 }
00383 
00384 void vsl_b_read(vsl_b_istream &is, vcl_size_t& n )
00385 {
00386   unsigned char buf[
00387     VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vcl_size_t))];
00388   unsigned char *ptr=buf;
00389   do
00390   {
00391     vsl_b_read(is, *ptr);
00392     if (ptr-buf >= (vcl_ptrdiff_t)VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vcl_size_t)))
00393     {
00394       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream &, vcl_size_t& )\n"
00395                << "           Integer too big. Likely cause either file corruption, or\n"
00396                << "           file was created on platform with larger integer sizes\n"
00397                << "           and represents a very large data structure.\n";
00398       is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00399       return;
00400     }
00401   }
00402   while (!(*(ptr++) & 128));
00403   vsl_convert_from_arbitrary_length(buf, &n);
00404 }
00405 #endif // 0
00406 
00407 
00408 void vsl_b_write(vsl_b_ostream& os,float n )
00409 {
00410   vsl_swap_bytes(( char* )&n, sizeof( n ) );
00411   os.os().write( ( char* )&n, sizeof( n ) );
00412 }
00413 
00414 void vsl_b_read(vsl_b_istream &is,float& n )
00415 {
00416   is.is().read( ( char* )&n, sizeof( n ) );
00417   vsl_swap_bytes(( char* )&n, sizeof( n ) );
00418 }
00419 
00420 void vsl_b_write(vsl_b_ostream& os,double n )
00421 {
00422   vsl_swap_bytes(( char* )&n, sizeof( n ) );
00423   os.os().write( ( char* )&n, sizeof( n ) );
00424 }
00425 
00426 void vsl_b_read(vsl_b_istream &is,double& n )
00427 {
00428   is.is().read( ( char* )&n, sizeof( n ) );
00429   vsl_swap_bytes(( char* )&n, sizeof( n ) );
00430 }
00431 
00432 
00433 const unsigned short vsl_b_ostream::version_no_ = 1;
00434 const vcl_streamoff vsl_b_ostream::header_length = 6;
00435 static const unsigned short vsl_magic_number_part_1=0x2c4e;
00436 static const unsigned short vsl_magic_number_part_2=0x472b;
00437 
00438 
00439 //: Create this adaptor using an existing stream
00440 // The stream (os) must be open (i.e. ready to be written to) so that the
00441 // IO version number can be written by this constructor.
00442 // User is responsible for deleting os after deleting the adaptor
00443 vsl_b_ostream::vsl_b_ostream(vcl_ostream *o_s): os_(o_s)
00444 {
00445   assert(os_ != 0);
00446   vsl_b_write_uint_16(*this, version_no_);
00447   vsl_b_write_uint_16(*this, vsl_magic_number_part_1);
00448   vsl_b_write_uint_16(*this, vsl_magic_number_part_2);
00449 }
00450 
00451 //: A reference to the adaptor's stream
00452 vcl_ostream& vsl_b_ostream::os() const
00453 {
00454   assert(os_ != 0);
00455   return *os_;
00456 }
00457 
00458 //: Returns true if the underlying stream has its fail bit set.
00459 bool vsl_b_ostream::operator!() const
00460 {
00461   return os_->operator!();
00462 }
00463 
00464 
00465 //: Clear the stream's record of any serialisation operations
00466 // Calling this function while outputting serialisable things to stream,
00467 // will mean that a second copy of an object may get stored to the stream.
00468 void vsl_b_ostream::clear_serialisation_records()
00469 {
00470   serialisation_records_.clear();
00471 }
00472 
00473 
00474 //: Adds an object pointer to the serialisation records.
00475 // Returns a unique identifier for the object.
00476 //
00477 // \a pointer must be non-null, so you should handle null pointers separately.
00478 //
00479 // You can optionally add some user-defined integer with each record
00480 // If error checking is on, and the object pointer is null or already in the records,
00481 // this function will abort()
00482 unsigned long vsl_b_ostream::add_serialisation_record
00483                     (void *pointer, int other_data /*= 0*/)
00484 {
00485   assert(pointer != 0);
00486   assert(serialisation_records_.find(pointer) == serialisation_records_.end());
00487   unsigned long id = (unsigned long)serialisation_records_.size() + 1;
00488   serialisation_records_[pointer] = vcl_make_pair(id, other_data);
00489   return id;
00490 }
00491 
00492 
00493 //: Returns a unique identifier for the object.
00494 // Returns 0 if there is no record of the object.
00495 unsigned long vsl_b_ostream::get_serial_number(void *pointer) const
00496 {
00497   serialisation_records_type::const_iterator entry =
00498     serialisation_records_.find(pointer);
00499   if (entry == serialisation_records_.end())
00500   {
00501     return 0;
00502   }
00503   else
00504   {
00505     return (*entry).second.first;
00506   }
00507 }
00508 
00509 //: Set the user-defined data associated with the object
00510 // If there is no record of the object, this function will return 0.
00511 // However a retval of 0 does not necessarily imply that the object is
00512 // unrecorded.
00513 int vsl_b_ostream::get_serialisation_other_data(void *pointer) const
00514 {
00515   serialisation_records_type::const_iterator entry =
00516     serialisation_records_.find(pointer);
00517   if (entry == serialisation_records_.end())
00518   {
00519     return 0;
00520   }
00521   else
00522   {
00523     return (*entry).second.second;
00524   }
00525 }
00526 
00527 //: Modify the user-defined data associated with the object.
00528 // If there is no record of the object, this function will abort.
00529 int vsl_b_ostream::set_serialisation_other_data
00530     (void *pointer, int /*other_data*/)
00531 {
00532   serialisation_records_type::iterator entry =
00533     serialisation_records_.find(pointer);
00534   if (entry == serialisation_records_.end())
00535   {
00536     vcl_cerr << "vsl_b_ostream::set_serialisation_other_data():\n"
00537              << "No such value " << pointer << "in records.\n";
00538     vcl_abort();
00539   }
00540   return (*entry).second.second;
00541 }
00542 
00543 
00544 //: destructor.
00545 vsl_b_ofstream::~vsl_b_ofstream()
00546 {
00547   if (os_) delete os_;
00548 }
00549 
00550 
00551 //: Close the stream
00552 void vsl_b_ofstream::close()
00553 {
00554   assert(os_ != 0);
00555   ((vcl_ofstream *)os_)->close();
00556   clear_serialisation_records();
00557 }
00558 
00559 //: Create this adaptor using an existing stream.
00560 // The stream (is) must be open (i.e. ready to be read from) so that the
00561 // IO version number can be read by this constructor.
00562 // User is responsible for deleting is after deleting the adaptor
00563 vsl_b_istream::vsl_b_istream(vcl_istream *i_s): is_(i_s)
00564 {
00565   assert(is_ != 0);
00566   if (!(*is_)) return;
00567   unsigned long v, m1, m2;
00568   vsl_b_read_uint_16(*this, v);
00569   vsl_b_read_uint_16(*this, m1);
00570   vsl_b_read_uint_16(*this, m2);
00571 
00572   // If this test fails, either the file is missing, or it is not a
00573   // Binary VXL file, or it is a corrupted Binary VXL file
00574   if (m2 != vsl_magic_number_part_2 || m1 != vsl_magic_number_part_1)
00575   {
00576     vcl_cerr << "\nI/O ERROR: vsl_b_istream::vsl_b_istream(vcl_istream *is)\n"
00577              <<   "           The input stream does not appear to be a binary VXL stream.\n"
00578              <<   "           Can't find correct magic number.\n";
00579     is_->clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00580   }
00581 
00582   if (v != 1)
00583   {
00584     vcl_cerr << "\nI/O ERROR: vsl_b_istream::vsl_b_istream(vcl_istream *is)\n"
00585              << "             The stream's leading version number is "
00586              << v << ". Expected value 1.\n";
00587     is_->clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00588   }
00589   version_no_ = (unsigned short)v;
00590 }
00591 
00592 //: A reference to the adaptor's stream
00593 vcl_istream & vsl_b_istream::is() const
00594 {
00595   assert(is_ != 0);
00596   return *is_;
00597 }
00598 
00599 
00600 //: Return the version number of the IO format of the file being read.
00601 unsigned short vsl_b_istream::version_no() const
00602 {
00603   return version_no_;
00604 }
00605 
00606 //: Returns true if the underlying stream has its fail bit set.
00607 bool vsl_b_istream::operator!() const
00608 {
00609   return is_->operator!();
00610 }
00611 
00612 //: Clear the stream's record of any serialisation operations
00613 // Calling this function while inputting serialisable things from a stream,
00614 // could cause errors during loading unless the records were cleared at a
00615 // similar point during output.
00616 void vsl_b_istream::clear_serialisation_records()
00617 {
00618   serialisation_records_.clear();
00619 }
00620 
00621 //: Adds record of object's unique serial number, and location in memory.
00622 // \a pointer must be non-null, so you should handle null pointers separately.
00623 //
00624 // Adding a null pointer or one that already exists will cause the function to abort(),
00625 // if debugging is turned on;
00626 //
00627 // You can also store a single integer as other data.
00628 // Interpretation of this data is entirely up to the client code.
00629 void vsl_b_istream::add_serialisation_record(unsigned long serial_number,
00630                                              void *pointer, int other_data /*= 0*/)
00631 {
00632   assert(pointer != 0);
00633   assert(serialisation_records_.find(serial_number) == serialisation_records_.end());
00634   serialisation_records_[serial_number] = vcl_make_pair(pointer, other_data);
00635 }
00636 
00637 //: Returns the pointer to the object identified by the unique serial number.
00638 // Returns 0 if no record has been added.
00639 void* vsl_b_istream::get_serialisation_pointer(unsigned long serial_number) const
00640 {
00641   serialisation_records_type::const_iterator entry =
00642         serialisation_records_.find(serial_number);
00643   if (entry == serialisation_records_.end())
00644   {
00645     return 0;
00646   }
00647   else
00648   {
00649     return (*entry).second.first;
00650   }
00651 }
00652 
00653 //: Returns the user defined data associated with the unique serial number
00654 // Returns 0 if no record has been added.
00655 int vsl_b_istream::get_serialisation_other_data
00656     (unsigned long serial_number) const
00657 {
00658   serialisation_records_type::const_iterator entry =
00659     serialisation_records_.find(serial_number);
00660   if (entry == serialisation_records_.end())
00661   {
00662     return 0;
00663   }
00664   else
00665   {
00666     return (*entry).second.second;
00667   }
00668 }
00669 
00670 //: Modify the user-defined data associated with the unique serial number
00671 // If there is no record of the object, this function will  abort.
00672 int vsl_b_istream::set_serialisation_other_data
00673     (unsigned long serial_number, int /*other_data*/)
00674 {
00675   serialisation_records_type::const_iterator entry =
00676     serialisation_records_.find(serial_number);
00677   if (entry == serialisation_records_.end())
00678   {
00679     vcl_cerr << "vsl_b_istream::set_serialisation_other_data():\n"
00680              << "  No such value " << serial_number << "in records.\n";
00681     vcl_abort();
00682   }
00683   return (*entry).second.second;
00684 }
00685 
00686 
00687 //: destructor.so that it can be overloaded
00688 vsl_b_ifstream::~vsl_b_ifstream()
00689 {
00690   if (is_) delete is_;
00691 }
00692 
00693 //: Close the stream
00694 void vsl_b_ifstream::close()
00695 {
00696   assert(is_ != 0);
00697   ((vcl_ifstream *)is_)->close();
00698   clear_serialisation_records();
00699 }