vsl_binary_explicit_io.h
Go to the documentation of this file.
1 // This is core/vsl/vsl_binary_explicit_io.h
2 #ifndef vsl_binary_explicit_io_h_
3 #define vsl_binary_explicit_io_h_
4 //:
5 // \file
6 // \brief Byte-swapping, arbitrary length integer conversion, and explicit I/O
7 // \author Ian Scott (Manchester) April 2001
8 //
9 // Include this file if you want to perform integer IO using fixed size encoding.
10 //
11 // If you want to read or write a large number of floating points, then;
12 // - Floats and doubles need byte swapped, and this can be done in situ.
13 // - Shorts, ints and longs need converted to/from the arbitrary length format.
14 //
15 // \par Implementation details:
16 // The arbitrary length encoding takes the number and breaks it into 7 bit
17 // nibbles. Each nibble is saved with the 8th bit set if this is the last byte.
18 // The nibbles are stored in little endian order. ie The first byte of the
19 // encoded format represents the least significant 7 bits.
20 //
21 // The algorithm used to encode an unsigned value works as follows
22 // \verbatim
23 // while value is greater than 2^7-1
24 // emit 0 bit
25 // emit least significant 7 bits of value.
26 // shift value right 7 bits
27 // emit bit 1
28 // emit value embedded in 7 bits
29 // \endverbatim
30 
31 #include <cstring>
32 #include <cstddef>
33 #include <iostream>
34 #include <vxl_config.h>
35 #include <cassert>
36 #ifdef _MSC_VER
37 # include <vcl_msvc_warnings.h>
38 #endif
39 #include "vsl_binary_io.h"
40 
41 // Both VXL_LITTLE_ENDIAN && VXL_BIG_ENDIAN should be defined
42 // One should equal 1 and the other equal 0;
43 #if VXL_LITTLE_ENDIAN == VXL_BIG_ENDIAN
44  extern "There is a problem with the ENDIAN indication macros.";
45 #endif
46 #if VXL_LITTLE_ENDIAN+VXL_BIG_ENDIAN != 1
47  extern "There is a problem with the ENDIAN indication macros.";
48 #endif
49 
50 /////////////////////////////////////////////////////////////////////////
51 
52 
53 //: Perform byte swapping in situ
54 // Where appropriate, swaps pairs of bytes (behaviour is system dependent)
55 // Apply this function to your floating-point data to convert from system
56 // format to I/O format. Apply the same function to do the reverse conversion.
57 //
58 // \param ptr The buffer to be byte-swapped.
59 // \param nbyte The length of the fundamental type, e.g. sizeof(float).
60 // \param nelem The number of elements in the buffer (default: 1).
61 //
62 // The standard I/O format is little-endian. The code assumes that
63 // your system's floats and doubles are stored in memory in either
64 // little-endian or big-endian IEEE floating point formats.
65 //
66 // Note: There is no point in #ifdef-ing out calls to byte-swapping if you
67 // are on a little-endian machine. An optimising compiler will inline the
68 // function to nothing for little-endian machines anyway.
69 //
70 // If your computer doesn't use IEEE format reals, then we really should
71 // redesign the floating point IO.
72 // Proposed design notes:
73 // Should do conversion to and from a buffer, rather than in place,
74 // (since size not known in general)
75 // double and reals should be converted to IEEE format.
76 // Someone needs to write a long double format anyway.
77 // Don't forget to fix all the code that calls vsl_swap_bytes.
78 // Really should check anything that #includes this file.
79 
80 #if VXL_LITTLE_ENDIAN
81 inline void vsl_swap_bytes(char*, unsigned, std::size_t = 1) { return; }
82 #else
83 inline void vsl_swap_bytes( char * ptr, unsigned nbyte, std::size_t nelem = 1)
84 {
85  // If the byte order of the file
86  // does not match the intel byte order
87  // then the bytes should be swapped
88  char temp;
89  char *ptr1, *ptr2;
90 
91  unsigned nbyte2 = nbyte/2;
92  for (std::size_t n = 0; n < nelem; n++ ) {
93  ptr1 = ptr;
94  ptr2 = ptr1 + nbyte - 1;
95  for (unsigned i = 0; i < nbyte2; i++ ) {
96  temp = *ptr1;
97  *ptr1++ = *ptr2;
98  *ptr2-- = temp;
99  }
100  ptr += nbyte;
101  }
102 }
103 #endif
104 
105 //: Perform byte swapping to a buffer
106 // Same as vsl_swap_bytes, but saves the results in a buffer.
107 // In general use vsl_swap_bytes where possible, because it is faster.
108 inline void vsl_swap_bytes_to_buffer( const char * source, char * dest, unsigned nbyte, std::size_t nelem = 1)
109 {
110 #if VXL_LITTLE_ENDIAN
111  std::memcpy(dest, source, nbyte * nelem);
112 #else
113 
114  assert(source != dest);
115 
116  // If the byte order of the file
117  // does not match the intel byte order
118  // then the bytes should be swapped
119 
120  const unsigned nbyte_x_2 = nbyte*2;
121  dest += nbyte - 1;
122 
123  for (std::size_t n = 0; n < nelem; n++ )
124  {
125  for (unsigned i = 0; i < nbyte; i++ )
126  *dest-- = *source++;
127 
128  dest += nbyte_x_2;
129  }
130 #endif
131 }
132 
133 /////////////////////////////////////////////////////////////////////////
134 /////////////////////////////////////////////////////////////////////////
135 #ifndef DOXYGEN_SHOULD_SKIP_THIS
136 #define macro( T ) \
137 inline const char * vsl_type_string(T /*dummy*/) { return #T; }
138 macro (short);
139 macro (unsigned short);
140 macro (int);
141 macro (unsigned int);
142 macro (long);
143 macro (unsigned long);
144 #if VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG
145 macro (vxl_int_64);
146 macro (vxl_uint_64);
147 #endif
148 #if 0
149 // This test will be replaced with !VCL_PTRDIFF_T_IS_A_STANDARD_TYPE
150 // When that macro is working.
151 macro(std::ptrdiff_t);
152 macro(std::size_t);
153 #endif
154 #undef macro
155 #endif // DOXYGEN_SHOULD_SKIP_THIS
156 
157 //: The maximum length of buffer to use with arbitrary length integers
158 // This macro tells you the size of buffer you need when using
159 // vsl_convert_ints_to_arbitrary_length().
160 // You should give the macro the size of the type you want to convert.
161 // If you are converting several integers at once, multiply the value by
162 // the number of integers.
163 #define VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(size_of_type) \
164  ((((size_of_type) * 8)/7) + (((((size_of_type) * 8) % 7) == 0) ? 0: 1))
165 
166 
167 //: Implement arbitrary length conversion for unsigned integers.
168 // This function should only be used by this header file.
169 // Returns the number of bytes written
170 template <class T>
172  const T* ints, unsigned char *buffer, std::size_t count)
173 {
174  unsigned char* ptr = buffer;
175  while (count-- > 0)
176  {
177  // The inside of this loop is run once per integer
178  T v = *(ints++);
179  while (v > 127)
180  {
181  *(ptr++) = (unsigned char)(v & 127);
182  v >>= 7;
183  }
184  *(ptr++) = (unsigned char)(v | 128);
185  }
186  return static_cast<std::size_t>(ptr - buffer);
187 }
188 
189 
190 //: Implement arbitrary length conversion for signed integers.
191 // This function should only be used by this header file.
192 // Returns the number of bytes written
193 template <class T>
195  const T* ints, unsigned char *buffer, std::size_t count)
196 {
197  unsigned char* ptr = buffer;
198  while (count-- > 0)
199  {
200  // The inside of this loop is run once per integer
201  T v = *(ints++);
202  while (v > 63 || v < -64)
203  {
204  *(ptr++) = (unsigned char)(v & 127);
205  v >>= 7;
206  }
207  *(ptr++) = (unsigned char)((v & 127) | 128);
208  }
209  return static_cast<std::size_t>(ptr - buffer);
210 }
211 
212 
213 //: Implement arbitrary length conversion for signed integers.
214 // This function should only be used by this header file.
215 template <class T>
217  const unsigned char* buffer, T *ints, std::size_t count)
218 {
219  assert (count != 0);
220  const unsigned char* ptr = buffer;
221  while (count-- > 0)
222  {
223  // The inside of this loop is run once per integer
224 
225  T v = 0; // The value being loaded
226  unsigned char b= *(ptr++);
227  int bitsLoaded = 0;
228  while ((b & 128) == 0)
229  {
230  v += ((T)b) << bitsLoaded;
231  bitsLoaded += 7;
232  b = *(ptr++);
233  }
234 
235  // At the end of the loop, the last seven bits have not been added
236  // Now check that number has not and will not overflow
237  int bitsLeft = sizeof(T)*8 - bitsLoaded;
238  if (bitsLeft < 7)
239  {
240  if (bitsLeft <= 0 ||
241  b & 64 ?
242  (((signed char)b >> (bitsLeft-1)) != -1) :
243  (((b & 127) >> (bitsLeft-1)) != 0)
244  )
245  {
246  std::cerr << "\nI/O ERROR: vsl_convert_from_arbitrary_length(.., "
247  << vsl_type_string(T()) << "*,..)\n"
248  << "has attempted to convert a number that is too large to fit into a "
249  << vsl_type_string(T()) << '\n';
250  return 0;
251  }
252  }
253 
254  // Now add the last 1<=n<=7 bits.
255  *(ints++) = v | // the stuff found before the final 7 bits
256  ( ((T)(b & 63)) << bitsLoaded) | // the value of the penultimate 6 bits
257  ( ((T)(b & 64)) ? (-64 << bitsLoaded) : 0); // the value of the final bit.
258  }
259  return static_cast<std::size_t>(ptr - buffer);
260 }
261 
262 //: Implement arbitrary length conversion for unsigned integers.
263 // This function should only be used by this header file.
264 template <class T>
266  const unsigned char* buffer, T *ints, std::size_t count = 1)
267 {
268  assert (count != 0);
269  const unsigned char* ptr = buffer;
270  while (count-- > 0)
271  {
272  // The inside of this loop is run once per integer
273  T v = 0;
274  unsigned char b = *(ptr++);
275  int bitsLoaded = 0;
276  while ((b & 128) == 0)
277  {
278  v += ((T)b) << bitsLoaded;
279  bitsLoaded += 7;
280  b = *(ptr++);
281  }
282 
283  // At the end of the loop, the last seven bits have not been added
284  // First check that number has not and will not overflow
285  int bitsLeft = sizeof(T)*8 - bitsLoaded;
286  if (bitsLeft < 7)
287  {
288  if (bitsLeft <= 0 || ((b & 127) >> bitsLeft) != 0)
289  {
290  std::cerr << "\nI/O ERROR: vsl_convert_from_arbitrary_length(.., "
291  << vsl_type_string(T()) << "*,..)\n"
292  << "has attempted to convert a number that is too large to fit into a "
293  << vsl_type_string(T()) << '\n';
294  return 0;
295  }
296  }
297 
298  // Now add the last 7 bits.
299  *(ints++) = T(v + ( ((T)(b & 127)) << bitsLoaded));
300  }
301  return static_cast<std::size_t>(ptr - buffer);
302 }
303 
304 /////////////////////////////////////////////////////////////////////////
305 
306 //: Encode an array of ints into an arbitrary length format.
307 // The return value is the number of bytes used.
308 // buffer should be at least as long as
309 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned long)) * count
310 inline std::size_t vsl_convert_to_arbitrary_length(const unsigned long* ints,
311  unsigned char *buffer,
312  std::size_t count = 1)
313 {
314  return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
315 }
316 
317 /////////////////////////////////////////////////////////////////////////
318 
319 //: Decode a buffer of arbitrary length integers
320 // Converts from the integers from the arbitrary length format into
321 // an array of normal longs.
322 // \param buffer The buffer to be converted.
323 // \param count Number of integers expected. Cannot be zero.
324 // \param ints should point to a buffer at least as long as count.
325 // \return the number of bytes used, or zero on error.
326 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
327  unsigned long *ints,
328  std::size_t count = 1)
329 {
330  return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
331 }
332 
333 
334 /////////////////////////////////////////////////////////////////////////
335 
336 //: Encode an array of ints into an arbitrary length format.
337 // The return value is the number of bytes used.
338 // buffer should be at least as long as
339 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(long)) * count
340 inline std::size_t vsl_convert_to_arbitrary_length(const long* ints,
341  unsigned char *buffer,
342  std::size_t count = 1)
343 {
344  return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
345 }
346 
347 /////////////////////////////////////////////////////////////////////////
348 
349 //: Decode a buffer of arbitrary length integers
350 // Converts from the integers from the arbitrary length format into
351 // an array of normal longs.
352 // \param buffer The buffer to be converted.
353 // \param count Number of integers expected. Cannot be zero.
354 // \param ints should point to a buffer at least as long as count.
355 // \return the number of bytes used, or zero on error.
356 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
357  long *ints,
358  std::size_t count = 1)
359 {
360  return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
361 }
362 
363 
364 /////////////////////////////////////////////////////////////////////////
365 
366 //: Encode an array of ints into an arbitrary length format.
367 // The return value is the number of bytes used.
368 // buffer should be at least as long as
369 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned int)) * count
370 inline std::size_t vsl_convert_to_arbitrary_length(const unsigned int* ints,
371  unsigned char *buffer,
372  std::size_t count = 1)
373 {
374  return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
375 }
376 
377 
378 /////////////////////////////////////////////////////////////////////////
379 
380 //: Decode a buffer of arbitrary length integers
381 // Converts from the integers from the arbitrary length format into
382 // an array of normal ints.
383 // \param buffer The buffer to be converted.
384 // \param count Number of integers expected. Cannot be zero.
385 // \param ints should point to a buffer at least as long as count.
386 // \return the number of bytes used, or zero on error.
387 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
388  unsigned int *ints,
389  std::size_t count = 1)
390 {
391  return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
392 }
393 
394 
395 /////////////////////////////////////////////////////////////////////////
396 
397 //: Encode an array of ints into an arbitrary length format.
398 // The return value is the number of bytes used.
399 // buffer should be at least as long as
400 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(int)) * count
401 inline std::size_t vsl_convert_to_arbitrary_length(const int* ints,
402  unsigned char *buffer,
403  std::size_t count = 1)
404 {
405  return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
406 }
407 
408 
409 /////////////////////////////////////////////////////////////////////////
410 
411 //: Decode a buffer of arbitrary length integers
412 // Converts from the integers from the arbitrary length format into
413 // an array of normal ints.
414 // \param buffer The buffer to be converted.
415 // \param count Number of integers expected. Cannot be zero.
416 // \param ints should point to a buffer at least as long as count.
417 // \return the number of bytes used, or zero on error.
418 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
419  int *ints,
420  std::size_t count = 1)
421 {
422  return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
423 }
424 
425 
426 /////////////////////////////////////////////////////////////////////////
427 
428 //: Encode an array of ints into an arbitrary length format.
429 // The return value is the number of bytes used.
430 // buffer should be at least as long as
431 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned short)) * count
432 inline std::size_t vsl_convert_to_arbitrary_length(const unsigned short* ints,
433  unsigned char *buffer,
434  std::size_t count = 1)
435 {
436  return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
437 }
438 
439 
440 /////////////////////////////////////////////////////////////////////////
441 
442 //: Decode a buffer of arbitrary length integers
443 // Converts from the integers from the arbitrary length format into
444 // an array of normal ints.
445 // \param buffer The buffer to be converted.
446 // \param count Number of integers expected. Cannot be zero.
447 // \param ints should point to a buffer at least as long as count.
448 // \return the number of bytes used, or zero on error.
449 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
450  unsigned short *ints,
451  std::size_t count = 1)
452 {
453  return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
454 }
455 
456 
457 /////////////////////////////////////////////////////////////////////////
458 
459 //: Encode an array of ints into an arbitrary length format.
460 // The return value is the number of bytes used.
461 // buffer should be at least as long as
462 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(short)) * count
463 inline std::size_t vsl_convert_to_arbitrary_length(const short* ints,
464  unsigned char *buffer,
465  std::size_t count = 1)
466 {
467  return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
468 }
469 
470 
471 /////////////////////////////////////////////////////////////////////////
472 
473 //: Decode a buffer of arbitrary length integers
474 // Converts from the integers from the arbitrary length format into
475 // an array of normal ints.
476 // \param buffer The buffer to be converted.
477 // \param count Number of integers expected. Cannot be zero.
478 // \param ints should point to a buffer at least as long as count.
479 // \return the number of bytes used, or zero on error.
480 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
481  short *ints,
482  std::size_t count = 1)
483 {
484  return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
485 }
486 
487 /////////////////////////////////////////////////////////////////////////
488 
489 #if VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG
490 
491 //: Decode a buffer of arbitrary length integers
492 // Converts from the integers from the arbitrary length format into
493 // an array of normal longs.
494 // \param buffer The buffer to be converted.
495 // \param count Number of integers expected. Cannot be zero.
496 // \param ints should point to a buffer at least as long as count.
497 // \return the number of bytes used, or zero on error.
498 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
499  vxl_uint_64 *ints,
500  std::size_t count = 1)
501 {
502  return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
503 }
504 
505 //: Decode a buffer of arbitrary length integers
506 // Converts from the integers from the arbitrary length format into
507 // an array of normal longs.
508 // \param buffer The buffer to be converted.
509 // \param count Number of integers expected. Cannot be zero.
510 // \param ints should point to a buffer at least as long as count.
511 // \return the number of bytes used, or zero on error.
512 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
513  vxl_int_64 *ints,
514  std::size_t count = 1)
515 {
516  return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
517 }
518 
519 //: Encode an array of ints into an arbitrary length format.
520 // The return value is the number of bytes used.
521 // buffer should be at least as long as
522 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(long)) * count
523 inline std::size_t vsl_convert_to_arbitrary_length(const vxl_int_64* ints,
524  unsigned char *buffer,
525  std::size_t count = 1)
526 {
527  return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
528 }
529 
530 //: Encode an array of ints into an arbitrary length format.
531 // The return value is the number of bytes used.
532 // buffer should be at least as long as
533 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(unsigned long)) * count
534 inline std::size_t vsl_convert_to_arbitrary_length(const vxl_uint_64* ints,
535  unsigned char *buffer,
536  std::size_t count = 1)
537 {
538  return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
539 }
540 
541 #endif // VXL_HAS_INT_64
542 
543 /////////////////////////////////////////////////////////////////////////
544 
545 #if 0
546 // This test will be replaced with !VCL_PTRDIFF_T_IS_A_STANDARD_TYPE
547 // When that macro is working.
548 
549 //: Encode an array of ints into an arbitrary length format.
550 // The return value is the number of bytes used.
551 // buffer should be at least as long as
552 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(std::size_t)) * count
553 inline std::size_t vsl_convert_to_arbitrary_length(const std::size_t* ints,
554  unsigned char *buffer,
555  std::size_t count = 1)
556 {
557  return vsl_convert_to_arbitrary_length_unsigned_impl(ints, buffer, count);
558 }
559 
560 
561 /////////////////////////////////////////////////////////////////////////
562 
563 //: Decode a buffer of arbitrary length integers
564 // Converts from the integers from the arbitrary length format into
565 // an array of normal ints.
566 // \param buffer The buffer to be converted.
567 // \param count Number of integers expected. Cannot be zero.
568 // \param ints should point to a buffer at least as long as count.
569 // \return the number of bytes used, or zero on error.
570 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
571  std::size_t *ints,
572  std::size_t count = 1)
573 {
574  return vsl_convert_from_arbitrary_length_unsigned_impl(buffer, ints, count);
575 }
576 
577 /////////////////////////////////////////////////////////////////////////
578 
579 //: Encode an array of ints into an arbitrary length format.
580 // The return value is the number of bytes used.
581 // buffer should be at least as long as
582 // VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(std::ptrdiff_t)) * count
583 inline std::size_t vsl_convert_to_arbitrary_length(const std::ptrdiff_t* ints,
584  unsigned char *buffer,
585  std::size_t count = 1)
586 {
587  return vsl_convert_to_arbitrary_length_signed_impl(ints, buffer, count);
588 }
589 
590 
591 /////////////////////////////////////////////////////////////////////////
592 
593 //: Decode a buffer of arbitrary length integers
594 // Converts from the integers from the arbitrary length format into
595 // an array of normal ints.
596 // \param buffer The buffer to be converted.
597 // \param count Number of integers expected. Cannot be zero.
598 // \param ints should point to a buffer at least as long as count.
599 // \return the number of bytes used, or zero on error.
600 inline std::size_t vsl_convert_from_arbitrary_length(const unsigned char* buffer,
601  std::ptrdiff_t *ints,
602  std::size_t count = 1)
603 {
604  return vsl_convert_from_arbitrary_length_signed_impl(buffer, ints, count);
605 }
606 #endif // 0
607 
608 /////////////////////////////////////////////////////////////////////////
609 /////////////////////////////////////////////////////////////////////////
610 
611 //: Write an unsigned int as 16 bits to vsl_b_ostream
612 // If your signed int cannot be represented in 16 bits (e.g. on a 32 bit
613 // platform) the stream's error flag will be set.
614 //
615 // Warning: This function should be used infrequently and carefully. Under
616 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
617 // vsl_binary_io.h will be perfectly adequate.
618 //
619 // You must use vsl_b_read_uint_16() to read the value saved with this
620 // function.
621 inline void vsl_b_write_uint_16(vsl_b_ostream& os, unsigned long n )
622 {
623  assert(n < (1 << 16));
624  vsl_swap_bytes(( char* )&n, sizeof(long) );
625  os.os().write( ( char* )&n, 2 );
626 }
627 
628 //: Read an unsigned int as 16 bits from vsl_b_istream
629 //
630 // Warning: This function should be used infrequently and carefully. Under
631 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
632 // vsl_binary_io.h will be perfectly adequate.
633 //
634 // This function will only read values saved using vsl_b_write_uint_16().
635 inline void vsl_b_read_uint_16(vsl_b_istream& is, unsigned long& n )
636 {
637  n = 0;
638  is.is().read( ( char* )&n, 2 );
639  vsl_swap_bytes(( char* )&n, sizeof(long) );
640 }
641 
642 
643 /////////////////////////////////////////////////////////////////////////
644 
645 //: Write a signed int as 16 bits to vsl_b_ostream
646 // If your signed int cannot be represented in 16 bits (e.g. on a 32 bit
647 // platform) the stream's error flag will be set.
648 //
649 // Warning: This function should be used infrequently and carefully. Under
650 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
651 // vsl_binary_io.h will be perfectly adequate.
652 //
653 // You must vsl_b_read_int_16() to read the value saved with this function.
654 inline void vsl_b_write_int_16(vsl_b_ostream& os, long n )
655 {
656  assert(n < 32768 && n >= - 32768);
657  vsl_swap_bytes(( char* )&n, sizeof(long) );
658  os.os().write( ( char* )&n, 2 );
659 }
660 
661 //: Read a signed int as 16 bits from vsl_b_istream
662 //
663 // Warning: This function should be used infrequently and carefully. Under
664 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
665 // vsl_binary_io.h will be perfectly adequate.
666 //
667 // This function will only read values saved using vsl_b_write_int_16().
668 inline void vsl_b_read_int_16(vsl_b_istream& is, long& n )
669 {
670  is.is().read( ( char* )&n, 2 );
671  if ((*(((unsigned char*)&n)+1) & 128) == 1)
672  {
673  vsl_swap_bytes(( char* )&n, sizeof(long) );
674  n |= -65536l;
675  }
676  else
677  {
678  vsl_swap_bytes(( char* )&n, sizeof(long) );
679  n &= 65535l;
680  }
681 }
682 
683 
684 //: Write a std::size_t as 64 bits to vsl_b_ostream
685 // Will assert if your std::size_t cannot be represented in 64 bits (e.g. on some 128 bit
686 // platforms).
687 //
688 // Warning: This function should be used infrequently and carefully. Under
689 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
690 // vsl_binary_io.h will be perfectly adequate.
691 //
692 // You must use vsl_b_read_uint_64() to read the value saved with this
693 // function.
694 inline void vsl_b_write_uint_64(vsl_b_ostream& os, std::size_t n )
695 {
696  assert(sizeof(std::size_t) <= 8 || n >> 16 >> 16 >> 16 >> 16 == 0);
697  vsl_swap_bytes(( char* )&n, sizeof(long) );
698  os.os().write( ( char* )&n, 8 );
699 }
700 
701 //: Read a std::size_t as 64 bits from vsl_b_istream
702 //
703 // Warning: This function should be used infrequently and carefully. Under
704 // all normal circumstances, the generic vsl_b_read and vsl_b_write in
705 // vsl_binary_io.h will be perfectly adequate.
706 //
707 // This function will only read values saved using vsl_b_write_uint_64().
708 inline void vsl_b_read_uint_64(vsl_b_istream& is, std::size_t& n )
709 {
710  n = 0;
711  is.is().read( ( char* )&n, 8 );
712  vsl_swap_bytes(( char* )&n, sizeof(long) );
713 }
714 
715 
716 #endif // vsl_binary_explicit_io_h_
void vsl_b_read_uint_64(vsl_b_istream &is, std::size_t &n)
Read a std::size_t as 64 bits from vsl_b_istream.
std::size_t vsl_convert_to_arbitrary_length_signed_impl(const T *ints, unsigned char *buffer, std::size_t count)
Implement arbitrary length conversion for signed integers.
void vsl_b_write_uint_64(vsl_b_ostream &os, std::size_t n)
Write a std::size_t as 64 bits to vsl_b_ostream.
std::size_t vsl_convert_to_arbitrary_length_unsigned_impl(const T *ints, unsigned char *buffer, std::size_t count)
Implement arbitrary length conversion for unsigned integers.
A binary output adaptor for any std::ostream.
Definition: vsl_binary_io.h:37
void vsl_b_read_uint_16(vsl_b_istream &is, unsigned long &n)
Read an unsigned int as 16 bits from vsl_b_istream.
void vsl_swap_bytes(char *ptr, unsigned nbyte, std::size_t nelem=1)
Perform byte swapping in situ.
void vsl_b_write_int_16(vsl_b_ostream &os, long n)
Write a signed int as 16 bits to vsl_b_ostream.
std::istream & is() const
A reference to the adaptor's stream.
std::size_t vsl_convert_from_arbitrary_length(const unsigned char *buffer, unsigned long *ints, std::size_t count=1)
Decode a buffer of arbitrary length integers.
std::size_t vsl_convert_from_arbitrary_length_signed_impl(const unsigned char *buffer, T *ints, std::size_t count)
Implement arbitrary length conversion for signed integers.
An adaptor for any std::istream to make it suitable for binary input.
std::size_t vsl_convert_to_arbitrary_length(const unsigned long *ints, unsigned char *buffer, std::size_t count=1)
Encode an array of ints into an arbitrary length format.
Set of functions, and objects to perform binary IO.
void vsl_b_read_int_16(vsl_b_istream &is, long &n)
Read a signed int as 16 bits from vsl_b_istream.
std::size_t vsl_convert_from_arbitrary_length_unsigned_impl(const unsigned char *buffer, T *ints, std::size_t count=1)
Implement arbitrary length conversion for unsigned integers.
std::ostream & os() const
A reference to the adaptor's stream.
void vsl_swap_bytes_to_buffer(const char *source, char *dest, unsigned nbyte, std::size_t nelem=1)
Perform byte swapping to a buffer.
void vsl_b_write_uint_16(vsl_b_ostream &os, unsigned long n)
Write an unsigned int as 16 bits to vsl_b_ostream.