summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2018-07-21 18:07:45 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2018-07-21 18:11:59 +0200
commitf1f783877f0f8338a225244faff4e40efe10a4ce (patch)
treee071d5df7024fbc3c72713517672f217096ea47f
parent315bb38444b8e363b4d8f2702d45d42fa585f619 (diff)
downloadMinedMap-f1f783877f0f8338a225244faff4e40efe10a4ce.tar
MinedMap-f1f783877f0f8338a225244faff4e40efe10a4ce.zip
NBT: rework type system
-rw-r--r--src/NBT/ByteArrayTag.hpp8
-rw-r--r--src/NBT/ByteTag.hpp7
-rw-r--r--src/NBT/CompoundTag.hpp10
-rw-r--r--src/NBT/DoubleTag.hpp7
-rw-r--r--src/NBT/EndTag.hpp9
-rw-r--r--src/NBT/FloatTag.hpp7
-rw-r--r--src/NBT/IntArrayTag.hpp7
-rw-r--r--src/NBT/IntTag.hpp7
-rw-r--r--src/NBT/ListTag.hpp31
-rw-r--r--src/NBT/LongArrayTag.hpp7
-rw-r--r--src/NBT/LongTag.hpp7
-rw-r--r--src/NBT/ShortTag.hpp7
-rw-r--r--src/NBT/StringTag.hpp7
-rw-r--r--src/NBT/Tag.cpp194
-rw-r--r--src/NBT/Tag.hpp63
-rw-r--r--src/World/Chunk.cpp8
-rw-r--r--src/World/Chunk.hpp4
17 files changed, 162 insertions, 228 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() << " ";
diff --git a/src/World/Chunk.cpp b/src/World/Chunk.cpp
index 07e38a4..38ca496 100644
--- a/src/World/Chunk.cpp
+++ b/src/World/Chunk.cpp
@@ -44,8 +44,9 @@ Chunk::Chunk(const ChunkData *data) {
std::shared_ptr<const NBT::ByteTag> lightPopulatedTag = level->get<NBT::ByteTag>("LightPopulated");
bool lightPopulated = lightPopulatedTag && lightPopulatedTag->getValue();
- sections = assertValue(level->get<NBT::ListTag<NBT::CompoundTag>>("Sections"));
- maxY = (assertValue(sections->back()->get<NBT::ByteTag>("Y"))->getValue() + 1) * SIZE;
+ sections = assertValue(level->get<NBT::ListTag>("Sections"));
+ const NBT::CompoundTag *lastSection = assertValue(dynamic_cast<const NBT::CompoundTag *>(sections->back().get()));
+ maxY = (assertValue(lastSection->get<NBT::ByteTag>("Y"))->getValue() + 1) * SIZE;
std::shared_ptr<const NBT::ByteArrayTag> biomeTag = assertValue(level->get<NBT::ByteArrayTag>("Biomes"));
@@ -65,7 +66,8 @@ Chunk::Chunk(const ChunkData *data) {
std::memset(blockBlockLight.get(), 0, maxY * SIZE * SIZE / 2);
- for (auto &section : *sections) {
+ for (auto &sectionTag : *sections) {
+ const NBT::CompoundTag *section = assertValue(dynamic_cast<const NBT::CompoundTag *>(sectionTag.get()));
std::shared_ptr<const NBT::ByteArrayTag> blocks = assertValue(section->get<NBT::ByteArrayTag>("Blocks"));
std::shared_ptr<const NBT::ByteArrayTag> data = assertValue(section->get<NBT::ByteArrayTag>("Data"));
size_t Y = assertValue(section->get<NBT::ByteTag>("Y"))->getValue();
diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp
index d4213b3..4bd301d 100644
--- a/src/World/Chunk.hpp
+++ b/src/World/Chunk.hpp
@@ -52,7 +52,7 @@ public:
private:
std::shared_ptr<const NBT::CompoundTag> level;
- std::shared_ptr<const NBT::ListTag<NBT::CompoundTag>> sections;
+ std::shared_ptr<const NBT::ListTag> sections;
unsigned maxY;
@@ -107,7 +107,7 @@ public:
return *level;
}
- const NBT::ListTag<NBT::CompoundTag> & getSections() const {
+ const NBT::ListTag & getSections() const {
return *sections;
}