diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2018-07-21 18:07:45 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2018-07-21 18:11:59 +0200 |
commit | f1f783877f0f8338a225244faff4e40efe10a4ce (patch) | |
tree | e071d5df7024fbc3c72713517672f217096ea47f /src/NBT | |
parent | 315bb38444b8e363b4d8f2702d45d42fa585f619 (diff) | |
download | MinedMap-f1f783877f0f8338a225244faff4e40efe10a4ce.tar MinedMap-f1f783877f0f8338a225244faff4e40efe10a4ce.zip |
NBT: rework type system
Diffstat (limited to 'src/NBT')
-rw-r--r-- | src/NBT/ByteArrayTag.hpp | 8 | ||||
-rw-r--r-- | src/NBT/ByteTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/CompoundTag.hpp | 10 | ||||
-rw-r--r-- | src/NBT/DoubleTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/EndTag.hpp | 9 | ||||
-rw-r--r-- | src/NBT/FloatTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/IntArrayTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/IntTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/ListTag.hpp | 31 | ||||
-rw-r--r-- | src/NBT/LongArrayTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/LongTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/ShortTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/StringTag.hpp | 7 | ||||
-rw-r--r-- | src/NBT/Tag.cpp | 194 | ||||
-rw-r--r-- | src/NBT/Tag.hpp | 63 |
15 files changed, 155 insertions, 223 deletions
diff --git a/src/NBT/ByteArrayTag.hpp b/src/NBT/ByteArrayTag.hpp index 1e4f2f9..0d58dc8 100644 --- a/src/NBT/ByteArrayTag.hpp +++ b/src/NBT/ByteArrayTag.hpp @@ -40,12 +40,16 @@ private: const uint8_t *value; public: + static const MakeType<ByteArrayTag> Type; + + ByteArrayTag(Buffer *buffer) { len = buffer->get32(); value = buffer->get(len); } - virtual Type getType() const { - return Type::ByteArray; + + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &indent) const { diff --git a/src/NBT/ByteTag.hpp b/src/NBT/ByteTag.hpp index 28b8b1a..c578b9c 100644 --- a/src/NBT/ByteTag.hpp +++ b/src/NBT/ByteTag.hpp @@ -37,12 +37,15 @@ private: uint8_t value; public: + static const MakeType<ByteTag> Type; + + ByteTag(Buffer *buffer) { value = buffer->get8(); } - virtual Type getType() const { - return Type::Byte; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &) const { diff --git a/src/NBT/CompoundTag.hpp b/src/NBT/CompoundTag.hpp index 310b995..68e2390 100644 --- a/src/NBT/CompoundTag.hpp +++ b/src/NBT/CompoundTag.hpp @@ -26,6 +26,7 @@ #pragma once +#include "EndTag.hpp" #include "Tag.hpp" #include <string> @@ -37,18 +38,21 @@ namespace NBT { class CompoundTag : public Tag, public std::unordered_map<std::string, std::shared_ptr<const Tag>> { public: + static const MakeType<CompoundTag> Type; + + CompoundTag(Buffer *buffer) { while (true) { std::pair<std::string, std::shared_ptr<const Tag>> v = Tag::readNamedTag(buffer); - if (v.second->getType() == Type::End) + if (v.second->getType() == EndTag::Type) break; insert(std::move(v)); } } - virtual Type getType() const { - return Type::Compound; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &indent) const { diff --git a/src/NBT/DoubleTag.hpp b/src/NBT/DoubleTag.hpp index 3dfdb74..b83efe2 100644 --- a/src/NBT/DoubleTag.hpp +++ b/src/NBT/DoubleTag.hpp @@ -37,12 +37,15 @@ private: const uint8_t *ptr; public: + static const MakeType<DoubleTag> Type; + + DoubleTag(Buffer *buffer) { ptr = buffer->get(8); } - virtual Type getType() const { - return Type::Double; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &) const { diff --git a/src/NBT/EndTag.hpp b/src/NBT/EndTag.hpp index 5f771fd..167412a 100644 --- a/src/NBT/EndTag.hpp +++ b/src/NBT/EndTag.hpp @@ -34,10 +34,13 @@ namespace NBT { class EndTag : public Tag { public: - EndTag() {} + static const MakeType<EndTag> Type; - virtual Type getType() const { - return Type::End; + + EndTag(Buffer *) {} + + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream&, const std::string &) const { diff --git a/src/NBT/FloatTag.hpp b/src/NBT/FloatTag.hpp index 4442f1a..8748bc6 100644 --- a/src/NBT/FloatTag.hpp +++ b/src/NBT/FloatTag.hpp @@ -36,12 +36,15 @@ class FloatTag : public Tag { const uint8_t *ptr; public: + static const MakeType<FloatTag> Type; + + FloatTag(Buffer *buffer) { ptr = buffer->get(4); } - virtual Type getType() const { - return Type::Float; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &) const { diff --git a/src/NBT/IntArrayTag.hpp b/src/NBT/IntArrayTag.hpp index b7a27b4..67c25b1 100644 --- a/src/NBT/IntArrayTag.hpp +++ b/src/NBT/IntArrayTag.hpp @@ -40,13 +40,16 @@ private: const uint8_t *ptr; public: + static const MakeType<IntArrayTag> Type; + + IntArrayTag(Buffer *buffer) { len = buffer->get32(); ptr = buffer->get(4*len); } - virtual Type getType() const { - return Type::IntArray; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &indent) const { diff --git a/src/NBT/IntTag.hpp b/src/NBT/IntTag.hpp index 6514546..e6babd0 100644 --- a/src/NBT/IntTag.hpp +++ b/src/NBT/IntTag.hpp @@ -37,12 +37,15 @@ private: const uint8_t *ptr; public: + static const MakeType<IntTag> Type; + + IntTag(Buffer *buffer) { ptr = buffer->get(4); } - virtual Type getType() const { - return Type::Int; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &) const { diff --git a/src/NBT/ListTag.hpp b/src/NBT/ListTag.hpp index d86abdb..7276923 100644 --- a/src/NBT/ListTag.hpp +++ b/src/NBT/ListTag.hpp @@ -34,34 +34,29 @@ namespace MinedMap { namespace NBT { +class ListTag : public Tag, public std::vector<std::shared_ptr<const Tag>> { +private: + const TagType *subtype; -class ListTagBase : public Tag { public: - virtual Type getType() const { - return Type::List; - } + static const MakeType<ListTag> Type; - virtual Type getSubtype() const = 0; -}; + ListTag(Buffer *buffer) { + subtype = &getTypeById(buffer->get8()); -template<typename T> -class ListTag : public ListTagBase, public std::vector<std::shared_ptr<const T>> { -private: - Type type; - -public: - ListTag(Type type0, Buffer *buffer) : type(type0) { uint32_t len = buffer->get32(); - this->resize(len); - for (uint32_t i = 0; i < len; i++) - (*this)[i] = std::static_pointer_cast<const T>(Tag::readTag(type, buffer)); + push_back(subtype->read(buffer)); + } + + virtual const TagType & getType() const { + return Type; } - virtual Type getSubtype() const { - return type; + virtual const TagType & getSubtype() const { + return *subtype; } virtual void print(std::ostream& os, const std::string &indent) const { diff --git a/src/NBT/LongArrayTag.hpp b/src/NBT/LongArrayTag.hpp index 1ca3ae6..545798f 100644 --- a/src/NBT/LongArrayTag.hpp +++ b/src/NBT/LongArrayTag.hpp @@ -40,13 +40,16 @@ private: const uint8_t *ptr; public: + static const MakeType<LongArrayTag> Type; + + LongArrayTag(Buffer *buffer) { len = buffer->get32(); ptr = buffer->get(8*len); } - virtual Type getType() const { - return Type::LongArray; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &indent) const { diff --git a/src/NBT/LongTag.hpp b/src/NBT/LongTag.hpp index f600d8e..05f6bc2 100644 --- a/src/NBT/LongTag.hpp +++ b/src/NBT/LongTag.hpp @@ -37,12 +37,15 @@ private: const uint8_t *ptr; public: + static const MakeType<LongTag> Type; + + LongTag(Buffer *buffer) { ptr = buffer->get(8); } - virtual Type getType() const { - return Type::Long; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &) const { diff --git a/src/NBT/ShortTag.hpp b/src/NBT/ShortTag.hpp index c66dc05..593a1ed 100644 --- a/src/NBT/ShortTag.hpp +++ b/src/NBT/ShortTag.hpp @@ -37,12 +37,15 @@ private: const uint8_t *ptr; public: + static const MakeType<ShortTag> Type; + + ShortTag(Buffer *buffer) { ptr = buffer->get(2); } - virtual Type getType() const { - return Type::Short; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &) const { diff --git a/src/NBT/StringTag.hpp b/src/NBT/StringTag.hpp index 2fda6d3..8672b73 100644 --- a/src/NBT/StringTag.hpp +++ b/src/NBT/StringTag.hpp @@ -38,13 +38,16 @@ private: const uint8_t *ptr; public: + static const MakeType<StringTag> Type; + + StringTag(Buffer *buffer) { len = buffer->get16(); ptr = buffer->get(len); } - virtual Type getType() const { - return Type::String; + virtual const TagType & getType() const { + return Type; } virtual void print(std::ostream& os, const std::string &) const { diff --git a/src/NBT/Tag.cpp b/src/NBT/Tag.cpp index 31f1420..e8c429f 100644 --- a/src/NBT/Tag.cpp +++ b/src/NBT/Tag.cpp @@ -41,176 +41,50 @@ #include "LongArrayTag.hpp" -#include <stdexcept> - - namespace MinedMap { namespace NBT { -std::shared_ptr<const Tag> Tag::readTag(Type type, Buffer *buffer) { - switch (type) { - case Type::End: - return std::make_shared<EndTag>(); - - case Type::Byte: - return std::make_shared<ByteTag>(buffer); - - case Type::Short: - return std::make_shared<ShortTag>(buffer); - - case Type::Int: - return std::make_shared<IntTag>(buffer); - - case Type::Long: - return std::make_shared<LongTag>(buffer); - - case Type::Float: - return std::make_shared<FloatTag>(buffer); - - case Type::Double: - return std::make_shared<DoubleTag>(buffer); - - case Type::ByteArray: - return std::make_shared<ByteArrayTag>(buffer); - - case Type::String: - return std::make_shared<StringTag>(buffer); - - case Type::List: - return readList(buffer); - - case Type::Compound: - return std::make_shared<CompoundTag>(buffer); - - case Type::IntArray: - return std::make_shared<IntArrayTag>(buffer); - - case Type::LongArray: - return std::make_shared<LongArrayTag>(buffer); - - default: - throw std::runtime_error("Tag::readTag: unknown tag type"); - } -} - -std::shared_ptr<const Tag> Tag::readList(Buffer *buffer) { - Type type = static_cast<Type>(buffer->get8()); - - switch (type) { - case Type::End: - return std::make_shared<ListTag<EndTag>>(type, buffer); - - case Type::Byte: - return std::make_shared<ListTag<ByteTag>>(type, buffer); - - case Type::Short: - return std::make_shared<ListTag<ShortTag>>(type, buffer); - - case Type::Int: - return std::make_shared<ListTag<IntTag>>(type, buffer); - - case Type::Long: - return std::make_shared<ListTag<LongTag>>(type, buffer); - - case Type::Float: - return std::make_shared<ListTag<FloatTag>>(type, buffer); - - case Type::Double: - return std::make_shared<ListTag<DoubleTag>>(type, buffer); +const Tag::MakeType<EndTag> EndTag::Type("End"); +const Tag::MakeType<ByteTag> ByteTag::Type("Byte"); +const Tag::MakeType<ShortTag> ShortTag::Type("Short"); +const Tag::MakeType<IntTag> IntTag::Type("Int"); +const Tag::MakeType<LongTag> LongTag::Type("Long"); +const Tag::MakeType<FloatTag> FloatTag::Type("Float"); +const Tag::MakeType<DoubleTag> DoubleTag::Type("Double"); +const Tag::MakeType<ByteArrayTag> ByteArrayTag::Type("ByteArray"); +const Tag::MakeType<StringTag> StringTag::Type("String"); +const Tag::MakeType<ListTag> ListTag::Type("List"); +const Tag::MakeType<CompoundTag> CompoundTag::Type("Compound"); +const Tag::MakeType<IntArrayTag> IntArrayTag::Type("IntArray"); +const Tag::MakeType<LongArrayTag> LongArrayTag::Type("LongArray"); + + +const std::vector<const TagType *> Tag::types = { + &EndTag::Type, + &ByteTag::Type, + &ShortTag::Type, + &IntTag::Type, + &LongTag::Type, + &FloatTag::Type, + &DoubleTag::Type, + &ByteArrayTag::Type, + &StringTag::Type, + &ListTag::Type, + &CompoundTag::Type, + &IntArrayTag::Type, + &LongArrayTag::Type, +}; - case Type::ByteArray: - return std::make_shared<ListTag<ByteArrayTag>>(type, buffer); - - case Type::String: - return std::make_shared<ListTag<StringTag>>(type, buffer); - - case Type::List: - return std::make_shared<ListTag<ListTagBase>>(type, buffer); - - case Type::Compound: - return std::make_shared<ListTag<CompoundTag>>(type, buffer); - - case Type::IntArray: - return std::make_shared<ListTag<IntArrayTag>>(type, buffer); - - case Type::LongArray: - return std::make_shared<ListTag<LongArrayTag>>(type, buffer); - - default: - throw std::runtime_error("Tag::readList: unknown tag type"); - } -} std::pair<std::string, std::shared_ptr<const Tag>> Tag::readNamedTag(Buffer *buffer) { - Type type = static_cast<Type>(buffer->get8()); - if (type == Type::End) - return std::make_pair("", std::shared_ptr<EndTag>(new EndTag())); + const TagType &type = getTypeById(buffer->get8()); + if (type == EndTag::Type) + return std::make_pair("", std::make_shared<EndTag>(buffer)); uint16_t len = buffer->get16(); std::string name(reinterpret_cast<const char*>(buffer->get(len)), len); - return std::make_pair(name, readTag(type, buffer)); -} - -std::ostream& operator<<(std::ostream& os, Tag::Type type) { - switch (type) { - case Tag::Type::End: - os << "End"; - break; - - case Tag::Type::Byte: - os << "Byte"; - break; - - case Tag::Type::Short: - os << "Short"; - break; - - case Tag::Type::Int: - os << "Int"; - break; - - case Tag::Type::Long: - os << "Long"; - break; - - case Tag::Type::Float: - os << "Float"; - break; - - case Tag::Type::Double: - os << "Double"; - break; - - case Tag::Type::ByteArray: - os << "ByteArray"; - break; - - case Tag::Type::String: - os << "String"; - break; - - case Tag::Type::List: - os << "List"; - break; - - case Tag::Type::Compound: - os << "Compound"; - break; - - case Tag::Type::IntArray: - os << "IntArray"; - break; - - case Tag::Type::LongArray: - os << "LongArray"; - break; - - default: - os.setstate(std::ios_base::failbit); - } - - return os; + return std::make_pair(name, type.read(buffer)); } } diff --git a/src/NBT/Tag.hpp b/src/NBT/Tag.hpp index b0c20af..3fb824b 100644 --- a/src/NBT/Tag.hpp +++ b/src/NBT/Tag.hpp @@ -29,6 +29,7 @@ #include <cstdint> #include <memory> #include <ostream> +#include <vector> #include "../Buffer.hpp" @@ -36,37 +37,61 @@ namespace MinedMap { namespace NBT { +class Tag; + +class TagType { +public: + TagType() = default; + TagType(const TagType&) = delete; + TagType & operator=(const TagType&) = delete; + + virtual const char * getName() const = 0; + virtual std::shared_ptr<const Tag> read(Buffer *buffer) const = 0; + + bool operator==(const TagType &type) const { + return this == &type; + } +}; + class Tag { private: - static std::shared_ptr<const Tag> readList(Buffer *buffer); + static const std::vector<const TagType *> types; -public: - enum class Type { - End = 0, - Byte = 1, - Short = 2, - Int = 3, - Long = 4, - Float = 5, - Double = 6, - ByteArray = 7, - String = 8, - List = 9, - Compound = 10, - IntArray = 11, - LongArray = 12, +protected: + template<typename T> + class MakeType : public TagType { + private: + const char *name; + + public: + MakeType(const char *name0) : name(name0) {} + + virtual const char * getName() const { + return name; + } + + virtual std::shared_ptr<const Tag> read(Buffer *buffer) const { + return std::make_shared<T>(buffer); + } }; - static std::shared_ptr<const Tag> readTag(Type type, Buffer *buffer); + + static const TagType & getTypeById(uint8_t id) { + return *types.at(id); + } + +public: static std::pair<std::string, std::shared_ptr<const Tag>> readNamedTag(Buffer *buffer); - virtual Type getType() const = 0; + virtual const TagType & getType() const = 0; virtual void print(std::ostream& os, const std::string &indent) const = 0; virtual ~Tag() {} }; -std::ostream& operator<<(std::ostream& os, Tag::Type type); +static inline std::ostream& operator<<(std::ostream& os, const TagType &type) { + return os << type.getName(); +} static inline std::ostream& operator<<(std::ostream& os, const Tag &tag) { os << tag.getType() << " "; |