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