Replaced the Bytestream class with QDataStream

Sun, 11 Aug 2013 14:04:03 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sun, 11 Aug 2013 14:04:03 +0300
changeset 18
6bf57b4f42cd
parent 17
b41d74bacdea
child 19
c9b6dd9dd4cd

Replaced the Bytestream class with QDataStream

src/bytestream.cpp file | annotate | diff | comparison | revisions
src/bytestream.h file | annotate | diff | comparison | revisions
src/demo.cpp file | annotate | diff | comparison | revisions
--- a/src/bytestream.cpp	Sun Aug 11 13:38:12 2013 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-/*
- *  ZanDemo: Zandronum demo launcher
- *  Copyright (C) 2013 Santeri Piippo
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "bytestream.h"
-#include "misc.h"
-#include <string.h>
-
-union {
-	uint32 i;
-	float f;
-} g_floatunion;
-
-Bytestream::Bytestream (ulong len) {
-	m_data = null;
-	resize (len);
-	clear();
-}
-
-Bytestream::Bytestream (const char* data, ulong len) {
-	m_data = null;
-	init (data, len);
-}
-
-void Bytestream::resize (ulong newsize) {
-	char* olddata = null;
-	ulong oldsize;
-
-	if (m_data) {
-		oldsize = m_size;
-		olddata = new char[oldsize];
-		memcpy (olddata, m_data, oldsize);
-	}
-
-	delete[] m_data;
-	m_data = new uint8[newsize];
-	m_size = newsize;
-
-	if (olddata)
-		memcpy (m_data, olddata, min<ulong> (oldsize, newsize));
-}
-
-void Bytestream::init (const char* data, ulong len) {
-	resize (len);
-	memcpy (m_data, data, len);
-	m_ptr = &m_data[0];
-	m_len = len;
-}
-
-size_t Bytestream::len() const {
-	return m_len;
-}
-
-void Bytestream::clear() {
-	m_ptr = &m_data[0];
-	m_len = 0;
-}
-
-uint8& Bytestream::subscript (ulong idx) {
-	return m_data[idx];
-}
-
-const uint8& Bytestream::const_subscript (ulong idx) const {
-	return m_data[idx];
-}
-
-void Bytestream::seek (ulong pos) {
-	m_ptr = m_data + pos;
-}
-
-// =============================================================================
-void Bytestream::rewind() {
-	m_ptr = m_data;
-}
-
-ulong Bytestream::bytesLeft() const {
-	return (m_len - (m_ptr - &m_data[0]));
-}
-
-ulong Bytestream::spaceLeft() const {
-	return (m_size - m_len);
-}
-
-// =============================================================================
-bool Bytestream::readByte (uint8& val) {
-	if (bytesLeft() < 1)
-		return false;
-
-	val = *m_ptr++;
-	return true;
-}
-
-// =============================================================================
-bool Bytestream::readShort (uint16& val) {
-	if (bytesLeft() < 2)
-		return false;
-
-	val = 0;
-
-	for (int i = 0; i < 2; ++i)
-		val |= *m_ptr++ << (i * 8);
-
-	return true;
-}
-
-// =============================================================================
-bool Bytestream::readLong (uint32& val) {
-	if (bytesLeft() < 4)
-		return false;
-
-	val = 0;
-
-	for (int i = 0; i < 4; ++i)
-		val |= *m_ptr++ << (i * 8);
-
-	return true;
-}
-
-// =============================================================================
-bool Bytestream::readFloat (float& val) {
-	if (!readLong (g_floatunion.i))
-		return false;
-
-	val = g_floatunion.f;
-	return true;
-}
-
-// =============================================================================
-bool Bytestream::readString (str& val) {
-	if (bytesLeft() < 1)  // need at least the null terminator
-		return false;
-
-	uint8_t c;
-
-	while (readByte (c) && c != '\0')
-		val += (char) c;
-
-	return true;
-}
-
-// =============================================================================
-void Bytestream::doWrite (uint8_t val) {
-	*m_ptr++ = val;
-	m_len++;
-}
-
-void Bytestream::growToFit (ulong bytes) {
-	if (spaceLeft() < bytes)
-		resize (m_size + bytes + 128);
-}
-
-bool Bytestream::readBytes (uint8 numbytes, uint8* val) {
-	while (numbytes--)
-		if (!readByte (*val++))
-			return false;
-
-	return true;
-}
-
-void Bytestream::writeBytes (uint8 numbytes, const uint8* val) {
-	growToFit (numbytes);
-
-	while (numbytes--)
-		writeByte (*val++);
-}
-
-// =============================================================================
-void Bytestream::writeByte (uint8 val) {
-	growToFit (1);
-	doWrite (val);
-}
-
-// =============================================================================
-void Bytestream::writeShort (uint16 val) {
-	growToFit (2);
-
-	for (int i = 0; i < 2; ++i)
-		doWrite ( (val >> (i * 8)) & 0xFF);
-}
-
-// =============================================================================
-void Bytestream::writeLong (uint32 val) {
-	growToFit (4);
-
-	for (int i = 0; i < 4; ++i)
-		doWrite ( (val >> (i * 8)) & 0xFF);
-}
-
-// =============================================================================
-void Bytestream::writeFloat (float val) {
-	g_floatunion.f = val;
-	writeLong (g_floatunion.i);
-}
-
-// =============================================================================
-void Bytestream::writeString (str val) {
-	growToFit (val.length() + 1);
-
-	for (qchar c : val)
-		doWrite (c.toLatin1());
-
-	doWrite ('\0');
-}
-
-// =============================================================================
-bool Bytestream::tryMerge (const Bytestream& other) {
-	if (spaceLeft() < other.len())
-		return false;
-
-	for (ulong i = 0; i < other.len(); ++i)
-		writeByte (other[i]);
-
-	return true;
-}
-
-void Bytestream::merge (const Bytestream& other) {
-	growToFit (other.len());
-
-	if (!tryMerge (other)) {
-		// Shouldn't happen
-		fprint (stderr, "ByteStream: Not enough space for merge (%1 bytes left, need %2)",
-				spaceLeft(), other.len());
-		abort();
-	}
-}
-
-const uint8* Bytestream::data() const {
-	return m_data;
-}
--- a/src/bytestream.h	Sun Aug 11 13:38:12 2013 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- *  ZanDemo: Zandronum demo launcher
- *  Copyright (C) 2013 Santeri Piippo
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef BYTESTREAM_H
-#define BYTESTREAM_H
-
-#include "types.h"
-
-class Bytestream {
-private:
-	uint8* m_data;
-	uint8* m_ptr;
-	ulong m_size, m_len;
-	
-	void doWrite (uint8_t val);
-	
-public:
-	Bytestream (ulong len = 2048);
-	Bytestream (const char* data, ulong len);
-	
-	void init (const char* data, ulong len);
-	void rewind ();
-	void seek (ulong pos);
-	void clear ();
-	void merge (const Bytestream& other);
-	bool tryMerge (const Bytestream& other);
-	void resize (ulong len);
-	size_t len () const;
-	ulong bytesLeft () const;
-	ulong spaceLeft () const;
-	void growToFit (ulong bytes);
-	const uint8* data () const;
-	
-	bool readBytes (uint8 numbytes, uint8* val);
-	bool readByte (uint8& val);
-	bool readShort (uint16& val);
-	bool readLong (uint32& val);
-	bool readString (str& val);
-	bool readFloat (float& val);
-	
-	void writeBytes (uint8 numbytes, const uint8* val);
-	void writeByte (uint8 val);
-	void writeShort (uint16 val);
-	void writeLong (uint32 val);
-	void writeFloat (float val);
-	void writeString (str val);
-	
-	Bytestream& operator<< (const Bytestream& other) {
-		merge (other);
-		return *this;
-	}
-	
-	uint8& subscript (ulong idx);
-	const uint8& const_subscript (ulong idx) const;
-	
-	uint8& operator[] (ulong idx) {
-		return subscript (idx);
-	}
-	
-	const uint8& operator[] (ulong idx) const {
-		return const_subscript (idx);
-	}
-};
-
-#endif // BYTESTREAM_H
\ No newline at end of file
--- a/src/demo.cpp	Sun Aug 11 13:38:12 2013 +0300
+++ b/src/demo.cpp	Sun Aug 11 14:04:03 2013 +0300
@@ -21,7 +21,6 @@
 #include <QMessageBox>
 #include <QProcess>
 #include "demo.h"
-#include "bytestream.h"
 #include "misc.h"
 #include "ui_demoprompt.h"
 #include "prompts.h"
@@ -101,38 +100,37 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-#ifdef _WIN32
-# define FILE_FLAGS "rb"
-#else
-# define FILE_FLAGS "r"
-#endif // _WIN32
+QDataStream& operator>> (QDataStream& stream, str& out) {
+	uint8 c;
+	out = "";
+	
+	for (stream >> c; c != '\0'; stream >> c)
+		out += c;
+	
+	return stream;
+}
 
+// =============================================================================
+// -----------------------------------------------------------------------------
 int launchDemo (str path) {
-	FILE* fp = fopen (path.toStdString().c_str(), FILE_FLAGS);
+	QFile f (path);
 	
-	if (!fp) {
+	if (!f.open (QIODevice::ReadOnly)) {
 		error (fmt (tr ("Couldn't open '%1' for reading: %2"), path, strerror (errno)));
 		return 1;
 	}
 	
-	fseek (fp, 0, SEEK_END);
-	const size_t fsize = ftell (fp);
-	rewind (fp);
-	
-	char* buf = new char[fsize];
-	
-	const size_t bytesRead = fread (buf, 1, fsize, fp);
-	if (bytesRead != fsize) {
-		error (fmt (tr ("I/O error: %1 / %2 bytes read"), bytesRead, fsize));
-		delete[] buf;
-		return 2;
-	}
-
-	Bytestream s (buf, fsize);
-	delete[] buf;
+	QDataStream stream (&f);
+	stream.setByteOrder (QDataStream::LittleEndian);
 	
 	uint8 offset;
 	uint32 length;
+	uint16 zanversionID, numWads;
+	uint32 longSink;
+	str zanversion;
+	list<str> wads;
+	uint8 buildID;
+	bool ready = false;
 	
 	struct {
 		str netname, skin, className;
@@ -144,7 +142,8 @@
 	{
 		uint32 sig;
 		
-		if (!s.readLong (sig) || sig != g_demoSignature) {
+		stream >> sig;
+		if (sig != g_demoSignature) {
 			error (fmt (tr ("'%1' is not a Zandronum demo file!"), path));
 			return 3;
 		}
@@ -153,63 +152,63 @@
 	// Zandronum stores CLD_DEMOLENGTH after the signature. This is also the
 	// first demo enumerator, so we can determine the offset (which is variable!)
 	// from this byte
-	s.readByte (offset);
-	s.readLong (length);
-
-	uint16 zanversionID, numWads;
-	uint32 longSink;
-	str zanversion;
-	list<str> wads;
-	bool ready = false;
-	uint8 buildID;
+	stream >> offset
+	       >> length;
 	
 	// Read the demo header and get data
 	for (;;) {
 		uint8 header;
-		
-		if (!s.readByte (header))
-			break;
+		stream >> header;
+		print ("header: %1\n", (int) header);
 		
 		if (header == DemoBodyStart + offset) {
 			ready = true;
 			break;
 		} elif (header == DemoVersion + offset) {
-			s.readShort (zanversionID);
-			s.readString (zanversion);
+			print ("Read demo version\n");
+			stream >> zanversionID
+			       >> zanversion;
+			
+			print ("version ID: %1, version: %2\n", zanversionID, zanversion);
 			
 			if (zanversion.left (4) != "1.1-" && zanversion.left (6) != "1.1.1-")
-				s.readByte (buildID);
-			else
+				stream >> buildID;
+			else {
+				// Assume a release build if not supplied. The demo only got the
+				// "ZCLD" signature in the 1.1 release build, 1.1.1 had no
+				// development binaries and the build ID will be included in 1.1.2.
 				buildID = 1;
+			}
 			
-			s.readLong (longSink);  // rng seed - we don't need it
+			stream >> longSink; // rng seed - we don't need it
 		} elif (header == DemoUserInfo + offset) {
-			s.readString (userinfo.netname);
-			s.readByte (userinfo.gender);
-			s.readLong (userinfo.color);
-			s.readLong (userinfo.aimdist);
-			s.readString (userinfo.skin);
-			s.readLong (userinfo.railcolor);
-			s.readByte (userinfo.handicap);
-			s.readByte (userinfo.unlagged);
-			s.readByte (userinfo.respawnOnFire);
-			s.readByte (userinfo.ticsPerUpdate);
-			s.readByte (userinfo.connectionType);
-			s.readString (userinfo.className);
+			print ("Read userinfo\n");
+			stream >> userinfo.netname
+			       >> userinfo.gender
+			       >> userinfo.color
+			       >> userinfo.aimdist
+			       >> userinfo.skin
+			       >> userinfo.railcolor
+			       >> userinfo.handicap
+			       >> userinfo.unlagged
+			       >> userinfo.respawnOnFire
+			       >> userinfo.ticsPerUpdate
+			       >> userinfo.connectionType
+			       >> userinfo.className;
 		} elif (header == DemoWads + offset) {
 			str sink;
-			s.readShort (numWads);
+			stream >> numWads;
 			
 			for (uint8 i = 0; i < numWads; ++i) {
 				str wad;
-				s.readString (wad);
+				stream >> wad;
 				wads << wad;
 			}
 			
 			// The demo has two checksum strings. We're not interested
-			// in them though.
+			// in them though. Down the sink they go...
 			for (int i = 0; i < 2; ++i)
-				s.readString (sink);
+				stream >> sink;
 		} else {
 			error (fmt (tr ("Unknown header %1!\n"), (int) header));
 			return 3;

mercurial