# ChecksumDataBuffer

Derived from: none

Declared in: ChecksumDataBuffer.h

Library: none

## Overview

ChecksumDataBuffer is a class which buffers data for transmission over a network. Its intended use is to write the data to the buffer, generate a checksum for the data, write the checksum to the buffer as well, and finally transmit the full buffer. Typically, there will be data at the beginning of the message indicating the overall length of the message. To facilitate this, you can also write to a specified position in the buffer. For example, you could write an int32 zero length at the beginning of the buffer, write the buffer content, read the buffer length once you're finished, write that length at position zero, generate a checksum, write the checksum to the end of the buffer, and send it.

## Constructor and Destructor

### ChecksumDataBuffer()

          ChecksumDataBuffer(uint32 growth_increment, bool use_network_order)

Creates a new ChecksumDataBuffer object, and initializes it according to the arguments. The growth_increment specified the initial buffer size, but if the message grows beyond this size, the buffer will continue to grow to hold the data. Note that the buffer stores the entire message so you probably shouldn't let the message grow beyond a couple of megabytes at the most. If a message can get that big, you want to transmit it directly without buffering.

### ~ChecksumDataBuffer()

          virtual ~ChecksumDataBuffer()

Destroys the object and frees all memory it allocated.

## Member Functions

### AddInt64(), AddInt32(), AddInt16(), AddInt8(), AddUint64(), AddUint32(), AddUint16(), AddUint8(), AddNumber(), AddData()

          void AddInt64(int64 data)
          void AddInt32(int32 data)
          void AddInt16(int16 data)
          void AddInt8(int8 data)
          void AddUint64(uint64 data)
          void AddUint32(uint32 data)
          void AddUint16(uint16 data)
          void AddUint8(uint8 data)
          void AddNumber(void* data, uint8 size)
          void AddData(const void* data, uint32 length)

Writes a number or data to the end of the buffer. For all calls except AddData, if the constructor specified use_network_order to be true, then it is written to the buffer in network byte order, otherwise, it is written in the native order for the machine. Note that it is safe to call AddData with a NULL pointer if the length is zero.

### Data(), Size()

          uint8* Data() const
          uint32 Size() const

Return a pointer to the beginning of the data buffer, and the size of the data in the buffer. Typically, after calling AddXXX and/or ReplaceXXX to build the buffer for transmission, generating a checksum, and adding the checksum to the end of the message, one will call Data and Size to get the fully constructed buffer and its size, and write the buffer to a socket.

### ExpandBufferForAdd(), ExternalAddDataAddress(), ExternalAddDataCompleted()

          void ExpandBufferForAdd(uint32 length)
          int8* ExternalAddDataAddress() const
          void ExternalAddDataCompleted(uint32 length)

ExpandBufferForAdd makes room in the buffer for an add to occur from an external source (typically, reading from a socket). Once this is done, you should call ExternalAddDataAddress to get the position to which that data should be read, and, in the socket case, read data to that address. Once that is done, call ExternalAddDataCompleted to tell the ChecksumDataBuffer how many bytes were added to it.

### Flush()

          void Flush()

Flushes the buffer so that the read and write pointers are at the beginning of the buffer. Typically, when writing to a socket, one will build the buffer using AddXXX and ReplaceXXX calls, generatie a checksum, add the checksum to the end of the message, then send the full buffer through a socket. At that point, to prepare for using the ChecksumDataBuffer for the next message, one will call Flush. On the receiving end, one will typically receive the message, extract its data using ReadXXX, and when finished, prepare for using the ChecksumDataBuffer for the next message by calling Flush.

### GetChecksum16(), GetChecksum32(), GetWrappingChecksum(), AddMoreWrappingChecksum()

          uint16 GetChecksum16() const {return GetChecksum16(m_data,m_buffer_pos);}
          uint32 GetChecksum32() const {return GetChecksum32(m_data,m_buffer_pos);}
          uint32 GetWrappingChecksum() const {return GetWrappingChecksum(m_data,m_buffer_pos);}
          static uint16 GetChecksum16(uint8* data, uint32 length);
          static uint32 GetChecksum32(uint8* data, uint32 length);
          static uint32 GetWrappingChecksum(uint8* data, uint32 length);
          static uint32 AddMoreWrappingChecksum(uint8* data, uint32 length, uint32 prev_data_length,
                uint32 prev_checksum)

