From 8a8a41a800dfe9bdcab934d6b53d9c6defd4a457 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 1 Feb 2015 04:14:42 +0100 Subject: Parse chunk data on demand --- src/Buffer.hpp | 43 ++++++++++++++++++++++++++++--------------- src/NBT/ByteArrayTag.hpp | 20 ++++++++++++-------- src/NBT/ByteTag.hpp | 2 +- src/NBT/DoubleTag.hpp | 13 +++---------- src/NBT/FloatTag.hpp | 9 +++------ src/NBT/IntArrayTag.hpp | 20 ++++---------------- src/NBT/IntTag.hpp | 9 +++------ src/NBT/ListTag.hpp | 5 +---- src/NBT/LongTag.hpp | 13 +++---------- src/NBT/ShortTag.hpp | 7 +++---- src/NBT/StringTag.hpp | 13 ++++--------- src/NBT/Tag.cpp | 9 ++++----- src/World/Chunk.cpp | 1 - src/World/Chunk.hpp | 2 ++ 14 files changed, 71 insertions(+), 95 deletions(-) diff --git a/src/Buffer.hpp b/src/Buffer.hpp index c7fa9c7..3bf1ef0 100644 --- a/src/Buffer.hpp +++ b/src/Buffer.hpp @@ -40,34 +40,47 @@ private: size_t len; public: - Buffer(const uint8_t *data0, size_t len0) : data(data0), len(len0) {} + static uint16_t parse16(const uint8_t *buf) { + return (buf[0] << 8) | buf[1]; + } - uint8_t get() { - if (!len) - throw std::runtime_error("Buffer::get(): buffer underrun"); + static uint32_t parse32(const uint8_t *buf) { + return (uint32_t(buf[0]) << 24) | (uint32_t(buf[1]) << 16) | (uint32_t(buf[2]) << 8) | uint32_t(buf[3]); + } - data++; - len--; - return data[-1]; + static uint64_t parse64(const uint8_t *buf) { + return (uint64_t(buf[0]) << 56) | (uint64_t(buf[1]) << 48) | (uint64_t(buf[2]) << 40) | (uint64_t(buf[3]) << 32) + | (uint64_t(buf[4]) << 24) | (uint64_t(buf[5]) << 16) | (uint64_t(buf[6]) << 8) | uint64_t(buf[7]); } - std::string getString(size_t n) { + + Buffer(const uint8_t *data0, size_t len0) : data(data0), len(len0) {} + + const uint8_t * get(size_t n) { if (n > len) throw std::runtime_error("Buffer::get(): buffer underrun"); data += n; len -= n; - return std::string(reinterpret_cast(data - n), n); + return (data - n); } - void getData(void *buf, size_t n) { - if (n > len) - throw std::runtime_error("Buffer::get(): buffer underrun"); + uint8_t get8() { + return *get(1); + } - data += n; - len -= n; - std::memcpy(buf, data - n, n); + uint16_t get16() { + return parse16(get(2)); + } + + uint32_t get32() { + return parse32(get(4)); + } + + uint64_t get64() { + return parse64(get(8)); } + }; } diff --git a/src/NBT/ByteArrayTag.hpp b/src/NBT/ByteArrayTag.hpp index ee0d7d1..2081759 100644 --- a/src/NBT/ByteArrayTag.hpp +++ b/src/NBT/ByteArrayTag.hpp @@ -38,22 +38,26 @@ class ByteArrayTag : public Tag { private: friend class Tag; - std::vector value; + uint32_t len; + const uint8_t *value; ByteArrayTag(Buffer *buffer) { - uint32_t len = uint32_t(buffer->get()) << 24; - len |= uint32_t(buffer->get()) << 16; - len |= uint32_t(buffer->get()) << 8; - len |= uint32_t(buffer->get()); - - value.resize(len); - buffer->getData(value.data(), len); + len = buffer->get32(); + value = buffer->get(len); } public: virtual Type getType() const { return Type::ByteArray; } + + uint32_t getLength() const { + return len; + } + + const uint8_t & operator[](size_t i) const { + return value[i]; + } }; } diff --git a/src/NBT/ByteTag.hpp b/src/NBT/ByteTag.hpp index cc4aba9..64bdaa1 100644 --- a/src/NBT/ByteTag.hpp +++ b/src/NBT/ByteTag.hpp @@ -39,7 +39,7 @@ private: uint8_t value; ByteTag(Buffer *buffer) { - value = buffer->get(); + value = buffer->get8(); } public: diff --git a/src/NBT/DoubleTag.hpp b/src/NBT/DoubleTag.hpp index 327dcf5..dace193 100644 --- a/src/NBT/DoubleTag.hpp +++ b/src/NBT/DoubleTag.hpp @@ -36,17 +36,10 @@ class DoubleTag : public Tag { private: friend class Tag; + const uint8_t *ptr; + DoubleTag(Buffer *buffer) { - uint64_t value; - - value = uint64_t(buffer->get()) << 56; - value |= uint64_t(buffer->get()) << 48; - value |= uint64_t(buffer->get()) << 40; - value |= uint64_t(buffer->get()) << 32; - value |= uint64_t(buffer->get()) << 24; - value |= uint64_t(buffer->get()) << 16; - value |= uint64_t(buffer->get()) << 8; - value |= uint64_t(buffer->get()); + ptr = buffer->get(8); } public: diff --git a/src/NBT/FloatTag.hpp b/src/NBT/FloatTag.hpp index 8859f94..ad9cc64 100644 --- a/src/NBT/FloatTag.hpp +++ b/src/NBT/FloatTag.hpp @@ -36,13 +36,10 @@ class FloatTag : public Tag { private: friend class Tag; - FloatTag(Buffer *buffer) { - uint32_t value; + const uint8_t *ptr; - value = uint32_t(buffer->get()) << 24; - value |= uint32_t(buffer->get()) << 16; - value |= uint32_t(buffer->get()) << 8; - value |= uint32_t(buffer->get()); + FloatTag(Buffer *buffer) { + ptr = buffer->get(4); } public: diff --git a/src/NBT/IntArrayTag.hpp b/src/NBT/IntArrayTag.hpp index e9b0d3d..22f84b2 100644 --- a/src/NBT/IntArrayTag.hpp +++ b/src/NBT/IntArrayTag.hpp @@ -38,24 +38,12 @@ class IntArrayTag : public Tag { private: friend class Tag; - std::vector value; + uint32_t len; + const uint8_t *ptr; IntArrayTag(Buffer *buffer) { - uint32_t len = uint32_t(buffer->get()) << 24; - len |= uint32_t(buffer->get()) << 16; - len |= uint32_t(buffer->get()) << 8; - len |= uint32_t(buffer->get()); - - value.resize(len); - - for (uint32_t i = 0; i < len; i++) { - uint32_t v = uint32_t(buffer->get()) << 24; - v |= uint32_t(buffer->get()) << 16; - v |= uint32_t(buffer->get()) << 8; - v |= uint32_t(buffer->get()); - - value[i] = v; - } + len = buffer->get32(); + ptr = buffer->get(4*len); } public: diff --git a/src/NBT/IntTag.hpp b/src/NBT/IntTag.hpp index 9e7b3db..b0337c7 100644 --- a/src/NBT/IntTag.hpp +++ b/src/NBT/IntTag.hpp @@ -36,13 +36,10 @@ class IntTag : public Tag { private: friend class Tag; - uint32_t value; + const uint8_t *ptr; IntTag(Buffer *buffer) { - value = uint32_t(buffer->get()) << 24; - value |= uint32_t(buffer->get()) << 16; - value |= uint32_t(buffer->get()) << 8; - value |= uint32_t(buffer->get()); + ptr = buffer->get(4); } public: @@ -51,7 +48,7 @@ public: } uint32_t getValue() const { - return value; + return Buffer::parse32(ptr); } }; diff --git a/src/NBT/ListTag.hpp b/src/NBT/ListTag.hpp index 1a48062..757a0aa 100644 --- a/src/NBT/ListTag.hpp +++ b/src/NBT/ListTag.hpp @@ -53,10 +53,7 @@ private: Type type; ListTag(Type type0, Buffer *buffer) : type(type0) { - uint32_t len = uint32_t(buffer->get()) << 24; - len |= uint32_t(buffer->get()) << 16; - len |= uint32_t(buffer->get()) << 8; - len |= uint32_t(buffer->get()); + uint32_t len = buffer->get32(); this->resize(len); diff --git a/src/NBT/LongTag.hpp b/src/NBT/LongTag.hpp index 6cd5f8f..b07bc1a 100644 --- a/src/NBT/LongTag.hpp +++ b/src/NBT/LongTag.hpp @@ -36,17 +36,10 @@ class LongTag : public Tag { private: friend class Tag; - uint64_t value; + const uint8_t *ptr; LongTag(Buffer *buffer) { - value = uint64_t(buffer->get()) << 56; - value |= uint64_t(buffer->get()) << 48; - value |= uint64_t(buffer->get()) << 40; - value |= uint64_t(buffer->get()) << 32; - value |= uint64_t(buffer->get()) << 24; - value |= uint64_t(buffer->get()) << 16; - value |= uint64_t(buffer->get()) << 8; - value |= uint64_t(buffer->get()); + ptr = buffer->get(8); } public: @@ -55,7 +48,7 @@ public: } uint64_t getValue() const { - return value; + return Buffer::parse64(ptr); } }; diff --git a/src/NBT/ShortTag.hpp b/src/NBT/ShortTag.hpp index a44ca9b..7415317 100644 --- a/src/NBT/ShortTag.hpp +++ b/src/NBT/ShortTag.hpp @@ -36,11 +36,10 @@ class ShortTag : public Tag { private: friend class Tag; - uint16_t value; + const uint8_t *ptr; ShortTag(Buffer *buffer) { - value = buffer->get() << 8; - value |= buffer->get(); + ptr = buffer->get(2); } public: @@ -49,7 +48,7 @@ public: } uint16_t getValue() const { - return value; + return Buffer::parse16(ptr); } }; diff --git a/src/NBT/StringTag.hpp b/src/NBT/StringTag.hpp index 0144081..42432f2 100644 --- a/src/NBT/StringTag.hpp +++ b/src/NBT/StringTag.hpp @@ -36,23 +36,18 @@ class StringTag : public Tag { private: friend class Tag; - std::string value; + uint16_t len; + const uint8_t *ptr; StringTag(Buffer *buffer) { - uint16_t len = buffer->get() << 8; - len |= buffer->get(); - - value = buffer->getString(len); + len = buffer->get16(); + ptr = buffer->get(len); } public: virtual Type getType() const { return Type::String; } - - const std::string & getValue() const { - return value; - } }; } diff --git a/src/NBT/Tag.cpp b/src/NBT/Tag.cpp index 1829dc5..c75cb9f 100644 --- a/src/NBT/Tag.cpp +++ b/src/NBT/Tag.cpp @@ -90,7 +90,7 @@ std::shared_ptr Tag::readTag(Type type, Buffer *buffer) { } std::shared_ptr Tag::readList(Buffer *buffer) { - Type type = static_cast(buffer->get()); + Type type = static_cast(buffer->get8()); switch (type) { case Type::End: @@ -135,13 +135,12 @@ std::shared_ptr Tag::readList(Buffer *buffer) { } std::pair> Tag::readNamedTag(Buffer *buffer) { - Type type = static_cast(buffer->get()); + Type type = static_cast(buffer->get8()); if (type == Type::End) return std::make_pair("", std::shared_ptr(new EndTag())); - uint16_t len = buffer->get() << 8; - len |= buffer->get(); - std::string name = buffer->getString(len); + uint16_t len = buffer->get16(); + std::string name(reinterpret_cast(buffer->get(len)), len); return std::make_pair(name, readTag(type, buffer)); } diff --git a/src/World/Chunk.cpp b/src/World/Chunk.cpp index fb46466..db286ee 100644 --- a/src/World/Chunk.cpp +++ b/src/World/Chunk.cpp @@ -82,7 +82,6 @@ Chunk::Chunk(uint8_t *buffer, size_t buflen) { if (format != 2) throw std::invalid_argument("unknown chunk format"); - UniqueCPtr data; size_t len; std::tie(data, len) = inflateChunk(buffer+5, size-1); diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp index 3ed6cf4..5b0ecdb 100644 --- a/src/World/Chunk.hpp +++ b/src/World/Chunk.hpp @@ -43,6 +43,8 @@ public: static const size_t SIZE = 16; private: + UniqueCPtr data; + static std::pair, size_t> inflateChunk(uint8_t *data, size_t len); std::shared_ptr> sections; -- cgit v1.2.3