core/vsl/vsl_binary_explicit_io.h
Go to the documentation of this file.
00001 // This is core/vsl/vsl_binary_explicit_io.h
00002 #ifndef vsl_binary_explicit_io_h_
00003 #define vsl_binary_explicit_io_h_
00004 //:
00005 // \file
00006 // \brief Byte-swapping, arbitrary length integer conversion, and explicit I/O
00007 // \author Ian Scott (Manchester) April 2001
00008 //
00009 // Include this file if you want to perform integer IO using fixed size encoding.
00010 //
00011 // If you want to read or write a large number of floating points, then;
00012 // - Floats and doubles need byte swapped, and this can be done in situ.
00013 // - Shorts, ints and longs need converted to/from the arbitrary length format.
00014 //
00015 // \par Implementation details:
00016 // The arbitrary length encoding takes the number and breaks it into 7 bit
00017 // nibbles. Each nibble is saved with the 8th bit set if this is the last byte.
00018 // The nibbles are stored in little endian order. ie The first byte of the
00019 // encoded format represents the least significant 7 bits.
00020 //
00021 // The algorithm used to encode an unsigned value works as follows
00022 // \verbatim
00023 //  while value is greater than 2^7-1
00024 //    emit 0 bit
00025 //    emit least significant 7 bits of value.
00026 //    shift value right 7 bits
00027 //  emit bit 1
00028 //  emit value embedded in 7 bits
00029 // \endverbatim
00030 
00031 #include <vxl_config.h>
00032 #include <vcl_cassert.h>
00033 #include <vcl_cstring.h>
00034 #include <vcl_cstddef.h>
00035 #include <vcl_iostream.h>
00036 #include "vsl_binary_io.h"
00037 
00038 // Both VXL_LITTLE_ENDIAN && VXL_BIG_ENDIAN should be defined
00039 // One should equal 1 and the other equal 0;
00040 #if VXL_LITTLE_ENDIAN == VXL_BIG_ENDIAN
00041   extern "There is a problem with the ENDIAN indication macros.";
00042 #endif
00043 #if VXL_LITTLE_ENDIAN+VXL_BIG_ENDIAN != 1
00044   extern "There is a problem with the ENDIAN indication macros.";
00045 #endif
00046 
00047 /////////////////////////////////////////////////////////////////////////
00048 
00049 
00050 //: Perform byte swapping in situ
00051 // Where appropriate, swaps pairs of bytes (behaviour is system dependent)
00052 // Apply this function to your floating-point data to convert from system
00053 // format to I/O format. Apply the same function to do the reverse conversion.
00054 //
00055 // \param ptr   The buffer to be byte-swapped.
00056 // \param nbyte The length of the fundamental type, e.g. sizeof(float).
00057 // \param nelem The number of elements in the buffer (default: 1).
00058 //
00059 // The standard I/O format is little-endian. The code assumes that
00060 // your system's floats and doubles are stored in memory in either
00061 // little-endian or big-endian IEEE floating point formats.
00062 //
00063 // Note: There is no point in #ifdef-ing out calls to byte-swapping if you
00064 // are on a little-endian machine. An optimising compiler will inline the
00065 // function to nothing for little-endian machines anyway.
00066 //
00067 // If your computer doesn't use IEEE format reals, then we really should
00068 // redesign the floating point IO.
00069 // Proposed design notes:
00070 // Should do conversion to and from a buffer, rather than in place,
00071 // (since size not known in general)
00072 // double and reals should be converted to IEEE format.
00073 // Someone needs to write a long double format anyway.
00074 // Don't forget to fix all the code that calls vsl_swap_bytes.
00075 // Really should check anything that #includes this file.
00076 
00077 #if VXL_LITTLE_ENDIAN
00078 inline void vsl_swap_bytes(char*, unsigned, vcl_size_t = 1) { return; }
00079 #else
00080 inline void vsl_swap_bytes( char * ptr, unsigned nbyte, vcl_size_t nelem = 1)
00081 {
00082   // If the byte order of the file
00083   // does not match the intel byte order
00084   // then the bytes should be swapped
00085   char temp;
00086   char *ptr1, *ptr2;
00087 
00088   unsigned nbyte2 = nbyte/2;
00089   for (vcl_size_t n = 0; n < nelem; n++ ) {
00090     ptr1 = ptr;
00091     ptr2 = ptr1 + nbyte - 1;
00092     for (unsigned i = 0; i < nbyte2; i++ ) {
00093       temp = *ptr1;
00094       *ptr1++ = *ptr2;
00095       *ptr2-- = temp;
00096     }
00097     ptr += nbyte;
00098   }
00099 }
00100 #endif
00101 
00102 //: Perform byte swapping to a buffer
00103 // Same as vsl_swap_bytes, but saves the results in a buffer.
00104 // In general use vsl_swap_bytes where possible, because it is faster.
00105 inline void vsl_swap_bytes_to_buffer( const char * source, char * dest, unsigned nbyte, vcl_size_t nelem = 1)
00106 {
00107 #if VXL_LITTLE_ENDIAN
00108   vcl_memcpy(dest, source, nbyte * nelem);
00109 #else
00110 
00111   assert(source != dest);
00112 
00113   // If the byte order of the file
00114   // does not match the intel byte order
00115   // then the bytes should be swapped
00116 
00117   const unsigned nbyte_x_2 = nbyte*2;
00118   dest += nbyte - 1;
00119 
00120   for (vcl_size_t n = 0; n < nelem; n++ )
00121   {
00122     for (unsigned i = 0; i < nbyte; i++ )
00123       *dest-- = *source++;
00124 
00125     dest += nbyte_x_2;
00126   }
00127 #endif
00128 }
00129 
00130 /////////////////////////////////////////////////////////////////////////
00131 /////////////////////////////////////////////////////////////////////////
00132 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00133 #define macro( T ) \
00134 inline const char * vsl_type_string(T /*dummy*/) { return #T; }
00135 macro (short);
00136 macro (unsigned short);
00137 macro (int);
00138 macro (unsigned int);
00139 macro (long);
00140 macro (unsigned long);
00141 #if VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG
00142 macro (vxl_int_64);
00143 macro (vxl_uint_64);
00144 #endif
00145 #if 0
00146 // This test will be replaced with !VCL_PTRDIFF_T_IS_A_STANDARD_TYPE
00147 // When that macro is working.
00148 macro(vcl_ptrdiff_t);
00149 macro(vcl_size_t);
00150 #endif
00151 #undef macro
00152 #endif // DOXYGEN_SHOULD_SKIP_THIS
00153 
00154 //: The maximum length of buffer to use with arbitrary length integers
00155 // This macro tells you the size of buffer you need when using
00156 // vsl_convert_ints_to_arbitrary_length().
00157 // You should give the macro the size of the type you want to convert.
00158 // If you are converting several integers at once, multiply the value by
00159 // the number of integers.
00160 #define VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(size_of_type) \
00161   (((size_of_type * 8)/7) + ((((size_of_type * 8) % 7) == 0) ? 0: 1))
00162 
00163 
00164 //: Implement arbitrary length conversion for unsigned integers.
00165 // This function should only be used by this header file.
00166 // Returns the number of bytes written
00167 template <class T>
00168 inline vcl_size_t vsl_convert_to_arbitrary_length_unsigned_impl(
00169   const T* ints, unsigned char *buffer, vcl_size_t count)
00170 {
00171   unsigned char* ptr = buffer;
00172   while (count-- > 0)
00173   {
00174     // The inside of this loop is run once per integer
00175     T v = *(ints++);
00176     while (v > 127)
00177     {
00178       *(ptr++) = (unsigned char)(v & 127);
00179       v >>= 7;
00180     }
00181     *(ptr++) = (unsigned char)(v | 128);
00182   }
00183   return static_cast<vcl_size_t>(ptr - buffer);
00184 }
00185 
00186 
00187 //: Implement arbitrary length conversion for signed integers.
00188 // This function should only be used by this header file.
00189 // Returns the number of bytes written
00190 template <class T>
00191 inline vcl_size_t vsl_convert_to_arbitrary_length_signed_impl(
00192   const T* ints, unsigned char *buffer, vcl_size_t count)
00193 {
00194   unsigned char* ptr = buffer;
00195   while (count-- > 0)
00196   {
00197     // The inside of this loop is run once per integer
00198     T v = *(ints++);
00199     while (v > 63 || v < -64)
00200     {
00201       *(ptr++) = (unsigned char)(v & 127);
00202       v >>= 7;
00203     }
00204     *(ptr++) = (unsigned char)((v & 127) | 128);
00205   }
00206   return static_cast<vcl_size_t>(ptr - buffer);
00207 }
00208 
00209 
00210 //: Implement arbitrary length conversion for signed integers.
00211 // This function should only be used by this header file.
00212 template <class T>
00213 inline vcl_size_t vsl_convert_from_arbitrary_length_signed_impl(
00214   const unsigned char* buffer, T *ints, vcl_size_t count)
00215 {
00216   assert (count != 0);
00217   const unsigned char* ptr = buffer;
00218   while (count-- > 0)
00219   {
00220     // The inside of this loop is run once per integer
00221 
00222     T v = 0; // The value being loaded
00223     unsigned char b= *(ptr++);
00224     int bitsLoaded = 0;
00225     while ((b & 128) == 0)
00226     {
00227       v += ((T)b) << bitsLoaded;
00228       bitsLoaded += 7;
00229       b = *(ptr++);
00230     }
00231 
00232     // At the end of the loop, the last seven bits have not been added
00233     // Now check that number has not and will not overflow
00234     int bitsLeft = sizeof(T)*8 - bitsLoaded;
00235     if (bitsLeft < 7)
00236     {
00237       if (bitsLeft <= 0 ||
00238           b & 64 ?
00239           (((signed char)b >> (bitsLeft-1)) != -1) :
00240           (((b & 127) >> (bitsLeft-1)) != 0)
00241          )
00242       {
00243         vcl_cerr << "\nI/O ERROR: vsl_convert_from_arbitrary_length(.., "
00244                  << vsl_type_string(T()) << "*,..)\n"
00245                  << "has attempted to convert a number that is too large to fit into a "
00246                  << vsl_type_string(T()) << '\n';
00247         return 0;
00248       }
00249     }
00250 
00251     // Now add the last 1<=n<=7 bits.
00252     *(ints++) = v |            // the stuff found before the final 7 bits
00253       ( ((T)(b & 63)) << bitsLoaded) | // the value of the penultimate 6 bits
00254       ( ((T)(b & 64)) ? (-64 << bitsLoaded) : 0); // the value of the final bit.
00255   }
00256   return static_cast<vcl_size_t>(ptr - buffer);
00257 }
00258 
00259 //: Implement arbitrary length conversion for unsigned integers.
00260 // This function should only be used by this header file.
00261 template <class T>
00262 inline vcl_size_t vsl_convert_from_arbitrary_length_unsigned_impl(
00263   const unsigned char* buffer, T *ints, vcl_size_t count = 1)
00264 {
00265   assert (count != 0);
00266   const unsigned char* ptr = buffer;
00267   while (count-- > 0)
00268   {
00269     // The inside of this loop is run once per integer
00270     T v = 0;
00271     unsigned char b = *(ptr++);
00272     int bitsLoaded = 0;
00273     while ((b & 128) == 0)
00274     {
00275       v += ((T)b) << bitsLoaded;
00276       bitsLoaded += 7;
00277       b = *(ptr++);
00278     }
00279 
00280     // At the end of the loop, the last seven bits have not been added
00281     // First check that number has not and will not overflow
00282     int bitsLeft = sizeof(T)*8 - bitsLoaded;
00283     if (bitsLeft < 7)
00284     {
00285       if (bitsLeft <= 0 || ((b & 127) >> bitsLeft) != 0)
00286       {
00287         vcl_cerr << "\nI/O ERROR: vsl_convert_from_arbitrary_length(.., "
00288                  << vsl_type_string(T()) << "*,..)\n"
00289                  << "has attempted to convert a number that is too large to fit into a "
00290                  << vsl_type_string(T()) << '\n';
00291         return 0;
00292       }
00293     }
00294 
00295     // Now add the last 7 bits.
00296     *(ints++) = T(v + ( ((T)(b & 127)) << bitsLoaded));
00297   }
00298   return static_cast<vcl_size_t>(ptr - buffer);
00299 }
00300 
00301 /////////////////////////////////////////////////////////////////////////
00302 
00303 //: Encode an array of ints into an arbitrary length format.
00304 // The return value is the number of bytes used.
00305 // buffer should be at least as long as
00306 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned long)) * count
00307 inline vcl_size_t vsl_convert_to_arbitrary_length(const unsigned long* ints,
00308                                                   unsigned char *buffer,
00309                                                   vcl_size_t count = 1)
00310 {
00311   return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
00312 }
00313 
00314 /////////////////////////////////////////////////////////////////////////
00315 
00316 //: Decode a buffer of arbitrary length integers
00317 // Converts from the integers from the arbitrary length format into
00318 // an array of normal longs.
00319 // \param buffer The buffer to be converted.
00320 // \param count  Number of integers expected. Cannot be zero.
00321 // \param ints   should point to a buffer at least as long as count.
00322 // \return the number of bytes used, or zero on error.
00323 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00324                                                     unsigned long *ints,
00325                                                     vcl_size_t count = 1)
00326 {
00327   return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
00328 }
00329 
00330 
00331 /////////////////////////////////////////////////////////////////////////
00332 
00333 //: Encode an array of ints into an arbitrary length format.
00334 // The return value is the number of bytes used.
00335 // buffer should be at least as long as
00336 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(long)) * count
00337 inline vcl_size_t vsl_convert_to_arbitrary_length(const long* ints,
00338                                                   unsigned char *buffer,
00339                                                   vcl_size_t count = 1)
00340 {
00341   return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
00342 }
00343 
00344 /////////////////////////////////////////////////////////////////////////
00345 
00346 //: Decode a buffer of arbitrary length integers
00347 // Converts from the integers from the arbitrary length format into
00348 // an array of normal longs.
00349 // \param buffer The buffer to be converted.
00350 // \param count  Number of integers expected. Cannot be zero.
00351 // \param ints   should point to a buffer at least as long as count.
00352 // \return the number of bytes used, or zero on error.
00353 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00354                                                     long *ints,
00355                                                     vcl_size_t count = 1)
00356 {
00357   return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
00358 }
00359 
00360 
00361 /////////////////////////////////////////////////////////////////////////
00362 
00363 //: Encode an array of ints into an arbitrary length format.
00364 // The return value is the number of bytes used.
00365 // buffer should be at least as long as
00366 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned int)) * count
00367 inline vcl_size_t vsl_convert_to_arbitrary_length(const unsigned int* ints,
00368                                                   unsigned char *buffer,
00369                                                   vcl_size_t count = 1)
00370 {
00371   return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
00372 }
00373 
00374 
00375 /////////////////////////////////////////////////////////////////////////
00376 
00377 //: Decode a buffer of arbitrary length integers
00378 // Converts from the integers from the arbitrary length format into
00379 // an array of normal ints.
00380 // \param buffer The buffer to be converted.
00381 // \param count  Number of integers expected. Cannot be zero.
00382 // \param ints   should point to a buffer at least as long as count.
00383 // \return the number of bytes used, or zero on error.
00384 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00385                                                     unsigned int *ints,
00386                                                     vcl_size_t count = 1)
00387 {
00388   return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
00389 }
00390 
00391 
00392 /////////////////////////////////////////////////////////////////////////
00393 
00394 //: Encode an array of ints into an arbitrary length format.
00395 // The return value is the number of bytes used.
00396 // buffer should be at least as long as
00397 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(int)) * count
00398 inline vcl_size_t vsl_convert_to_arbitrary_length(const int* ints,
00399                                                   unsigned char *buffer,
00400                                                   vcl_size_t count = 1)
00401 {
00402   return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
00403 }
00404 
00405 
00406 /////////////////////////////////////////////////////////////////////////
00407 
00408 //: Decode a buffer of arbitrary length integers
00409 // Converts from the integers from the arbitrary length format into
00410 // an array of normal ints.
00411 // \param buffer The buffer to be converted.
00412 // \param count  Number of integers expected. Cannot be zero.
00413 // \param ints   should point to a buffer at least as long as count.
00414 // \return the number of bytes used, or zero on error.
00415 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00416                                                     int *ints,
00417                                                     vcl_size_t count = 1)
00418 {
00419   return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
00420 }
00421 
00422 
00423 /////////////////////////////////////////////////////////////////////////
00424 
00425 //: Encode an array of ints into an arbitrary length format.
00426 // The return value is the number of bytes used.
00427 // buffer should be at least as long as
00428 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned short)) * count
00429 inline vcl_size_t vsl_convert_to_arbitrary_length(const unsigned short* ints,
00430                                                   unsigned char *buffer,
00431                                                   vcl_size_t count = 1)
00432 {
00433   return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
00434 }
00435 
00436 
00437 /////////////////////////////////////////////////////////////////////////
00438 
00439 //: Decode a buffer of arbitrary length integers
00440 // Converts from the integers from the arbitrary length format into
00441 // an array of normal ints.
00442 // \param buffer The buffer to be converted.
00443 // \param count  Number of integers expected. Cannot be zero.
00444 // \param ints   should point to a buffer at least as long as count.
00445 // \return the number of bytes used, or zero on error.
00446 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00447                                                     unsigned short *ints,
00448                                                     vcl_size_t count = 1)
00449 {
00450   return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
00451 }
00452 
00453 
00454 /////////////////////////////////////////////////////////////////////////
00455 
00456 //: Encode an array of ints into an arbitrary length format.
00457 // The return value is the number of bytes used.
00458 // buffer should be at least as long as
00459 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(short)) * count
00460 inline vcl_size_t vsl_convert_to_arbitrary_length(const short* ints,
00461                                                   unsigned char *buffer,
00462                                                   vcl_size_t count = 1)
00463 {
00464   return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
00465 }
00466 
00467 
00468 /////////////////////////////////////////////////////////////////////////
00469 
00470 //: Decode a buffer of arbitrary length integers
00471 // Converts from the integers from the arbitrary length format into
00472 // an array of normal ints.
00473 // \param buffer The buffer to be converted.
00474 // \param count  Number of integers expected. Cannot be zero.
00475 // \param ints   should point to a buffer at least as long as count.
00476 // \return the number of bytes used, or zero on error.
00477 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00478                                                     short *ints,
00479                                                     vcl_size_t count = 1)
00480 {
00481   return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
00482 }
00483 
00484 /////////////////////////////////////////////////////////////////////////
00485 
00486 #if VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG
00487 
00488 //: Decode a buffer of arbitrary length integers
00489 // Converts from the integers from the arbitrary length format into
00490 // an array of normal longs.
00491 // \param buffer The buffer to be converted.
00492 // \param count  Number of integers expected. Cannot be zero.
00493 // \param ints   should point to a buffer at least as long as count.
00494 // \return the number of bytes used, or zero on error.
00495 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00496                                                     vxl_uint_64 *ints,
00497                                                     vcl_size_t count = 1)
00498 {
00499   return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
00500 }
00501 
00502 //: Decode a buffer of arbitrary length integers
00503 // Converts from the integers from the arbitrary length format into
00504 // an array of normal longs.
00505 // \param buffer The buffer to be converted.
00506 // \param count  Number of integers expected. Cannot be zero.
00507 // \param ints   should point to a buffer at least as long as count.
00508 // \return the number of bytes used, or zero on error.
00509 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00510                                                     vxl_int_64 *ints,
00511                                                     vcl_size_t count = 1)
00512 {
00513   return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
00514 }
00515 
00516 //: Encode an array of ints into an arbitrary length format.
00517 // The return value is the number of bytes used.
00518 // buffer should be at least as long as
00519 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(long)) * count
00520 inline vcl_size_t vsl_convert_to_arbitrary_length(const vxl_int_64* ints,
00521                                                   unsigned char *buffer,
00522                                                   vcl_size_t count = 1)
00523 {
00524   return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
00525 }
00526 
00527 //: Encode an array of ints into an arbitrary length format.
00528 // The return value is the number of bytes used.
00529 // buffer should be at least as long as
00530 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned long)) * count
00531 inline vcl_size_t vsl_convert_to_arbitrary_length(const vxl_uint_64* ints,
00532                                                   unsigned char *buffer,
00533                                                   vcl_size_t count = 1)
00534 {
00535   return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
00536 }
00537 
00538 #endif // VXL_HAS_INT_64
00539 
00540 /////////////////////////////////////////////////////////////////////////
00541 
00542 #if 0
00543 // This test will be replaced with !VCL_PTRDIFF_T_IS_A_STANDARD_TYPE
00544 // When that macro is working.
00545 
00546 //: Encode an array of ints into an arbitrary length format.
00547 // The return value is the number of bytes used.
00548 // buffer should be at least as long as
00549 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vcl_size_t)) * count
00550 inline vcl_size_t vsl_convert_to_arbitrary_length(const vcl_size_t* ints,
00551                                                   unsigned char *buffer,
00552                                                   vcl_size_t count = 1)
00553 {
00554   return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
00555 }
00556 
00557 
00558 /////////////////////////////////////////////////////////////////////////
00559 
00560 //: Decode a buffer of arbitrary length integers
00561 // Converts from the integers from the arbitrary length format into
00562 // an array of normal ints.
00563 // \param buffer The buffer to be converted.
00564 // \param count  Number of integers expected. Cannot be zero.
00565 // \param ints   should point to a buffer at least as long as count.
00566 // \return the number of bytes used, or zero on error.
00567 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00568                                                     vcl_size_t *ints,
00569                                                     vcl_size_t count = 1)
00570 {
00571   return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
00572 }
00573 
00574 /////////////////////////////////////////////////////////////////////////
00575 
00576 //: Encode an array of ints into an arbitrary length format.
00577 // The return value is the number of bytes used.
00578 // buffer should be at least as long as
00579 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(vcl_ptrdiff_t)) * count
00580 inline vcl_size_t vsl_convert_to_arbitrary_length(const vcl_ptrdiff_t* ints,
00581                                                   unsigned char *buffer,
00582                                                   vcl_size_t count = 1)
00583 {
00584   return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
00585 }
00586 
00587 
00588 /////////////////////////////////////////////////////////////////////////
00589 
00590 //: Decode a buffer of arbitrary length integers
00591 // Converts from the integers from the arbitrary length format into
00592 // an array of normal ints.
00593 // \param buffer The buffer to be converted.
00594 // \param count  Number of integers expected. Cannot be zero.
00595 // \param ints   should point to a buffer at least as long as count.
00596 // \return the number of bytes used, or zero on error.
00597 inline vcl_size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
00598                                                     vcl_ptrdiff_t *ints,
00599                                                     vcl_size_t count = 1)
00600 {
00601   return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
00602 }
00603 #endif // 0
00604 
00605 /////////////////////////////////////////////////////////////////////////
00606 /////////////////////////////////////////////////////////////////////////
00607 
00608 //: Write an unsigned int as 16 bits to vsl_b_ostream
00609 // If your signed int cannot be represented in 16 bits (e.g. on a 32 bit
00610 // platform) the stream's error flag will be set.
00611 //
00612 // Warning: This function should be used infrequently and carefully. Under
00613 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
00614 // vsl_binary_io.h will be perfectly adequate.
00615 //
00616 // You must use vsl_b_read_uint_16() to read the value saved with this
00617 // function.
00618 inline void vsl_b_write_uint_16(vsl_b_ostream& os, unsigned long n )
00619 {
00620   assert(n < (1 << 16));
00621   vsl_swap_bytes(( char* )&n, sizeof(long) );
00622   os.os().write( ( char* )&n, 2 );
00623 }
00624 
00625 //: Read an unsigned int as 16 bits from vsl_b_istream
00626 //
00627 // Warning: This function should be used infrequently and carefully. Under
00628 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
00629 // vsl_binary_io.h will be perfectly adequate.
00630 //
00631 // This function will only read values saved using vsl_b_write_uint_16().
00632 inline void vsl_b_read_uint_16(vsl_b_istream& is, unsigned long& n )
00633 {
00634   n = 0;
00635   is.is().read( ( char* )&n, 2 );
00636   vsl_swap_bytes(( char* )&n, sizeof(long) );
00637 }
00638 
00639 
00640 /////////////////////////////////////////////////////////////////////////
00641 
00642 //: Write a signed int as 16 bits to vsl_b_ostream
00643 // If your signed int cannot be represented in 16 bits (e.g. on a 32 bit
00644 // platform) the stream's error flag will be set.
00645 //
00646 // Warning: This function should be used infrequently and carefully. Under
00647 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
00648 // vsl_binary_io.h will be perfectly adequate.
00649 //
00650 // You must vsl_b_read_int_16() to read the value saved with this function.
00651 inline void vsl_b_write_int_16(vsl_b_ostream& os, long n )
00652 {
00653   assert(n < 32768 && n >= - 32768);
00654   vsl_swap_bytes(( char* )&n, sizeof(long) );
00655   os.os().write( ( char* )&n, 2 );
00656 }
00657 
00658 //: Read a signed int as 16 bits from vsl_b_istream
00659 //
00660 // Warning: This function should be used infrequently and carefully. Under
00661 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
00662 // vsl_binary_io.h will be perfectly adequate.
00663 //
00664 // This function will only read values saved using vsl_b_write_int_16().
00665 inline void vsl_b_read_int_16(vsl_b_istream& is, long& n )
00666 {
00667   is.is().read( ( char* )&n, 2 );
00668   if ((*(((unsigned char*)&n)+1) & 128) == 1)
00669   {
00670     vsl_swap_bytes(( char* )&n, sizeof(long) );
00671     n |= -65536l;
00672   }
00673   else
00674   {
00675     vsl_swap_bytes(( char* )&n, sizeof(long) );
00676     n &= 65535l;
00677   }
00678 }
00679 
00680 
00681 //: Write a vcl_size_t as 64 bits to vsl_b_ostream
00682 // Will assert if your vcl_size_t cannot be represented in 64 bits (e.g. on some 128 bit
00683 // platforms).
00684 //
00685 // Warning: This function should be used infrequently and carefully. Under
00686 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
00687 // vsl_binary_io.h will be perfectly adequate.
00688 //
00689 // You must use vsl_b_read_uint_64() to read the value saved with this
00690 // function.
00691 inline void vsl_b_write_uint_64(vsl_b_ostream& os, vcl_size_t n )
00692 {
00693   assert(sizeof(vcl_size_t) <= 8 || n >> 16 >> 16 >> 16 >> 16 == 0);
00694   vsl_swap_bytes(( char* )&n, sizeof(long) );
00695   os.os().write( ( char* )&n, 8 );
00696 }
00697 
00698 //: Read a vcl_size_t as 64 bits from vsl_b_istream
00699 //
00700 // Warning: This function should be used infrequently and carefully. Under
00701 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
00702 // vsl_binary_io.h will be perfectly adequate.
00703 //
00704 // This function will only read values saved using vsl_b_write_uint_64().
00705 inline void vsl_b_read_uint_64(vsl_b_istream& is, vcl_size_t& n )
00706 {
00707   n = 0;
00708   is.is().read( ( char* )&n, 8 );
00709   vsl_swap_bytes(( char* )&n, sizeof(long) );
00710 }
00711 
00712 
00713 #endif // vsl_binary_explicit_io_h_