home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-02-17 | 7.4 KB | 260 lines | [TEXT/ALFA] |
- // This may look like C code, but it is really -*- C++ -*-
- /*
- ************************************************************************
- *
- * Class Endian_IO
- * to read integers of various sizes taking the byte order
- * into account
- * and bit-stream IO
- *
- * Two different byte orders are supported
- * bigendian - most significant byte first
- * littleendian - most significant byte last
- *
- * $Id: endian_io.h,v 2.6 1996/03/15 17:07:19 oleg Exp oleg $
- *
- ************************************************************************
- */
-
- #ifndef __GNUC__
- #pragma once
- #endif
- #ifndef endian_io_h
- #define endian_io_h
-
- #ifdef __GNUC__
- #pragma interface
- #endif
-
- #include <fstream.h>
- #include "myenv.h"
-
- #ifdef __GNUC__
- #define _IOS_Bin_ ios::bin
- #elif defined(__SUNPRO_CC)
- #define _IOS_Bin_ 0
- #else
- #define _IOS_Bin_ ios::binary
- #endif
-
- // Extension to 'ios' to keep byte order
- // and stream sharing info
- class EndianIOData : virtual public ios
- {
- enum { MSBfirst, LSBfirst } byte_order;
- bool shared; // Was this stream shared with some other
- // stream?
-
- // These are deliberately private and
- // unimplemented to discourage
- // copy-constructing
- EndianIOData(const EndianIOData&);
- EndianIOData& operator = (const EndianIOData&);
-
- public:
- // Means having this stream reference the same
- // disk structure *and* the memory buffer
- // as a_file
- void share_with(EndianIOData& a_file);
- void unshare(void); // Check for sharing and break it
- EndianIOData(void) : byte_order(LSBfirst), shared(false) {}
- ~EndianIOData(void) { unshare(); }
-
- void set_bigendian(void) // Most significant byte first
- { byte_order = MSBfirst; }
- void set_littlendian(void) // Least significant byte first
- { byte_order = LSBfirst; }
- bool q_MSBfirst(void) const { return byte_order == MSBfirst; }
- bool was_shared(void) const { return shared; }
- // Returns TRUE if something goes wrong
- // with the I/O
- bool operator ! () { return !good(); }
- void error(const char *descr);
- // Make sure the stream was opened successfully
- void assert_open(const char * file_name);
- };
-
- // Class to read (binary) data from the input stream
- // keeping in mind the byte order
- class EndianIn : public EndianIOData, public ifstream
- {
- // These are deliberately private and
- // unimplemented to discourage
- // copy-constructing
- EndianIn(const EndianIn&);
- EndianIn& operator = (const EndianIn&);
-
- public:
- EndianIn(void) {}
- EndianIn(const char * file_name) : ifstream(file_name,ios::in|_IOS_Bin_)
- { assert_open(file_name); }
- ~EndianIn(void) { unshare(); }
-
- // Open by example. File handle of
- // 'file' is dup-ed, so closing the
- // present file would not close 'file'
- EndianIn(EndianIn& file) { share_with(file); }
-
- void open(const char *name, int mode=ios::in|_IOS_Bin_)
- { ifstream::open(name,mode); assert_open(name); }
-
- void close(void); // Close the stream breaking sharing if any
-
- // The following I/O functions take
- // the char string op_description
- // that tells what this operation is for
- // On error, this string is printed along
- // with the error description
- unsigned char read_byte(const char * op_description);
- unsigned short read_short(const char * op_description);
- unsigned long read_long(const char * op_description);
- };
-
- inline unsigned char EndianIn::read_byte(const char * op_description)
- {
- unsigned char c;
- if( !get(c) )
- error(op_description);
- return c;
- }
-
- // Class to write (binary) data from the input stream
- // keeping in mind the byte order
- class EndianOut : public EndianIOData, public ofstream
- {
- // These are deliberately private and
- // unimplemented to discourage
- // copy-constructing
- EndianOut(const EndianOut&);
- EndianOut& operator = (const EndianOut&);
-
- public:
- EndianOut(void) {}
- EndianOut(const char * file_name)
- : ofstream(file_name,ios::out|ios::trunc|_IOS_Bin_)
- { assert_open(file_name); }
- ~EndianOut(void) { unshare(); }
-
- // Open by example. File handle of
- // 'file' is dup-ed, so closing the
- // present file would not close 'file'
- EndianOut(EndianOut& file) { share_with(file); }
-
- void open(const char *name, int mode=ios::out|ios::trunc|_IOS_Bin_, int prot=0644)
- { ofstream::open(name,mode); assert_open(name); }
-
- void close(void); // Close the stream
-
- // The following I/O functions take
- // the char string op_description
- // that tells what this operation is for
- // On error, this string is printed along
- // with the error description
-
- // Note, the first operand of write_byte
- // has to be specified as 'int' rather
- // than 'unsigned char', as bizarre as
- // it may seem. Otherwise, write_byte(0xff)
- // results in the i/o error
- // 'Inappropriate IOCTL for device'
- // after some 2000-4000 writings such a byte.
- void write_byte(const int item, const char * op_description = "");
- void write_short(const unsigned short item, const char* op_description = "");
- void write_long(const unsigned long item, const char * op_description = "");
- };
-
- /*
- *------------------------------------------------------------------------
- * Bit-stream Input-Output
- * Note, bits are written in first-in first-out mode
- */
-
- class BitIOBuffer
- {
- protected:
- unsigned char buffer;
- enum { largest_bit_in_buffer = (1<<7) };
- unsigned char curr_bit_pos;
- public:
- BitIOBuffer(void) : buffer(0), curr_bit_pos(largest_bit_in_buffer) {}
- };
-
- class BitIn : BitIOBuffer, public EndianIn
- {
- // These are deliberately private and
- // unimplemented to discourage
- // copy-constructing
- BitIn(const BitIn&);
- BitIn& operator = (const BitIn&);
-
- public:
- // This is a dummy constructor. Use open() function
- // of EndianIO class to perform the actual opening
- BitIn(void) {}
-
- int get_bit(void); // Get a bit from the input stream
- short get_short(void); // Get a short integer that was written
- // using a variable size code
- };
-
- class BitOut : BitIOBuffer, public EndianOut
- {
- // These are deliberately private and
- // unimplemented to discourage
- // copy-constructing
- BitOut(const BitOut&);
- BitOut& operator = (const BitOut&);
-
- public:
- // This is a dummy constructor. Use open() function
- // of EndianIO class to perform the actual opening
- BitOut(void) {}
- ~BitOut(void);
-
- void put_bit(const char bit); // Write a bit into the output stream
- void put_short(const short item); // Write a signed short integer
- // using a variable size code
- void close(void); // Close the stream
- };
-
- // Put a bit (0/1) into the bit stream
- inline void BitOut::put_bit(const char bit)
- {
- if( bit )
- buffer |= curr_bit_pos;
- if( (curr_bit_pos>>=1) == 0 )
- write_byte(buffer), curr_bit_pos = largest_bit_in_buffer, buffer = 0;
- }
-
- // Flush the bit buffer on closing the stream
- inline void BitOut::close(void)
- {
- // If the buffer contains something
- if( curr_bit_pos != largest_bit_in_buffer )
- {
- write_byte(buffer); // Flush the buffer
- curr_bit_pos = largest_bit_in_buffer, buffer = 0;
- }
- EndianOut::close();
- }
-
- inline BitOut::~BitOut(void) { close(); }
-
-
- // Read a bit from the bit stream
- inline int BitIn::get_bit(void)
- {
- if( curr_bit_pos & largest_bit_in_buffer )
- {
- if( eof() )
- error("Reading an 8-bit chunk");
- get(buffer);
- }
- unsigned char bit_pos = curr_bit_pos;
- if( (curr_bit_pos >>=1) == 0 )
- curr_bit_pos = largest_bit_in_buffer;
- return buffer & bit_pos ? 1 : 0;
- }
-
- #endif
-