Listing 1: An implementation of NetBuffer

// For simplicity, this code assumes that CHAR_BITS is 8
// It is possible to further generalize this code for
// platforms having different CHAR_BITS values.
//
// In any case, the network format must have 8-bit chars,
// 16-bit shorts and 32-bit ints

typedef std::vector<char> Buffer;

class NetBuffer
{
  Buffer theBuffer;
  size_t theReadCounter;
  size_t theWriteCounter;

  void reset()
  {
    theReadCounter  = 0;
    theWriteCounter = 0;
  }

public:

  explicit NetBuffer(size_t aSize=0)
    : theBuffer(aSize) { reset(); }

  NetBuffer(const Buffer &aBuffer) : theBuffer(aBuffer) { reset(); }

  NetBuffer(const char *aBuffer, size_t aSize)
     : theBuffer(aSize) { reset(); put(aBuffer, aSize); reset(); }


  bool get(char *aBuffer, size_t aSize);
  void put(const char *aBuffer, size_t aSize);

  const Buffer & buffer() const { return theBuffer; }
  Buffer & buffer() { return theBuffer; }

  size_t size() const { return theBuffer.size(); }
  void resize(size_t aSize) { theBuffer.resize(aSize); }

  size_t bytesRead() const { return theReadCounter; }
  size_t bytesWritten() const { return theWriteCounter; }

};

void NetBuffer::put(const char * aBuffer, size_t aSize)
{
  if( theWriteCounter + aSize <= size() )
  {
    memcpy(&(theBuffer[theWriteCounter]), aBuffer, aSize);
  }
  theWriteCounter += aSize;
}

bool NetBuffer::get(char * aBuffer, size_t aSize)
{
  bool ret = true;

  if( theReadCounter + aSize <= size() )
  {
    memcpy( aBuffer, &(theBuffer[theReadCounter]), aSize);
  }
  else
  {
    ret = false;
  }

  theReadCounter += aSize;

  return ret;
}

bool operator==(const NetBuffer & a, const NetBuffer &b)
{
  if(a.size() != b.size()) return false;

  return memcmp(&(a.buffer()[0]), &(b.buffer()[0]), a.size() )==0;
}

NetBuffer & operator << (NetBuffer &n, int8_t aChar)
{
  n.put(reinterpret_cast<char *>(&aChar), 1);
  return n;
}

NetBuffer & operator >> (NetBuffer &n, int8_t  & aChar)
{
  if(!n.get(reinterpret_cast<char *>(&aChar), 1))
    aChar = 0;
  return n;
}

NetBuffer & operator << (NetBuffer &n, int16_t aShort)
{
  int16_t netValue = htons(aShort);
  n.put(reinterpret_cast<char *>(&netValue), 2);
  return n;
}

NetBuffer & operator >> (NetBuffer &n, int16_t & aShort)
{
  aShort = n.get( reinterpret_cast<char *>(&aShort),2)
    ?  ntohs(aShort) : 0;
  return n;
}

NetBuffer & operator << (NetBuffer &n, int32_t anInt)
{
  int32_t netValue = htonl(anInt);
  n.put(reinterpret_cast<char *>(&netValue), 4);
  return n;
}

NetBuffer & operator >> (NetBuffer &n, int32_t & anInt)
{
  anInt = n.get( reinterpret_cast<char *>(&anInt),4)
    ?  ntohs(anInt) : 0;
  return n;
}

NetBuffer & operator << (NetBuffer &n, const Buffer &aBuffer)
{
  n.put( &(aBuffer[0]) , aNetBuffer.size() );
  return n;
}

NetBuffer & operator >> (NetBuffer &n, NetBuffer &aBuffer)
{
  n.get( &(aBuffer[0]) , aNetBuffer.size() );
  return n;
}
— End of Listing —