Start hooking stuff up!
This commit is contained in:
parent
e5a3717e64
commit
7744e18d8c
15 changed files with 368 additions and 23 deletions
|
@ -1,5 +1,6 @@
|
|||
#include "Accountant.h"
|
||||
#include "Tag.h"
|
||||
#include "CompoundTag.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace nbt;
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace nbt
|
|||
}
|
||||
}
|
||||
|
||||
void ByteArrayTag::writeValue(ByteLayer &data)
|
||||
void ByteArrayTag::writeValue(ByteLayer &data) const
|
||||
{
|
||||
data.writeInt(static_cast<int>(value.size()));
|
||||
for (int i : value)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace nbt
|
|||
value = data.readByte();
|
||||
}
|
||||
|
||||
void ByteTag::writeValue(ByteLayer &data)
|
||||
void ByteTag::writeValue(ByteLayer &data) const
|
||||
{
|
||||
data.writeByte(value);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
263
src/nbt/CompoundTag.cpp
Normal file
263
src/nbt/CompoundTag.cpp
Normal file
|
@ -0,0 +1,263 @@
|
|||
#include "CompoundTag.h"
|
||||
#include "Tag.h"
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
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<int>(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<std::string, Tag*>& other) {
|
||||
value.insert(other.begin(), other.end());
|
||||
for (auto& [key, tag] : other) {
|
||||
tag->updateParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
void CompoundTag::addEntries(const std::map<std::string, Tag*>& newEntries) {
|
||||
value.insert(newEntries.begin(), newEntries.end());
|
||||
for (auto& [key, tag] : newEntries) {
|
||||
tag->updateParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RK, typename RV>
|
||||
std::map<RK, RV> CompoundTag::cast() const {
|
||||
std::map<RK, RV> result;
|
||||
for (const auto& [key, tag] : value) {
|
||||
result[static_cast<RK>(key)] = static_cast<RV>(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<std::string, Tag*>::const_iterator CompoundTag::begin() const {
|
||||
return value.begin();
|
||||
}
|
||||
|
||||
std::map<std::string, Tag*>::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<std::string, Tag*>::const_iterator CompoundTag::keys() const {
|
||||
return value.begin();
|
||||
}
|
||||
|
||||
int CompoundTag::length() const {
|
||||
return static_cast<int>(value.size());
|
||||
}
|
||||
|
||||
std::map<std::string, Tag*> CompoundTag::map(std::pair<std::string, Tag*>(*)(const std::string&, Tag*)) const {
|
||||
std::map<std::string, Tag*> 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<std::string, Tag*>::const_iterator CompoundTag::values() const {
|
||||
return value.begin();
|
||||
}
|
||||
|
||||
}
|
77
src/nbt/CompoundTag.h
Normal file
77
src/nbt/CompoundTag.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef COMPOUNDTAG_H
|
||||
#define COMPOUNDTAG_H
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#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<std::string, Tag*>& other);
|
||||
void addEntries(const std::map<std::string, Tag*>& newEntries);
|
||||
|
||||
template <typename RK, typename RV>
|
||||
std::map<RK, RV> cast() const;
|
||||
|
||||
void clear();
|
||||
void unsetParent();
|
||||
|
||||
bool containsKey(const std::string& key) const;
|
||||
bool containsValue(const Tag* value) const;
|
||||
|
||||
std::map<std::string, Tag*>::const_iterator begin() const;
|
||||
std::map<std::string, Tag*>::const_iterator end() const;
|
||||
void forEach(void (*action)(const std::string&, Tag*)) const;
|
||||
|
||||
bool isEmpty() const;
|
||||
bool isNotEmpty() const;
|
||||
std::map<std::string, Tag*>::const_iterator keys() const;
|
||||
int length() const;
|
||||
std::map<std::string, Tag*> map(std::pair<std::string, Tag*>(*)(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<std::string, Tag*>::const_iterator values() const;
|
||||
|
||||
private:
|
||||
std::map<std::string, Tag*> value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // COMPOUNDTAG_H
|
|
@ -22,7 +22,7 @@ namespace nbt
|
|||
value = data.readDouble();
|
||||
}
|
||||
|
||||
void DoubleTag::writeValue(ByteLayer &data)
|
||||
void DoubleTag::writeValue(ByteLayer &data) const
|
||||
{
|
||||
data.writeDouble(value);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace nbt
|
|||
// Implementation here
|
||||
}
|
||||
|
||||
void EndTag::writeValue(ByteLayer &data)
|
||||
void EndTag::writeValue(ByteLayer &data) const
|
||||
{
|
||||
// Implementation here
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace nbt
|
|||
value = data.readFloat();
|
||||
}
|
||||
|
||||
void FloatTag::writeValue(ByteLayer &data)
|
||||
void FloatTag::writeValue(ByteLayer &data) const
|
||||
{
|
||||
data.writeFloat(value);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "Tag.h"
|
||||
#include "EndTag.h"
|
||||
#include "ByteTag.h"
|
||||
#include "ByteArrayTag.h"
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -12,15 +14,17 @@ using namespace libac;
|
|||
namespace nbt
|
||||
{
|
||||
|
||||
std::shared_ptr<Tag> Tag::readNamedTag(ByteLayer &data)
|
||||
Tag *Tag::readNamedTag(ByteLayer &data)
|
||||
{
|
||||
int type = data.readByte();
|
||||
switch (static_cast<TagType>(type))
|
||||
{
|
||||
case TagType::End:
|
||||
return std::make_shared<EndTag>();
|
||||
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> 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> tag = makeTagOfType(type);
|
||||
Tag *tag = makeTagOfType(type);
|
||||
tag->setKey(name);
|
||||
tag->readStringifiedValue(string);
|
||||
|
||||
|
|
|
@ -52,11 +52,11 @@ namespace nbt
|
|||
|
||||
static TagType getStringifiedTagType(StringReader &str);
|
||||
|
||||
void updateParent(std::shared_ptr<Tag> 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<Tag> 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<Tag> readNamedTag(ByteLayer &data);
|
||||
static Tag* readNamedTag(ByteLayer &data);
|
||||
static void writeNamedTag(Tag &tag, ByteLayer &data);
|
||||
static std::shared_ptr<Tag> readStringifiedNamedTag(StringReader &string);
|
||||
static Tag* readStringifiedNamedTag(StringReader &string);
|
||||
static void writeStringifiedNamedTag(Tag &tag, StringBuilder &builder, int indents);
|
||||
|
||||
static std::shared_ptr<Tag> 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<Tag> _parentTag;
|
||||
Tag* _parentTag;
|
||||
TagType _parentTagType = TagType::End;
|
||||
std::string _key;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue