From 7744e18d8c1ebe4c9d85853956c2d4aca302bc59 Mon Sep 17 00:00:00 2001 From: zontreck Date: Tue, 30 Jul 2024 22:59:35 -0700 Subject: [PATCH] Start hooking stuff up! --- src/nbt/Accountant.cpp | 1 + src/nbt/ByteArrayTag.cpp | 2 +- src/nbt/ByteArrayTag.h | 2 +- src/nbt/ByteTag.cpp | 2 +- src/nbt/ByteTag.h | 2 +- src/nbt/CompoundTag.cpp | 263 +++++++++++++++++++++++++++++++++++++++ src/nbt/CompoundTag.h | 77 ++++++++++++ src/nbt/DoubleTag.cpp | 2 +- src/nbt/DoubleTag.h | 2 +- src/nbt/EndTag.cpp | 2 +- src/nbt/EndTag.h | 2 +- src/nbt/FloatTag.cpp | 2 +- src/nbt/FloatTag.h | 2 +- src/nbt/Tag.cpp | 14 ++- src/nbt/Tag.h | 16 +-- 15 files changed, 368 insertions(+), 23 deletions(-) create mode 100644 src/nbt/CompoundTag.cpp create mode 100644 src/nbt/CompoundTag.h diff --git a/src/nbt/Accountant.cpp b/src/nbt/Accountant.cpp index 52066e0..e0790dd 100644 --- a/src/nbt/Accountant.cpp +++ b/src/nbt/Accountant.cpp @@ -1,5 +1,6 @@ #include "Accountant.h" #include "Tag.h" +#include "CompoundTag.h" #include using namespace nbt; diff --git a/src/nbt/ByteArrayTag.cpp b/src/nbt/ByteArrayTag.cpp index 8f979fd..3eef88f 100644 --- a/src/nbt/ByteArrayTag.cpp +++ b/src/nbt/ByteArrayTag.cpp @@ -27,7 +27,7 @@ namespace nbt } } - void ByteArrayTag::writeValue(ByteLayer &data) + void ByteArrayTag::writeValue(ByteLayer &data) const { data.writeInt(static_cast(value.size())); for (int i : value) diff --git a/src/nbt/ByteArrayTag.h b/src/nbt/ByteArrayTag.h index d335c8a..2b68b25 100644 --- a/src/nbt/ByteArrayTag.h +++ b/src/nbt/ByteArrayTag.h @@ -21,7 +21,7 @@ namespace nbt // Override functions from the Tag class void readValue(ByteLayer &data) override; - void writeValue(ByteLayer &data) override; + void writeValue(ByteLayer &data) const override; TagType getTagType() const override; dynamic getValue() const; void setValue(const dynamic &val) override; diff --git a/src/nbt/ByteTag.cpp b/src/nbt/ByteTag.cpp index a4f3f87..e73f0dd 100644 --- a/src/nbt/ByteTag.cpp +++ b/src/nbt/ByteTag.cpp @@ -24,7 +24,7 @@ namespace nbt value = data.readByte(); } - void ByteTag::writeValue(ByteLayer &data) + void ByteTag::writeValue(ByteLayer &data) const { data.writeByte(value); } diff --git a/src/nbt/ByteTag.h b/src/nbt/ByteTag.h index 450ec2d..1e2153f 100644 --- a/src/nbt/ByteTag.h +++ b/src/nbt/ByteTag.h @@ -21,7 +21,7 @@ namespace nbt // Override functions from the Tag class void readValue(ByteLayer &data) override; - void writeValue(ByteLayer &data) override; + void writeValue(ByteLayer &data) const override; TagType getTagType() const override; dynamic getValue() const override; void setValue(const dynamic &val) override; diff --git a/src/nbt/CompoundTag.cpp b/src/nbt/CompoundTag.cpp new file mode 100644 index 0000000..d8fc1c8 --- /dev/null +++ b/src/nbt/CompoundTag.cpp @@ -0,0 +1,263 @@ +#include "CompoundTag.h" +#include "Tag.h" +#include +#include +#include +#include + +using namespace nbt; +using namespace std; + +namespace nbt { + + CompoundTag::CompoundTag() : Tag() { + // Constructor implementation + } + + CompoundTag::~CompoundTag() { + + } + + void CompoundTag::readValue(ByteLayer& data) { + value.clear(); + + while (true) { + Tag* tag = Tag::readNamedTag(data); + if (tag->getTagType() == TagType::End) { + return; + } + + tag->setParentTagType(TagType::Compound); + put(tag->getKey(), tag); + } + } + + void CompoundTag::writeValue(ByteLayer& data) const { + for (auto& [key, tag] : value) { + Tag::writeNamedTag(*tag, data); + } + data.writeByte(static_cast(TagType::End)); + } + + void CompoundTag::put(const std::string& name, Tag* tag) { + value[name] = tag; + tag->setKey(name); + tag->updateParent(this); + } + + Tag* CompoundTag::get(const std::string& name) const { + auto it = value.find(name); + if (it != value.end()) { + return it->second; + } + return nullptr; + } + + TagType CompoundTag::getTagType() const { + return TagType::Compound; + } + + void CompoundTag::setValue(const dynamic& val) { + // No specific implementation needed for this example + } + + dynamic CompoundTag::getValue() const { + return dynamic(); // Returning a default dynamic instance + } + + void CompoundTag::prettyPrint(int indent, bool recurse) const { + std::string indentStr(indent, '\t'); + std::cout << indentStr << Tag::getCanonicalName(getTagType()) << ": [" << value.size() << " entries]" << std::endl; + std::cout << indentStr << "{" << std::endl; + if (recurse) { + for (const auto& [key, tag] : value) { + tag->prettyPrint(indent + 1, true); + } + } + } + + void CompoundTag::endPrettyPrint(int indent) const { + std::cout << std::string(indent, '\t') << "}" << std::endl; + } + + void CompoundTag::writeStringifiedValue(StringBuilder& builder, int indent, bool isList) const { + builder.append(isList ? std::string(indent - 1, '\t') + "{\n" : "{\n"); + + bool firstEntry = true; + for (const auto& [key, tag] : value) { + if (!firstEntry) { + builder.append(",\n"); + } + Tag::writeStringifiedNamedTag(tag, builder, indent); + firstEntry = false; + } + builder.append("\n" + std::string(indent - 1, '\t') + "}"); + } + + void CompoundTag::readStringifiedValue(StringReader& reader) { + reader.expect("{"); + + while (reader.peek() != "}") { + Tag* tag = Tag::readStringifiedNamedTag(reader); + put(tag->getKey(), tag); + + if (reader.peek() == ",") reader.next(); + } + + reader.expect("}"); + } + + Tag* CompoundTag::operator[](const std::string& key) const { + auto it = value.find(key); + return (it != value.end()) ? it->second : nullptr; + } + + void CompoundTag::operator[]=(const std::string& key, Tag* tag) { + put(key, tag); + } + + void CompoundTag::addAll(const std::map& other) { + value.insert(other.begin(), other.end()); + for (auto& [key, tag] : other) { + tag->updateParent(this); + } + } + + void CompoundTag::addEntries(const std::map& newEntries) { + value.insert(newEntries.begin(), newEntries.end()); + for (auto& [key, tag] : newEntries) { + tag->updateParent(this); + } + } + + template + std::map CompoundTag::cast() const { + std::map result; + for (const auto& [key, tag] : value) { + result[static_cast(key)] = static_cast(tag); + } + return result; + } + + void CompoundTag::clear() { + unsetParent(); + value.clear(); + } + + void CompoundTag::unsetParent() { + for (auto& [key, tag] : value) { + tag->setParentTagType(TagType::End); + tag->updateParent(nullptr); + } + } + + bool CompoundTag::containsKey(const std::string& key) const { + return value.find(key) != value.end(); + } + + bool CompoundTag::containsValue(const Tag* tag) const { + for (const auto& [key, valueTag] : value) { + if (valueTag == tag) { + return true; + } + } + return false; + } + + std::map::const_iterator CompoundTag::begin() const { + return value.begin(); + } + + std::map::const_iterator CompoundTag::end() const { + return value.end(); + } + + void CompoundTag::forEach(void (*action)(const std::string&, Tag*)) const { + for (const auto& [key, tag] : value) { + action(key, tag); + } + } + + bool CompoundTag::isEmpty() const { + return value.empty(); + } + + bool CompoundTag::isNotEmpty() const { + return !value.empty(); + } + + std::map::const_iterator CompoundTag::keys() const { + return value.begin(); + } + + int CompoundTag::length() const { + return static_cast(value.size()); + } + + std::map CompoundTag::map(std::pair(*)(const std::string&, Tag*)) const { + std::map result; + for (const auto& [key, tag] : value) { + result[key] = tag; + } + return result; + } + + Tag* CompoundTag::putIfAbsent(const std::string& key, Tag* (*ifAbsent)()) { + auto [it, inserted] = value.emplace(key, ifAbsent()); + Tag* tag = it->second; + tag->updateParent(this); + return tag; + } + + Tag* CompoundTag::remove(const std::string& key) { + auto it = value.find(key); + if (it != value.end()) { + Tag* tag = it->second; + tag->updateParent(nullptr); + value.erase(it); + return tag; + } + return nullptr; + } + + void CompoundTag::removeWhere(bool (*test)(const std::string&, Tag*)) { + for (auto it = value.begin(); it != value.end();) { + if (test(it->first, it->second)) { + it->second->updateParent(nullptr); + it = value.erase(it); + } else { + ++it; + } + } + } + + Tag* CompoundTag::update(const std::string& key, Tag* (*update)(Tag*), Tag* (*ifAbsent)()) { + auto it = value.find(key); + if (it != value.end()) { + Tag* updatedTag = update(it->second); + it->second->updateParent(nullptr); + value[key] = updatedTag; + updatedTag->updateParent(this); + return updatedTag; + } else if (ifAbsent) { + Tag* newTag = ifAbsent(); + put(key, newTag); + return newTag; + } + return nullptr; + } + + void CompoundTag::updateAll(Tag* (*update)(const std::string&, Tag*)) { + for (auto& [key, tag] : value) { + Tag* updatedTag = update(key, tag); + tag->updateParent(nullptr); + value[key] = updatedTag; + updatedTag->updateParent(this); + } + } + + std::map::const_iterator CompoundTag::values() const { + return value.begin(); + } + +} diff --git a/src/nbt/CompoundTag.h b/src/nbt/CompoundTag.h new file mode 100644 index 0000000..5fcce5c --- /dev/null +++ b/src/nbt/CompoundTag.h @@ -0,0 +1,77 @@ +#ifndef COMPOUNDTAG_H +#define COMPOUNDTAG_H + +#include +#include +#include +#include "Tag.h" +#include "ByteLayer.h" +#include "StringBuilder.h" +#include "StringReader.h" + +namespace nbt { + + class CompoundTag : public Tag { + public: + CompoundTag(); + ~CompoundTag(); + + void readValue(ByteLayer& data) override; + void writeValue(ByteLayer& data) const override; + + void put(const std::string& name, Tag* tag); + Tag* get(const std::string& name) const; + + TagType getTagType() const override; + void setValue(const dynamic& val) override; + dynamic getValue() const override; + + void prettyPrint(int indent, bool recurse) const override; + void endPrettyPrint(int indent) const; + + void writeStringifiedValue(StringBuilder& builder, int indent, bool isList) const override; + void readStringifiedValue(StringReader& reader) override; + + Tag* operator[](const std::string& key) const; + + void addAll(const std::map& other); + void addEntries(const std::map& newEntries); + + template + std::map cast() const; + + void clear(); + void unsetParent(); + + bool containsKey(const std::string& key) const; + bool containsValue(const Tag* value) const; + + std::map::const_iterator begin() const; + std::map::const_iterator end() const; + void forEach(void (*action)(const std::string&, Tag*)) const; + + bool isEmpty() const; + bool isNotEmpty() const; + std::map::const_iterator keys() const; + int length() const; + std::map map(std::pair(*)(const std::string&, Tag*)) const; + + Tag* putIfAbsent(const std::string& key, Tag* (*ifAbsent)()); + + Tag* remove(const std::string& key); + + void removeWhere(bool (*test)(const std::string&, Tag*)); + + Tag* update(const std::string& key, Tag* (*update)(Tag*), Tag* (*ifAbsent)() = nullptr); + + void updateAll(Tag* (*update)(const std::string&, Tag*)); + + std::map::const_iterator values() const; + + private: + std::map value; + }; + +} + +#endif // COMPOUNDTAG_H diff --git a/src/nbt/DoubleTag.cpp b/src/nbt/DoubleTag.cpp index c7c0742..95ddf22 100644 --- a/src/nbt/DoubleTag.cpp +++ b/src/nbt/DoubleTag.cpp @@ -22,7 +22,7 @@ namespace nbt value = data.readDouble(); } - void DoubleTag::writeValue(ByteLayer &data) + void DoubleTag::writeValue(ByteLayer &data) const { data.writeDouble(value); } diff --git a/src/nbt/DoubleTag.h b/src/nbt/DoubleTag.h index d099a0d..530285b 100644 --- a/src/nbt/DoubleTag.h +++ b/src/nbt/DoubleTag.h @@ -14,7 +14,7 @@ namespace nbt // Function overrides void readValue(ByteLayer &data) override; - void writeValue(ByteLayer &data) override; + void writeValue(ByteLayer &data) const override; TagType getTagType() const override; dynamic getValue() const override; void setValue(const dynamic &val) override; diff --git a/src/nbt/EndTag.cpp b/src/nbt/EndTag.cpp index b45da97..480f662 100644 --- a/src/nbt/EndTag.cpp +++ b/src/nbt/EndTag.cpp @@ -20,7 +20,7 @@ namespace nbt // Implementation here } - void EndTag::writeValue(ByteLayer &data) + void EndTag::writeValue(ByteLayer &data) const { // Implementation here } diff --git a/src/nbt/EndTag.h b/src/nbt/EndTag.h index f5b5982..ce595b8 100644 --- a/src/nbt/EndTag.h +++ b/src/nbt/EndTag.h @@ -16,7 +16,7 @@ namespace nbt // Override functions from the Tag class void readValue(ByteLayer &data) override; - void writeValue(ByteLayer &data) override; + void writeValue(ByteLayer &data) const override; TagType getTagType() const override; void setValue(const dynamic &val) override; dynamic getValue() const override; diff --git a/src/nbt/FloatTag.cpp b/src/nbt/FloatTag.cpp index 82f2c64..f409db9 100644 --- a/src/nbt/FloatTag.cpp +++ b/src/nbt/FloatTag.cpp @@ -22,7 +22,7 @@ namespace nbt value = data.readFloat(); } - void FloatTag::writeValue(ByteLayer &data) + void FloatTag::writeValue(ByteLayer &data) const { data.writeFloat(value); } diff --git a/src/nbt/FloatTag.h b/src/nbt/FloatTag.h index 42bcbad..e15004e 100644 --- a/src/nbt/FloatTag.h +++ b/src/nbt/FloatTag.h @@ -14,7 +14,7 @@ namespace nbt // Function overrides void readValue(ByteLayer &data) override; - void writeValue(ByteLayer &data) override; + void writeValue(ByteLayer &data) const override; TagType getTagType() const override; dynamic getValue() const override; void setValue(const dynamic &val) override; diff --git a/src/nbt/Tag.cpp b/src/nbt/Tag.cpp index 430adac..13b0efa 100644 --- a/src/nbt/Tag.cpp +++ b/src/nbt/Tag.cpp @@ -1,5 +1,7 @@ #include "Tag.h" #include "EndTag.h" +#include "ByteTag.h" +#include "ByteArrayTag.h" #include #include @@ -12,15 +14,17 @@ using namespace libac; namespace nbt { - std::shared_ptr Tag::readNamedTag(ByteLayer &data) + Tag *Tag::readNamedTag(ByteLayer &data) { int type = data.readByte(); switch (static_cast(type)) { case TagType::End: - return std::make_shared(); + return new EndTag(); case TagType::Byte: - // handle other cases similarly + return new ByteTag(); + case TagType::ByteArray: + return new ByteArrayTag(); default: // default handling return nullptr; @@ -82,7 +86,7 @@ namespace nbt } } - std::shared_ptr Tag::readStringifiedNamedTag(StringReader &string) + Tag *Tag::readStringifiedNamedTag(StringReader &string) { std::string name; if (string.peek() == '{' || string.peek() == '[') @@ -95,7 +99,7 @@ namespace nbt string.expect(':'); } TagType type = Tag::getStringifiedTagType(string); - std::shared_ptr tag = makeTagOfType(type); + Tag *tag = makeTagOfType(type); tag->setKey(name); tag->readStringifiedValue(string); diff --git a/src/nbt/Tag.h b/src/nbt/Tag.h index db06c83..b22d8f7 100644 --- a/src/nbt/Tag.h +++ b/src/nbt/Tag.h @@ -52,11 +52,11 @@ namespace nbt static TagType getStringifiedTagType(StringReader &str); - void updateParent(std::shared_ptr tag) + void updateParent(Tag* tag) { if (tag == nullptr) { - _parentTag.reset(); + _parentTag = nullptr; setParentTagType(TagType::End); } else @@ -66,7 +66,7 @@ namespace nbt } } - std::shared_ptr getParent() const + Tag* getParent() const { return _parentTag; } @@ -96,7 +96,7 @@ namespace nbt virtual void writeStringifiedValue(StringBuilder &stream, int indent, bool isList) const = 0; virtual void readStringifiedValue(StringReader &reader) = 0; - virtual void writeValue(ByteLayer &data); + virtual void writeValue(ByteLayer &data) const; virtual void setValue(const dynamic &val); virtual void prettyPrint(int indent, bool recurse) const; virtual void readStringifiedValue(StringReader &reader); @@ -108,19 +108,19 @@ namespace nbt return getType() == other.getType() && getKey() == other.getKey(); } - static std::shared_ptr readNamedTag(ByteLayer &data); + static Tag* readNamedTag(ByteLayer &data); static void writeNamedTag(Tag &tag, ByteLayer &data); - static std::shared_ptr readStringifiedNamedTag(StringReader &string); + static Tag* readStringifiedNamedTag(StringReader &string); static void writeStringifiedNamedTag(Tag &tag, StringBuilder &builder, int indents); - static std::shared_ptr makeTagOfType(TagType type); + static Tag* makeTagOfType(TagType type); static std::string getCanonicalName(TagType type); bool shouldQuoteName(); static bool shouldQuote(const string &value); protected: - std::shared_ptr _parentTag; + Tag* _parentTag; TagType _parentTagType = TagType::End; std::string _key; };