home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Libraries / c++advio 2.3 / Advanced i⁄o / endian_io.h < prev    next >
Encoding:
Text File  |  1997-02-17  |  7.4 KB  |  260 lines  |  [TEXT/ALFA]

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Class Endian_IO
  6.  *    to read integers of various sizes taking the byte order
  7.  *                into account
  8.  *              and bit-stream IO
  9.  *
  10.  *   Two different byte orders are supported
  11.  *    bigendian    - most significant byte first
  12.  *    littleendian    - most significant byte last
  13.  *
  14.  * $Id: endian_io.h,v 2.6 1996/03/15 17:07:19 oleg Exp oleg $
  15.  *
  16.  ************************************************************************
  17.  */
  18.  
  19. #ifndef __GNUC__
  20. #pragma once
  21. #endif
  22. #ifndef endian_io_h
  23. #define endian_io_h
  24.  
  25. #ifdef __GNUC__
  26. #pragma interface
  27. #endif
  28.  
  29. #include <fstream.h>
  30. #include "myenv.h"
  31.  
  32. #ifdef __GNUC__
  33. #define _IOS_Bin_               ios::bin
  34. #elif defined(__SUNPRO_CC)
  35. #define _IOS_Bin_               0
  36. #else
  37. #define _IOS_Bin_               ios::binary
  38. #endif
  39.  
  40.                 // Extension to 'ios' to keep byte order
  41.                 // and stream sharing info
  42. class EndianIOData : virtual public ios
  43. {
  44.   enum { MSBfirst, LSBfirst } byte_order;
  45.   bool shared;            // Was this stream shared with some other
  46.                 // stream?
  47.  
  48.                 // These are deliberately private and
  49.                 // unimplemented to discourage
  50.                 // copy-constructing
  51.   EndianIOData(const EndianIOData&);
  52.   EndianIOData& operator = (const EndianIOData&);
  53.  
  54. public:
  55.                 // Means having this stream reference the same
  56.                 // disk structure *and* the memory buffer
  57.                 // as a_file
  58.   void share_with(EndianIOData& a_file);
  59.   void unshare(void);        // Check for sharing and break it
  60.   EndianIOData(void) : byte_order(LSBfirst), shared(false)  {}
  61.   ~EndianIOData(void)        { unshare(); }
  62.  
  63.   void set_bigendian(void)          // Most significant byte first
  64.                   { byte_order = MSBfirst; }
  65.   void set_littlendian(void)        // Least significant byte first
  66.                 { byte_order = LSBfirst; }
  67.   bool q_MSBfirst(void) const    { return byte_order == MSBfirst; }
  68.   bool was_shared(void) const    { return shared; }
  69.                 // Returns TRUE if something goes wrong
  70.                 // with the I/O
  71.   bool operator ! ()    { return !good(); }
  72.   void error(const char *descr);
  73.                 // Make sure the stream was opened successfully
  74.   void assert_open(const char * file_name);
  75. };
  76.  
  77.             // Class to read (binary) data from the input stream
  78.             // keeping in mind the byte order
  79. class EndianIn : public EndianIOData, public ifstream
  80. {
  81.                 // These are deliberately private and
  82.                 // unimplemented to discourage
  83.                 // copy-constructing
  84.   EndianIn(const EndianIn&);
  85.   EndianIn& operator = (const EndianIn&);
  86.  
  87. public:
  88.   EndianIn(void) {}
  89.   EndianIn(const char * file_name) : ifstream(file_name,ios::in|_IOS_Bin_)
  90.                 { assert_open(file_name); }
  91.   ~EndianIn(void)         { unshare(); }
  92.  
  93.                     // Open by example. File handle of
  94.                     // 'file' is dup-ed, so closing the
  95.                     // present file would not close 'file'
  96.   EndianIn(EndianIn& file)        { share_with(file); }
  97.  
  98.   void open(const char *name, int mode=ios::in|_IOS_Bin_)
  99.         { ifstream::open(name,mode); assert_open(name); }
  100.  
  101.   void close(void);        // Close the stream breaking sharing if any
  102.  
  103.                 // The following I/O functions take
  104.                 // the char string op_description
  105.                 // that tells what this operation is for
  106.                 // On error, this string is printed along
  107.                 // with the error description
  108.   unsigned char  read_byte(const char * op_description);
  109.   unsigned short read_short(const char * op_description);
  110.   unsigned long  read_long(const char * op_description);
  111. };
  112.  
  113. inline unsigned char EndianIn::read_byte(const char * op_description) 
  114. {
  115.   unsigned char c;
  116.   if( !get(c) )
  117.     error(op_description);
  118.   return c;
  119. }
  120.  
  121.             // Class to write (binary) data from the input stream
  122.             // keeping in mind the byte order
  123. class EndianOut : public EndianIOData, public ofstream
  124. {
  125.                 // These are deliberately private and
  126.                 // unimplemented to discourage
  127.                 // copy-constructing
  128.   EndianOut(const EndianOut&);
  129.   EndianOut& operator = (const EndianOut&);
  130.  
  131. public:
  132.   EndianOut(void) {}
  133.   EndianOut(const char * file_name)
  134.     : ofstream(file_name,ios::out|ios::trunc|_IOS_Bin_)
  135.                 { assert_open(file_name); }
  136.   ~EndianOut(void)         { unshare(); }
  137.  
  138.                     // Open by example. File handle of
  139.                     // 'file' is dup-ed, so closing the
  140.                     // present file would not close 'file'
  141.   EndianOut(EndianOut& file)        { share_with(file); }
  142.  
  143.   void open(const char *name, int mode=ios::out|ios::trunc|_IOS_Bin_, int prot=0644)
  144.         { ofstream::open(name,mode); assert_open(name); }
  145.  
  146.   void close(void);        // Close the stream
  147.  
  148.                 // The following I/O functions take
  149.                 // the char string op_description
  150.                 // that tells what this operation is for
  151.                 // On error, this string is printed along
  152.                 // with the error description
  153.  
  154.                 // Note, the first operand of write_byte
  155.                 // has to be specified as 'int' rather
  156.                 // than 'unsigned char', as bizarre as
  157.                 // it may seem. Otherwise, write_byte(0xff)
  158.                 // results in the i/o error
  159.                 // 'Inappropriate IOCTL for device'
  160.                 // after some 2000-4000 writings such a byte.
  161.   void write_byte(const int item, const char * op_description = "");
  162.   void write_short(const unsigned short item, const char* op_description = "");
  163.   void write_long(const unsigned long item, const char * op_description = "");
  164. };
  165.  
  166. /*
  167.  *------------------------------------------------------------------------
  168.  *            Bit-stream Input-Output
  169.  * Note, bits are written in first-in first-out mode
  170.  */
  171.  
  172. class BitIOBuffer
  173. {
  174. protected:
  175.   unsigned char buffer;
  176.   enum { largest_bit_in_buffer = (1<<7) };
  177.   unsigned char curr_bit_pos;
  178. public:
  179.   BitIOBuffer(void) : buffer(0), curr_bit_pos(largest_bit_in_buffer) {}
  180. };
  181.  
  182. class BitIn : BitIOBuffer, public EndianIn
  183. {
  184.                 // These are deliberately private and
  185.                 // unimplemented to discourage
  186.                 // copy-constructing
  187.   BitIn(const BitIn&);
  188.   BitIn& operator = (const BitIn&);
  189.  
  190. public:
  191.             // This is a dummy constructor. Use open() function
  192.             // of EndianIO class to perform the actual opening
  193.   BitIn(void) {}
  194.  
  195.   int  get_bit(void);            // Get a bit from the input stream
  196.   short get_short(void);        // Get a short integer that was written
  197.                       // using a variable size code
  198. };
  199.  
  200. class BitOut : BitIOBuffer, public EndianOut
  201. {
  202.                 // These are deliberately private and
  203.                 // unimplemented to discourage
  204.                 // copy-constructing
  205.   BitOut(const BitOut&);
  206.   BitOut& operator = (const BitOut&);
  207.  
  208. public:
  209.             // This is a dummy constructor. Use open() function
  210.             // of EndianIO class to perform the actual opening
  211.   BitOut(void) {}
  212.   ~BitOut(void);
  213.  
  214.   void put_bit(const char bit);        // Write a bit into the output stream
  215.   void put_short(const short item);    // Write a signed short integer 
  216.                       // using a variable size code
  217.   void close(void);            // Close the stream
  218. };
  219.  
  220.             // Put a bit (0/1) into the bit stream
  221. inline void BitOut::put_bit(const char bit)
  222. {
  223.   if( bit )
  224.     buffer |= curr_bit_pos;
  225.   if( (curr_bit_pos>>=1) == 0 )
  226.     write_byte(buffer), curr_bit_pos = largest_bit_in_buffer, buffer = 0;
  227. }
  228.  
  229.             // Flush the bit buffer on closing the stream      
  230. inline void BitOut::close(void)
  231. {
  232.                     // If the buffer contains something
  233.   if( curr_bit_pos != largest_bit_in_buffer )
  234.   {
  235.     write_byte(buffer);            // Flush the buffer
  236.     curr_bit_pos = largest_bit_in_buffer, buffer = 0;
  237.   }
  238.   EndianOut::close();
  239. }
  240.  
  241. inline BitOut::~BitOut(void)                { close(); }
  242.  
  243.  
  244.             // Read a bit from the bit stream
  245. inline int BitIn::get_bit(void)
  246. {
  247.   if( curr_bit_pos & largest_bit_in_buffer )
  248.   {
  249.     if( eof() ) 
  250.       error("Reading an 8-bit chunk");
  251.     get(buffer);
  252.   }
  253.   unsigned char bit_pos = curr_bit_pos;
  254.   if( (curr_bit_pos >>=1) == 0 )
  255.     curr_bit_pos = largest_bit_in_buffer;
  256.   return buffer & bit_pos ? 1 : 0;
  257. }
  258.  
  259. #endif
  260.