# HG changeset patch # User Teemu Piippo # Date 1376219043 -10800 # Node ID 6bf57b4f42cd4fc006c5e29a1116a83037e7eba4 # Parent b41d74bacdeaf7255881073e9b15b846d2d9a580 Replaced the Bytestream class with QDataStream diff -r b41d74bacdea -r 6bf57b4f42cd src/bytestream.cpp --- 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 . - */ - -#include "bytestream.h" -#include "misc.h" -#include - -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 (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; -} diff -r b41d74bacdea -r 6bf57b4f42cd src/bytestream.h --- 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 . - */ - -#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 diff -r b41d74bacdea -r 6bf57b4f42cd src/demo.cpp --- 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 #include #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 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 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;