Search

Sponsored Links

Meta

Categories

Archives

Recent Posts

RSS Feeds

18
Jan

Binary Streams Utility Classes

Related Blog Items

Binary streams are commonly used in many applications. They require special care while dealing with them. Here is a binary class which can be deployed and customized according to your need. This binary class has awareness of endian. It act according to endain. If your machine is little endian and you wish to process your binary stream in little endian, then set the mode to little endian. If your machine big endian set the mode to big endian. However little more intelligence yet to be incorporated in case of your machine is little endian and you want the binary stream processing in big endian, in this case you need to use utilities mentioned in the post Little and big endianess explained - part2

There are three classes, BinaryStream, IBinaryStream, OBinaryStream. IBinaryStream is input binary stream and OBinaryStream is output binary stream. You can directly create class instances and attach a buffer and work on it. However you can extend this class by defining some overloading operators to the operations in the class or you can add more functionality to these classes.

#define NUM_BITS_IN_BYTE 8

 

//these classes doesn't bother about whether integers are word aligned or not,
//internally take care of it

//binary stream class
class BinaryStream
{
public:
  BinaryStream()
  {
    buf = NULL;
    len = 0;
    currptr = 0;
    err = STREAM_OK;
    endianness = LITTLE_ENDIAN;
  }

  virtual ~BinaryStream(){};

  enum
  {
    LITTLE_ENDIAN,
    BIG_ENDIAN,
  };

  enum
  {
   BS_SEEK_SET,
   BS_SEEK_CUR,
   BS_SEEK_END,
  };

  enum
  {
    STREAM_OK,
    STREAM_EOF,
    STREAM_FAIL,
  };

  //is stream ok
  bool IsStreamOk()
  {
    return (err == STREAM_OK);
  }

  //is end of stream
  bool eof()
  {
    return (err == STREAM_EOF);
  }

  //can read/write n bytes from stream
  bool IsSpaceAvailableForOperation(unsigned long bytes)
  {
    return (currptr < (buf+len-bytes));
  }

  //attach a buffer to work on
  void Attach(void * buffer, unsigned long length)
  {
    buf = (unsigned char *)buffer;
    currptr = buf;
    len = length;
    err = STREAM_OK;
  }

  //current position in stream
  unsigned long tell()
  {
    return (currptr - buf);
  }

  //seek to offset in stream
  void seek(int offset, int fromwhere)
  {
    switch(fromwhere)
    {
      case BS_SEEK_SET:
          currptr = buf + offset;
          break;
      case BS_SEEK_CUR:
          currptr += offset;
          break;
      case BS_SEEK_END:
          if (offset < 0)
          {
            currptr += offset;
          }
          break;
      default:
          break;
    }
  }
protected:
  int err;
  unsigned char *buf;
  unsigned long len;
  unsigned char *currptr;
  int endianness; //endianness of stream

};

Here is the input binary stream class. It inherits from above binary class.

//input binary stream
class IBinaryStream : public BinaryStream
{
private:
  public:
 
  IBinaryStream(){};
  ~IBinaryStream(){};
 
  //reads a byte from stream
  unsigned char ReadByte()
  {
    if (IsSpaceAvailableForOperation(sizeof(unsigned char)))
    {
      return(*currptr++);
    }
    err = STREAM_EOF;
    return 0;
  }
 
  unsigned short ReadUnsignedShort()
  {
    unsigned short result = 0;
    unsigned char byte1, byte2;
 
    if (IsSpaceAvailableForOperation(sizeof(unsigned short)))
    {
      if (endianness == LITTLE_ENDIAN)
      {
        byte1 = ReadByte();
        byte2 = ReadByte();
      }
      else
      {
        byte2 = ReadByte();
        byte1 = ReadByte();
      }
      currptr += sizeof(unsigned short);
      result = byte1;
      return(( result << NUM_BITS_IN_BYTE) | byte2 );
    } /*IsSpaceAvailableForOperation(sizeof(unsigned short)))*/
    err = STREAM_EOF;
    return 0;
  }
 
