Thu, 11 Dec 2014 05:58:55 +0200
- code cleanup
- added network-related classes (bytestream, ipaddress, udp socket)
#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()); }