The non-static versions of GetChecksum generate checksums for the full buffer currently held by the ChecksumDataBuffer. The static versions take a pointer to a buffer and a length. The AddMoreWrappingChecksum method is used to continue generating a wrapping checksum for a large message that is too big to fit in one buffer. By calling it repeatedly, you can generate a wrapping checksum on a discontiguous buffer. GetChecksum16 and GetChecksum32 simply add all the bytes in a buffer in a uint16 or uint32, allowing it to wrap as the sum grows. The wrapping version generates a checksum in a uint32, and at each byte, shifts it one more bit to the right until it reaches a shift of 24, after which it shifts back to the left again. See ChecksumDataBuffer.cpp for the implementation. An almost bulletproof checksum is a combination of GetChecksum16 and GetWrappingChecksum.

### ReadInt64(), ReadInt32(), ReadInt16(), ReadInt8(), ReadUint64(), ReadUint32(), ReadUint16(), ReadUint8(), ReadNumber(), ReadData(), ReadInt64At(), ReadInt32At(), ReadInt16At(), ReadInt8At(), ReadUint64At(), ReadUint32At(), ReadUint16At(), ReadUint8At(), ReadNumberAt(), ReadDataAt()

          int64 ReadInt64()
          int32 ReadInt32()
          int16 ReadInt16()
          int8  ReadInt8()
          uint64 ReadUint64()
          uint32 ReadUint32()
          uint16 ReadUint16()
          uint8  ReadUint8()
          int64 ReadInt64At(uint32 at_pos) const
          int32 ReadInt32At(uint32 at_pos) const
          int16 ReadInt16At(uint32 at_pos) const
          int8  ReadInt8At(uint32 at_pos) const
          uint64 ReadUint64At(uint32 at_pos) const
          uint32 ReadUint32At(uint32 at_pos) const
          uint16 ReadUint16At(uint32 at_pos) const
          uint8  ReadUint8At(uint32 at_pos) const
          void ReadNumber(void* data, uint8 size)
          void ReadNumberAt(void* data, uint8 size, uint32 at_pos)  const
          const uint8* ReadData(uint32 length)
          const uint8* ReadDataAt(uint32 length, uint32 at_pos)

Reads numbers or data from the buffer. For the At versions of the above functions, the data is read from the specified position without affecting the read pointer. Otherwise, the number of data is read at the current read pointer, and the read pointer is advanced. For all calls except ReadData, if the constructor specified use_network_order to be true, then it is read from the buffer in network byte order, otherwise, it is read in the native order for the machine.

### ReplaceInt64(), ReplaceInt32(), ReplaceInt16(), ReplaceInt8(), ReplaceUint64(), ReplaceUint32(), ReplaceUint16(), ReplaceUint8(), ReplaceNumber(), ReplaceData()

          void ReplaceInt64(int64 data, int32 at_pos)
          void ReplaceInt32(int32 data, int32 at_pos)
          void ReplaceInt16(int16 data, int32 at_pos)
          void ReplaceInt8(int8 data, int32 at_pos)
          void ReplaceUint64(uint64 data, int32 at_pos)
          void ReplaceUint32(uint32 data, int32 at_pos)
          void ReplaceUint16(uint16 data, int32 at_pos)
          void ReplaceUint8(uint8 data, int32 at_pos)
          void ReplaceNumber(void* data, uint8 size, uint32 at_pos)
          void ReplaceData(const void* data, uint32 length, uint32 at_pos)

Replaces a number in the buffer. For all calls except ReplaceData, if the constructor specified use_network_order to be true, then it is written to the buffer in network byte order, otherwise, it is written in the native order for the machine. Note that it is safe to call ReplaceData with a NULL pointer if the length is zero.

By Brian Tietz

Copyright 2000

Bug reports (including documentation errors) and feature requests can be sent to briant@timelinevista.com.