From fc1fc8fbbc9dd9534f40de348210ea66b6defe42 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 1 Feb 2015 03:21:57 +0100 Subject: Use template argument for list subtype, extract further information from chunks --- src/NBT/ByteArrayTag.hpp | 4 +--- src/NBT/CompoundTag.hpp | 24 ++++++++++-------------- src/NBT/ListTag.hpp | 29 ++++++++++++++++++---------- src/NBT/Tag.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++-- src/NBT/Tag.hpp | 4 +++- 5 files changed, 80 insertions(+), 30 deletions(-) (limited to 'src/NBT') diff --git a/src/NBT/ByteArrayTag.hpp b/src/NBT/ByteArrayTag.hpp index d5a6333..ee0d7d1 100644 --- a/src/NBT/ByteArrayTag.hpp +++ b/src/NBT/ByteArrayTag.hpp @@ -47,9 +47,7 @@ private: len |= uint32_t(buffer->get()); value.resize(len); - - for (uint32_t i = 0; i < len; i++) - value[i] = buffer->get(); + buffer->getData(value.data(), len); } public: diff --git a/src/NBT/CompoundTag.hpp b/src/NBT/CompoundTag.hpp index 18de1c6..28efc41 100644 --- a/src/NBT/CompoundTag.hpp +++ b/src/NBT/CompoundTag.hpp @@ -35,19 +35,17 @@ namespace MinedMap { namespace NBT { -class CompoundTag : public Tag { +class CompoundTag : public Tag, public std::unordered_map> { private: friend class Tag; - std::unordered_map> values; - CompoundTag(Buffer *buffer) { while (true) { std::pair> v = Tag::readNamedTag(buffer); if (v.second->getType() == Type::End) break; - values.insert(std::move(v)); + insert(std::move(v)); } } @@ -56,20 +54,18 @@ public: return Type::Compound; } - const std::unordered_map> & getValues() const { - return values; - } - - const std::shared_ptr & get(const std::string &key) const { - return values.at(key); + template + std::shared_ptr get(const std::string &key) const { + return std::dynamic_pointer_cast(at(key)); } - template const std::shared_ptr & get(const std::string &key, const Args &...args) const { - std::shared_ptr tag = std::dynamic_pointer_cast(get(key)); + template + std::shared_ptr get(const std::string &key, const Args &...args) const { + std::shared_ptr tag = get(key); if (!tag) - return std::shared_ptr(nullptr); + return std::shared_ptr(); - tag->get(args...); + return tag->get(args...); } }; diff --git a/src/NBT/ListTag.hpp b/src/NBT/ListTag.hpp index 67ba619..1a48062 100644 --- a/src/NBT/ListTag.hpp +++ b/src/NBT/ListTag.hpp @@ -34,30 +34,39 @@ namespace MinedMap { namespace NBT { -class ListTag : public Tag { -private: - friend class Tag; - std::vector> value; +class ListTagBase : public Tag { +public: + virtual Type getType() const { + return Type::List; + } + virtual Type getSubtype() const = 0; +}; - ListTag(Buffer *buffer) { - Type type = static_cast(buffer->get()); +template +class ListTag : public ListTagBase, public std::vector> { +private: + friend class Tag; + + 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()); - value.resize(len); + this->resize(len); for (uint32_t i = 0; i < len; i++) - value[i] = Tag::readTag(type, buffer); + (*this)[i] = std::static_pointer_cast(Tag::readTag(type, buffer)); } public: - virtual Type getType() const { - return Type::List; + virtual Type getSubtype() const { + return type; } }; diff --git a/src/NBT/Tag.cpp b/src/NBT/Tag.cpp index a2d57e3..1829dc5 100644 --- a/src/NBT/Tag.cpp +++ b/src/NBT/Tag.cpp @@ -76,7 +76,7 @@ std::shared_ptr Tag::readTag(Type type, Buffer *buffer) { return std::shared_ptr(new StringTag(buffer)); case Type::List: - return std::shared_ptr(new ListTag(buffer)); + return readList(buffer); case Type::Compound: return std::shared_ptr(new CompoundTag(buffer)); @@ -85,7 +85,52 @@ std::shared_ptr Tag::readTag(Type type, Buffer *buffer) { return std::shared_ptr(new IntArrayTag(buffer)); default: - throw std::runtime_error("Tag::read: unknown tag type"); + throw std::runtime_error("Tag::readTag: unknown tag type"); + } +} + +std::shared_ptr Tag::readList(Buffer *buffer) { + Type type = static_cast(buffer->get()); + + switch (type) { + case Type::End: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::Byte: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::Short: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::Int: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::Long: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::Float: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::Double: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::ByteArray: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::String: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::List: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::Compound: + return std::shared_ptr(new ListTag(type, buffer)); + + case Type::IntArray: + return std::shared_ptr(new ListTag(type, buffer)); + + default: + throw std::runtime_error("Tag::readList: unknown tag type"); } } diff --git a/src/NBT/Tag.hpp b/src/NBT/Tag.hpp index 077c508..a3c0c76 100644 --- a/src/NBT/Tag.hpp +++ b/src/NBT/Tag.hpp @@ -37,6 +37,9 @@ namespace MinedMap { namespace NBT { class Tag { +private: + static std::shared_ptr readList(Buffer *buffer); + public: enum class Type { End = 0, @@ -54,7 +57,6 @@ public: }; static std::shared_ptr readTag(Type type, Buffer *buffer); - static std::pair> readNamedTag(Buffer *buffer); virtual Type getType() const = 0; -- cgit v1.2.3