Use template argument for list subtype, extract further information from chunks

This commit is contained in:
Matthias Schiffer 2015-02-01 03:21:57 +01:00
parent a6a2a62812
commit fc1fc8fbbc
9 changed files with 108 additions and 32 deletions

View file

@ -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:

View file

@ -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;
template<typename T>
std::shared_ptr<const T> get(const std::string &key) const {
return std::dynamic_pointer_cast<const T>(at(key));
}
const std::shared_ptr<const Tag> & get(const std::string &key) const {
return values.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...);
}
};

View file

@ -34,30 +34,39 @@
namespace MinedMap {
namespace NBT {
class ListTag : public Tag {
class ListTagBase : public Tag {
public:
virtual Type getType() const {
return Type::List;
}
virtual Type getSubtype() const = 0;
};
template<typename T>
class ListTag : public ListTagBase, public std::vector<std::shared_ptr<const T>> {
private:
friend class Tag;
std::vector<std::shared_ptr<const Tag>> value;
ListTag(Buffer *buffer) {
Type type = static_cast<Type>(buffer->get());
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;
}
};

View file

@ -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");
}
}

View file

@ -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;