  unsigned long ReadUnsignedLong()
  {
    unsigned long result = 0;
    if ( IsSpaceAvailableForOperation(sizeof(unsigned long)))
    {
      unsigned char byte1, byte2, byte3, byte4;
 
      if (endianness == LITTLE_ENDIAN)
      {
        byte1 = ReadByte();
        byte2 = ReadByte();
        byte3 = ReadByte();
        byte4 = ReadByte();
      }
      else
      {
        byte4 = ReadByte();
        byte3 = ReadByte();
        byte2 = ReadByte();
        byte1 = ReadByte();
      }
      result = byte1;
      result = (result << NUM_BITS_IN_BYTE) | byte2;
      result = (result << NUM_BITS_IN_BYTE) | byte3;
      result = (result << NUM_BITS_IN_BYTE) | byte4;
      currptr += sizeof(unsigned long);
      return result;
    } /*IsSpaceAvailableForOperation(sizeof(unsigned long)))*/
    err = STREAM_EOF;
    return result;
  }
 
  //Reads 'length' number of bytes from the stream and places them in 'data'.
  int read(unsigned char * data, int size)
  {
    if (data && IsSpaceAvailableForOperation(size) )
    {
      memcpy(data, currptr, size);
      currptr += size;
    }
 
    err = STREAM_FAIL;
    return 0;
  }
};

The below class is output binary class, it also inherits from BinaryStream.

//output binary stream
class OBinaryStream : public BinaryStream
{
public:
  OBinaryStream(){};
  virtual ~OBinaryStream(){};
 
  //write into stream
  int write(const unsigned char * data, int size)
  {
    if (data && IsSpaceAvailableForOperation(size))
    {
      memcpy(currptr, data, size);
      currptr += size;
      return size;
    }
    err = STREAM_FAIL;
    return 0;
  }
 
  //write a byte
  int WriteByte(unsigned char n)
  {
    if ( IsSpaceAvailableForOperation(sizeof(unsigned char)))
    {
      *currptr = n;
      currptr += sizeof(unsigned char);
      return sizeof(unsigned char);
    }
    err = STREAM_EOF;
    return 0;
  }
 
  //write a unsigned short
  int WriteUnsignedShort(unsigned short n)
  {
    unsigned char byte1, byte2;
 
    if ( IsSpaceAvailableForOperation(sizeof(unsigned short)))
    {
      if (endianness == LITTLE_ENDIAN)
      {
        byte1 = (unsigned char)n;
        byte2 = n >> NUM_BITS_IN_BYTE;
      }
      else
      {
        byte2 = (unsigned char)n;
        byte1 = n >> NUM_BITS_IN_BYTE;
      }
 
      *currptr++ = byte2;
      *currptr++ = byte1;
 
      return sizeof(unsigned short);
    } /*IsSpaceAvailableForOperation(sizeof(unsigned short)))*/
    err = STREAM_EOF;
    return 0;
  }
 
  //write a unsigned long
  int WriteUnsignedLong(unsigned long n)
  {
    unsigned char byte1, byte2, byte3, byte4;
 
    if ( IsSpaceAvailableForOperation(sizeof(unsigned long)))
    {
      if (endianness == LITTLE_ENDIAN)
      {
        byte1 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte2 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte3 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte4 = (unsigned char)n;
      }
      else
      {
        byte4 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte3 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte2 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte1 = (unsigned char)n;
      }
 
      *currptr++ = byte4;
      *currptr++ = byte3;
      *currptr++ = byte2;
      *currptr++ = byte1;
 
      return sizeof(unsigned long);
    } /*IsSpaceAvailableForOperation(sizeof(unsigned short)))*/
    err = STREAM_EOF;
    return 0;
  } 
};

Please let me know your comments and suggestions.

Popularity: 5%

You need to log on to convert this article into PDF


Related Blog Items

No Comments

No comments yet.

Leave a comment

*
To prove you're a person (not a spam script), type the security word shown in the picture.
Anti-spam image