--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/network/bytestream.cpp Thu Dec 11 05:58:55 2014 +0200 @@ -0,0 +1,266 @@ +#include "bytestream.h" +#include <string.h> + +bool Bytestream::sink; + +// ------------------------------------------------------------------------------------------------- +// +Bytestream::Bytestream (unsigned long length) : + m_data (nullptr) +{ + resize (length); + clear(); +} + +// ------------------------------------------------------------------------------------------------- +// +Bytestream::Bytestream (const unsigned char* data, unsigned long length) : + m_data (nullptr) +{ + m_data = nullptr; + init (data, length); +} + +// ------------------------------------------------------------------------------------------------- +// +Bytestream::Bytestream (const Vector<unsigned char>& bytes) : + m_data (nullptr) +{ + init (bytes.data(), bytes.size()); +} + +// ------------------------------------------------------------------------------------------------- +// +Bytestream::~Bytestream() +{ + delete m_data; +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::resize (unsigned long newsize) +{ + Vector<unsigned char> olddata; + unsigned long oldsize = 0L; + + if (m_data != nullptr) + { + oldsize = allocated_size(); + olddata.resize (oldsize); + memcpy (olddata.data(), m_data, oldsize); + } + + delete[] m_data; + m_allocatedSize = newsize; + m_data = new unsigned char[newsize]; + + if (olddata > 0L) + memcpy (m_data, olddata, min (oldsize, newsize)); +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::init (const unsigned char* data, unsigned long length) +{ + resize (length); + memcpy (m_data, data, length); + m_cursor = &m_data[0]; + m_writtenLength = length; +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::clear() +{ + m_cursor = &m_data[0]; + m_writtenLength = 0; +} + +// ------------------------------------------------------------------------------------------------- +// +char Bytestream::read_byte (bool* ok) +{ + *ok = bytes_left() > 0; + return *ok ? *m_cursor++ : -1; +} + +// ------------------------------------------------------------------------------------------------- +// +short int Bytestream::read_short (bool* ok) +{ + if (bytes_left() < 2) + { + *ok = false; + return false; + } + + short int val = 0; + + for (int i = 0; i < 2; ++i) + val |= *m_cursor++ << (i * 8); + + *ok = true; + return true; +} + +// ------------------------------------------------------------------------------------------------- +// +long int Bytestream::read_long (bool* ok) +{ + if (bytes_left() < 4) + { + *ok = false; + return -1; + } + + long int val = 0; + + for (int i = 0; i < 4; ++i) + val |= *m_cursor++ << (i * 8); + + *ok = true; + return val; +} + +// ------------------------------------------------------------------------------------------------- +// +float Bytestream::read_float (bool* ok) +{ + int value = read_long (ok); + + if (*ok == false) + return -1.0f; + + return reinterpret_cast<float&> (value); +} + +// ------------------------------------------------------------------------------------------------- +// +String Bytestream::read_string (bool* ok) +{ + // Zandronum sends strings of maximum 2048 characters, though it only + // reads 2047-character long ones so I guess we can follow up and do + // the same :-) + static char buffer[MAX_NETWORK_STRING]; + unsigned char* stringEnd; + unsigned char* stringBegin = m_cursor; + unsigned char* end = m_data + allocated_size(); + + // where's the end of the string? + for (stringEnd = m_cursor; *stringEnd != '\0'; ++stringEnd) + { + if (stringEnd == end) + { + // past the end of the buffer! Argh! + *ok = false; + return ""; + } + } + + m_cursor = stringEnd + 1; + *ok = true; + unsigned int length = stringEnd - m_cursor; + + // ensure we won't write past the buffer (note: we still moved + // past the excess bytes in the above statement, those are ignored) + if (length >= MAX_NETWORK_STRING) + length = MAX_NETWORK_STRING - 1; + + memcpy (buffer, stringBegin, length); + buffer[length] = '\0'; + return String (buffer); +} + +// ------------------------------------------------------------------------------------------------- +// +METHOD +Bytestream::read (unsigned char* buffer, unsigned long length, bool* ok) -> void +{ + if (bytes_left() < length) + { + *ok = false; + return; + } + + memcpy (buffer, m_cursor, length); + m_cursor += length; + *ok = true; +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::write (unsigned char val) +{ + *m_cursor++ = val; + m_writtenLength++; +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::write (const unsigned char* val, unsigned int length) +{ + grow_to_fit (length); + memcpy (m_cursor, val, length); + m_cursor += length; + m_writtenLength += length; +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::grow_to_fit (unsigned long bytes) +{ + if (space_left() < bytes) + resize (allocated_size() + bytes + 128); +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::write_byte (char val) +{ + grow_to_fit (1); + write (val); +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::write_short (short int val) +{ + grow_to_fit (2); + + for (int i = 0; i < 2; ++i) + write ((val >> (i * 8)) & 0xFF); +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::write_long (long int val) +{ + grow_to_fit (4); + + for (int i = 0; i < 4; ++i) + write ((val >> (i * 8)) & 0xFF); +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::write_float (float val) +{ + // I know this is probably dangerous but this is what Zandronum does so yeah + write_long (reinterpret_cast<int&> (val)); +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::write_string (const String& val) +{ + grow_to_fit (val.length() + 1); + write (reinterpret_cast<const unsigned char*> (val.chars()), val.length()); + write (0); +} + +// ------------------------------------------------------------------------------------------------- +// +void Bytestream::write_buffer (const Bytestream& other) +{ + write (other.data(), other.written_length()); +}