sources/network/bytestream.cpp

changeset 5
146825d63b9a
child 9
e7a09ceb4505
--- /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());
+}

mercurial