summaryrefslogtreecommitdiffstats
path: root/src/NBT
diff options
context:
space:
mode:
Diffstat (limited to 'src/NBT')
-rw-r--r--src/NBT/ByteArrayTag.hpp4
-rw-r--r--src/NBT/CompoundTag.hpp24
-rw-r--r--src/NBT/ListTag.hpp29
-rw-r--r--src/NBT/Tag.cpp49
-rw-r--r--src/NBT/Tag.hpp4
5 files changed, 80 insertions, 30 deletions
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<std::string, std::shared_ptr<const Tag>> {
private:
friend class Tag;
- std::unordered_map<std::string, std::shared_ptr<const Tag>> values;
-
CompoundTag(Buffer *buffer) {
while (true) {
std::pair<std::string, std::shared_ptr<const Tag>> 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<std::string, std::shared_ptr<const Tag>> & getValues() const {
- return values;
- }
-
- const std::shared_ptr<const Tag> & get(const std::string &key) const {
- return values.at(key);
+ template<typename T>
+ std::shared_ptr<const T> get(const std::string &key) const {
+ return std::dynamic_pointer_cast<const T>(at(key));
}
- template<typename... Args> const std::shared_ptr<const Tag> & get(const std::string &key, const Args &...args) const {
- std::shared_ptr<const CompoundTag> tag = std::dynamic_pointer_cast<const CompoundTag>(get(key));
+ template<typename T, typename... Args>
+ std::shared_ptr<const T> get(const std::string &key, const Args &...args) const {
+ std::shared_ptr<const CompoundTag> tag = get<CompoundTag>(key);
if (!tag)
- return std::shared_ptr<Tag>(nullptr);
+ return std::shared_ptr<const T>();
- tag->get(args...);
+ return tag->get<T>(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<std::shared_ptr<const Tag>> 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<Type>(buffer->get());
+template<typename T>
+class ListTag : public ListTagBase, public std::vector<std::shared_ptr<const T>> {
+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<const T>(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<const Tag> Tag::readTag(Type type, Buffer *buffer) {
return std::shared_ptr<StringTag>(new StringTag(buffer));
case Type::List:
- return std::shared_ptr<ListTag>(new ListTag(buffer));
+ return readList(buffer);
case Type::Compound:
return std::shared_ptr<CompoundTag>(new CompoundTag(buffer));
@@ -85,7 +85,52 @@ std::shared_ptr<const Tag> Tag::readTag(Type type, Buffer *buffer) {
return std::shared_ptr<IntArrayTag>(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<const Tag> Tag::readList(Buffer *buffer) {
+ Type type = static_cast<Type>(buffer->get());
+
+ switch (type) {
+ case Type::End:
+ return std::shared_ptr<Tag>(new ListTag<EndTag>(type, buffer));
+
+ case Type::Byte:
+ return std::shared_ptr<Tag>(new ListTag<ByteTag>(type, buffer));
+
+ case Type::Short:
+ return std::shared_ptr<Tag>(new ListTag<ShortTag>(type, buffer));
+
+ case Type::Int:
+ return std::shared_ptr<Tag>(new ListTag<IntTag>(type, buffer));
+
+ case Type::Long:
+ return std::shared_ptr<Tag>(new ListTag<LongTag>(type, buffer));
+
+ case Type::Float:
+ return std::shared_ptr<Tag>(new ListTag<FloatTag>(type, buffer));
+
+ case Type::Double:
+ return std::shared_ptr<Tag>(new ListTag<DoubleTag>(type, buffer));
+
+ case Type::ByteArray:
+ return std::shared_ptr<Tag>(new ListTag<ByteArrayTag>(type, buffer));
+
+ case Type::String:
+ return std::shared_ptr<Tag>(new ListTag<StringTag>(type, buffer));
+
+ case Type::List:
+ return std::shared_ptr<Tag>(new ListTag<ListTagBase>(type, buffer));
+
+ case Type::Compound:
+ return std::shared_ptr<Tag>(new ListTag<CompoundTag>(type, buffer));
+
+ case Type::IntArray:
+ return std::shared_ptr<Tag>(new ListTag<IntArrayTag>(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<const Tag> readList(Buffer *buffer);
+
public:
enum class Type {
End = 0,
@@ -54,7 +57,6 @@ public:
};
static std::shared_ptr<const Tag> readTag(Type type, Buffer *buffer);
-
static std::pair<std::string, std::shared_ptr<const Tag>> readNamedTag(Buffer *buffer);
virtual Type getType() const = 0;