Makes some stuff work
This commit is contained in:
parent
43e16ce945
commit
e5a3717e64
24 changed files with 2048 additions and 1 deletions
40
src/nbt/Accountant.cpp
Normal file
40
src/nbt/Accountant.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include "Accountant.h"
|
||||
#include "Tag.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace nbt;
|
||||
using namespace libac;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
int NBTAccountant::_prettyIndex = 0;
|
||||
|
||||
void NBTAccountant::printRead(const Tag &tag)
|
||||
{
|
||||
tag.prettyPrint(_prettyIndex, false);
|
||||
}
|
||||
|
||||
void NBTAccountant::visitTag()
|
||||
{
|
||||
_prettyIndex++;
|
||||
}
|
||||
|
||||
void NBTAccountant::leaveTag(const Tag &tag)
|
||||
{
|
||||
// Assuming Tag has virtual methods to check its type or a `getType` method
|
||||
if (dynamic_cast<const CompoundTag *>(&tag) || dynamic_cast<const ListTag *>(&tag))
|
||||
{
|
||||
if (const CompoundTag *ct = dynamic_cast<const CompoundTag *>(&tag))
|
||||
{
|
||||
ct->endPrettyPrint(_prettyIndex);
|
||||
}
|
||||
else if (const ListTag *lt = dynamic_cast<const ListTag *>(&tag))
|
||||
{
|
||||
lt->endPrettyPrint(_prettyIndex);
|
||||
}
|
||||
}
|
||||
_prettyIndex--;
|
||||
}
|
||||
|
||||
}
|
21
src/nbt/Accountant.h
Normal file
21
src/nbt/Accountant.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef NBTACCOUNTANT_H
|
||||
#define NBTACCOUNTANT_H
|
||||
|
||||
#include "Tag.h" // Assuming this includes definitions for Tag, CompoundTag, and ListTag
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
class NBTAccountant
|
||||
{
|
||||
public:
|
||||
static void printRead(const Tag &tag);
|
||||
static void visitTag();
|
||||
static void leaveTag(const Tag &tag);
|
||||
|
||||
private:
|
||||
static int _prettyIndex;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NBTACCOUNTANT_H
|
104
src/nbt/ByteArrayTag.cpp
Normal file
104
src/nbt/ByteArrayTag.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
#include "ByteArrayTag.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
ByteArrayTag::ByteArrayTag() : Tag()
|
||||
{
|
||||
// Default constructor
|
||||
}
|
||||
|
||||
ByteArrayTag::ByteArrayTag(const std::vector<uint8_t> &value) : Tag(), value(value)
|
||||
{
|
||||
// Constructor with initial value
|
||||
}
|
||||
|
||||
void ByteArrayTag::readValue(ByteLayer &data)
|
||||
{
|
||||
int len = data.readInt();
|
||||
value.clear();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
value.push_back(data.readByte());
|
||||
}
|
||||
}
|
||||
|
||||
void ByteArrayTag::writeValue(ByteLayer &data)
|
||||
{
|
||||
data.writeInt(static_cast<int>(value.size()));
|
||||
for (int i : value)
|
||||
{
|
||||
data.writeByte(i);
|
||||
}
|
||||
}
|
||||
|
||||
TagType ByteArrayTag::getTagType() const
|
||||
{
|
||||
return TagType::ByteArray;
|
||||
}
|
||||
|
||||
dynamic ByteArrayTag::getValue() const
|
||||
{
|
||||
return dynamic(value);
|
||||
}
|
||||
|
||||
void ByteArrayTag::setValue(const dynamic &val)
|
||||
{
|
||||
value = val.get<vector<uint8_t>>();
|
||||
}
|
||||
|
||||
void ByteArrayTag::prettyPrint(int indent, bool recurse) const
|
||||
{
|
||||
std::cout << std::setw(indent) << std::setfill('\t') << ""
|
||||
<< Tag::getCanonicalName(getTagType()) << ": [";
|
||||
for (size_t i = 0; i < value.size(); i++)
|
||||
{
|
||||
std::cout << value[i];
|
||||
if (i < value.size() - 1)
|
||||
{
|
||||
std::cout << ", ";
|
||||
}
|
||||
}
|
||||
std::cout << "]";
|
||||
}
|
||||
|
||||
void ByteArrayTag::writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const
|
||||
{
|
||||
builder << (isList ? std::string(indent, '\t') : "") << "[B; ";
|
||||
for (size_t i = 0; i < value.size(); i++)
|
||||
{
|
||||
builder << value[i] << "B";
|
||||
if (i < value.size() - 1)
|
||||
{
|
||||
builder << ", ";
|
||||
}
|
||||
}
|
||||
builder << "]";
|
||||
}
|
||||
|
||||
void ByteArrayTag::readStringifiedValue(StringReader &reader)
|
||||
{
|
||||
std::string temp;
|
||||
reader.expect('[');
|
||||
reader.expect('B');
|
||||
reader.expect(';');
|
||||
value.clear();
|
||||
|
||||
while (reader.peek() != ']')
|
||||
{
|
||||
uint8_t num = stoi(reader.readNumber());
|
||||
value.push_back(num);
|
||||
|
||||
reader.expect('b');
|
||||
|
||||
if (reader.peek() == ',')
|
||||
reader.next();
|
||||
}
|
||||
reader.expect(']');
|
||||
}
|
||||
|
||||
}
|
37
src/nbt/ByteArrayTag.h
Normal file
37
src/nbt/ByteArrayTag.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef BYTEARRAYTAG_H
|
||||
#define BYTEARRAYTAG_H
|
||||
|
||||
#include "Tag.h"
|
||||
#include "../utils/ByteLayer.h" // Assuming ByteLayer is a class you have
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
using namespace libac;
|
||||
using namespace std;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
class ByteArrayTag : public Tag
|
||||
{
|
||||
public:
|
||||
ByteArrayTag();
|
||||
ByteArrayTag(const std::vector<uint8_t> &value);
|
||||
|
||||
// Override functions from the Tag class
|
||||
void readValue(ByteLayer &data) override;
|
||||
void writeValue(ByteLayer &data) override;
|
||||
TagType getTagType() const override;
|
||||
dynamic getValue() const;
|
||||
void setValue(const dynamic &val) override;
|
||||
void prettyPrint(int indent, bool recurse) const override;
|
||||
void writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const override;
|
||||
void readStringifiedValue(StringReader &reader) override;
|
||||
|
||||
private:
|
||||
vector<uint8_t> value;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BYTEARRAYTAG_H
|
66
src/nbt/ByteTag.cpp
Normal file
66
src/nbt/ByteTag.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "ByteTag.h"
|
||||
#include "../utils/ByteLayer.h"
|
||||
#include "../utils/StringBuilder.h"
|
||||
#include "../utils/StringReader.h"
|
||||
#include <iomanip>
|
||||
|
||||
using namespace libac;
|
||||
using namespace std;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
ByteTag::ByteTag() : Tag(), value(0)
|
||||
{
|
||||
// Default constructor
|
||||
}
|
||||
|
||||
ByteTag::ByteTag(int value) : Tag(), value(value)
|
||||
{
|
||||
}
|
||||
|
||||
void ByteTag::readValue(ByteLayer &data)
|
||||
{
|
||||
value = data.readByte();
|
||||
}
|
||||
|
||||
void ByteTag::writeValue(ByteLayer &data)
|
||||
{
|
||||
data.writeByte(value);
|
||||
}
|
||||
|
||||
TagType ByteTag::getTagType() const
|
||||
{
|
||||
return TagType::Byte;
|
||||
}
|
||||
|
||||
dynamic ByteTag::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void ByteTag::setValue(const dynamic &val)
|
||||
{
|
||||
value = val.get<uint8_t>();
|
||||
}
|
||||
|
||||
void ByteTag::prettyPrint(int indent, bool recurse) const
|
||||
{
|
||||
std::cout << std::setw(indent) << std::setfill('\t') << ""
|
||||
<< Tag::getCanonicalName(getTagType()) << ": " << value;
|
||||
}
|
||||
|
||||
void ByteTag::writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const
|
||||
{
|
||||
builder << (isList ? std::string(indent, '\t') : "") << value << "b";
|
||||
}
|
||||
|
||||
void ByteTag::readStringifiedValue(StringReader &reader)
|
||||
{
|
||||
std::string val = reader.readNumber();
|
||||
value = stoi(val);
|
||||
|
||||
reader.expect('b');
|
||||
}
|
||||
|
||||
}
|
37
src/nbt/ByteTag.h
Normal file
37
src/nbt/ByteTag.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef BYTETAG_H
|
||||
#define BYTETAG_H
|
||||
|
||||
#include "Tag.h"
|
||||
#include <string>
|
||||
#include "../utils/ByteLayer.h"
|
||||
#include "../utils/StringBuilder.h"
|
||||
#include "../utils/StringReader.h"
|
||||
|
||||
using namespace libac;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
class ByteTag : public Tag
|
||||
{
|
||||
public:
|
||||
ByteTag();
|
||||
ByteTag(int value);
|
||||
~ByteTag();
|
||||
|
||||
// Override functions from the Tag class
|
||||
void readValue(ByteLayer &data) override;
|
||||
void writeValue(ByteLayer &data) override;
|
||||
TagType getTagType() const override;
|
||||
dynamic getValue() const override;
|
||||
void setValue(const dynamic &val) override;
|
||||
void prettyPrint(int indent, bool recurse) const override;
|
||||
void writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const override;
|
||||
void readStringifiedValue(StringReader &reader) override;
|
||||
|
||||
private:
|
||||
uint8_t value;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BYTETAG_H
|
62
src/nbt/DoubleTag.cpp
Normal file
62
src/nbt/DoubleTag.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "DoubleTag.h"
|
||||
|
||||
using namespace libac;
|
||||
using namespace std;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
DoubleTag::DoubleTag() : Tag(), value(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
DoubleTag::DoubleTag(double val) : Tag(), value(val)
|
||||
{
|
||||
}
|
||||
|
||||
void DoubleTag::readValue(ByteLayer &data)
|
||||
{
|
||||
value = data.readDouble();
|
||||
}
|
||||
|
||||
void DoubleTag::writeValue(ByteLayer &data)
|
||||
{
|
||||
data.writeDouble(value);
|
||||
}
|
||||
|
||||
TagType DoubleTag::getTagType() const
|
||||
{
|
||||
return TagType::Double;
|
||||
}
|
||||
|
||||
dynamic DoubleTag::getValue() const
|
||||
{
|
||||
return dynamic(value);
|
||||
}
|
||||
|
||||
void DoubleTag::setValue(const dynamic &val)
|
||||
{
|
||||
value = val.get<double>();
|
||||
}
|
||||
|
||||
void DoubleTag::prettyPrint(int indent, bool recurse) const
|
||||
{
|
||||
cout << setw(indent) << setfill('\t') << Tag::getCanonicalName(getTagType()) << ": " << value;
|
||||
}
|
||||
|
||||
void DoubleTag::writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const
|
||||
{
|
||||
builder << (isList ? std::string(indent, '\t') : "") << value << "d";
|
||||
}
|
||||
|
||||
void DoubleTag::readStringifiedValue(StringReader &reader)
|
||||
{
|
||||
double val = stod(reader.readNumber());
|
||||
value = val;
|
||||
|
||||
reader.expect('d');
|
||||
}
|
||||
}
|
30
src/nbt/DoubleTag.h
Normal file
30
src/nbt/DoubleTag.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef DOUBLE_TAG_H
|
||||
#define DOUBLE_TAG_H
|
||||
|
||||
#include "Tag.h"
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
class DoubleTag : public Tag
|
||||
{
|
||||
public:
|
||||
DoubleTag();
|
||||
DoubleTag(double val);
|
||||
~DoubleTag();
|
||||
|
||||
// Function overrides
|
||||
void readValue(ByteLayer &data) override;
|
||||
void writeValue(ByteLayer &data) override;
|
||||
TagType getTagType() const override;
|
||||
dynamic getValue() const override;
|
||||
void setValue(const dynamic &val) override;
|
||||
void prettyPrint(int indent, bool recurse) const override;
|
||||
void writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const override;
|
||||
void readStringifiedValue(StringReader &reader) override;
|
||||
|
||||
private:
|
||||
double value;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
59
src/nbt/EndTag.cpp
Normal file
59
src/nbt/EndTag.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "EndTag.h"
|
||||
#include "Tag.h" // Ensure you include the Tag class header
|
||||
#include <iostream>
|
||||
#include <iomanip> // For std::setw if needed
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
EndTag::EndTag() : Tag()
|
||||
{
|
||||
// Constructor implementation if needed
|
||||
}
|
||||
|
||||
EndTag::~EndTag(){
|
||||
|
||||
}
|
||||
|
||||
void EndTag::readValue(ByteLayer &data)
|
||||
{
|
||||
// Implementation here
|
||||
}
|
||||
|
||||
void EndTag::writeValue(ByteLayer &data)
|
||||
{
|
||||
// Implementation here
|
||||
}
|
||||
|
||||
TagType EndTag::getTagType() const
|
||||
{
|
||||
return TagType::End;
|
||||
}
|
||||
|
||||
void EndTag::setValue(const dynamic &val)
|
||||
{
|
||||
// Implementation here
|
||||
}
|
||||
|
||||
dynamic EndTag::getValue() const
|
||||
{
|
||||
// Implementation here
|
||||
return new dynamic(new string("")); // Return appropriate value
|
||||
}
|
||||
|
||||
void EndTag::prettyPrint(int indent, bool recurse) const
|
||||
{
|
||||
std::cout << std::setw(indent) << std::setfill('\t') << "" << Tag::getCanonicalName(getTagType());
|
||||
}
|
||||
|
||||
void EndTag::writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const
|
||||
{
|
||||
// Implementation here
|
||||
}
|
||||
|
||||
void EndTag::readStringifiedValue(StringReader &reader)
|
||||
{
|
||||
// Implementation here
|
||||
}
|
||||
|
||||
}
|
29
src/nbt/EndTag.h
Normal file
29
src/nbt/EndTag.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef ENDTAG_H
|
||||
#define ENDTAG_H
|
||||
|
||||
#include "Tag.h"
|
||||
#include "../utils/ByteLayer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
class EndTag : public Tag
|
||||
{
|
||||
public:
|
||||
EndTag();
|
||||
~EndTag();
|
||||
|
||||
// Override functions from the Tag class
|
||||
void readValue(ByteLayer &data) override;
|
||||
void writeValue(ByteLayer &data) override;
|
||||
TagType getTagType() const override;
|
||||
void setValue(const dynamic &val) override;
|
||||
dynamic getValue() const override;
|
||||
void prettyPrint(int indent, bool recurse) const override;
|
||||
void writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const override;
|
||||
void readStringifiedValue(StringReader &reader) override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
62
src/nbt/FloatTag.cpp
Normal file
62
src/nbt/FloatTag.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "FloatTag.h"
|
||||
|
||||
using namespace libac;
|
||||
using namespace std;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
FloatTag::FloatTag() : Tag(), value(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
FloatTag::FloatTag(float val) : Tag(), value(val)
|
||||
{
|
||||
}
|
||||
|
||||
void FloatTag::readValue(ByteLayer &data)
|
||||
{
|
||||
value = data.readFloat();
|
||||
}
|
||||
|
||||
void FloatTag::writeValue(ByteLayer &data)
|
||||
{
|
||||
data.writeFloat(value);
|
||||
}
|
||||
|
||||
TagType FloatTag::getTagType() const
|
||||
{
|
||||
return TagType::Float;
|
||||
}
|
||||
|
||||
dynamic FloatTag::getValue() const
|
||||
{
|
||||
return dynamic(value);
|
||||
}
|
||||
|
||||
void FloatTag::setValue(const dynamic &val)
|
||||
{
|
||||
value = val.get<float>();
|
||||
}
|
||||
|
||||
void FloatTag::prettyPrint(int indent, bool recurse) const
|
||||
{
|
||||
cout << setw(indent) << setfill('\t') << Tag::getCanonicalName(getTagType()) << ": " << value;
|
||||
}
|
||||
|
||||
void FloatTag::writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const
|
||||
{
|
||||
builder << (isList ? std::string(indent, '\t') : "") << value << "f";
|
||||
}
|
||||
|
||||
void FloatTag::readStringifiedValue(StringReader &reader)
|
||||
{
|
||||
float val = stof(reader.readNumber());
|
||||
value = val;
|
||||
|
||||
reader.expect('f');
|
||||
}
|
||||
}
|
30
src/nbt/FloatTag.h
Normal file
30
src/nbt/FloatTag.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef FLOAT_TAG_H
|
||||
#define FLOAT_TAG_H
|
||||
|
||||
#include "Tag.h"
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
class FloatTag : public Tag
|
||||
{
|
||||
public:
|
||||
FloatTag();
|
||||
FloatTag(float val);
|
||||
~FloatTag();
|
||||
|
||||
// Function overrides
|
||||
void readValue(ByteLayer &data) override;
|
||||
void writeValue(ByteLayer &data) override;
|
||||
TagType getTagType() const override;
|
||||
dynamic getValue() const override;
|
||||
void setValue(const dynamic &val) override;
|
||||
void prettyPrint(int indent, bool recurse) const override;
|
||||
void writeStringifiedValue(StringBuilder &builder, int indent, bool isList) const override;
|
||||
void readStringifiedValue(StringReader &reader) override;
|
||||
|
||||
private:
|
||||
float value;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
255
src/nbt/Tag.cpp
Normal file
255
src/nbt/Tag.cpp
Normal file
|
@ -0,0 +1,255 @@
|
|||
#include "Tag.h"
|
||||
#include "EndTag.h"
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../utils/ByteLayer.h"
|
||||
#include "../utils/StringBuilder.h"
|
||||
#include "../utils/StringReader.h"
|
||||
|
||||
using namespace libac;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
std::shared_ptr<Tag> Tag::readNamedTag(ByteLayer &data)
|
||||
{
|
||||
int type = data.readByte();
|
||||
switch (static_cast<TagType>(type))
|
||||
{
|
||||
case TagType::End:
|
||||
return std::make_shared<EndTag>();
|
||||
case TagType::Byte:
|
||||
// handle other cases similarly
|
||||
default:
|
||||
// default handling
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Tag::shouldQuoteName()
|
||||
{
|
||||
std::string key = getKey();
|
||||
if (key.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
for (char digit : key)
|
||||
{
|
||||
if (letters.find(digit) != std::string::npos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Tag::shouldQuote(const std::string &value)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
for (char digit : value)
|
||||
{
|
||||
if (letters.find(digit) != std::string::npos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Tag::writeNamedTag(Tag &tag, ByteLayer &data)
|
||||
{
|
||||
data.writeByte(tag.getType());
|
||||
if (tag.getType() != static_cast<int>(TagType::End))
|
||||
{
|
||||
data.writeString(tag.getKey());
|
||||
tag.writeValue(data);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Tag> Tag::readStringifiedNamedTag(StringReader &string)
|
||||
{
|
||||
std::string name;
|
||||
if (string.peek() == '{' || string.peek() == '[')
|
||||
{
|
||||
name = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
name = string.readString();
|
||||
string.expect(':');
|
||||
}
|
||||
TagType type = Tag::getStringifiedTagType(string);
|
||||
std::shared_ptr<Tag> tag = makeTagOfType(type);
|
||||
tag->setKey(name);
|
||||
tag->readStringifiedValue(string);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
void Tag::writeStringifiedNamedTag(Tag &tag, StringBuilder &builder, int indents)
|
||||
{
|
||||
if (tag.getType() != (int)TagType::End)
|
||||
{
|
||||
if (tag.getKey().empty())
|
||||
{
|
||||
builder << std::string(indents, '\t');
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tag.shouldQuoteName())
|
||||
{
|
||||
builder << std::string(indents, '\t') << "\"" << tag.getKey() << "\": ";
|
||||
}
|
||||
else
|
||||
{
|
||||
builder << std::string(indents, '\t') << tag.getKey() << ": ";
|
||||
}
|
||||
}
|
||||
tag.writeStringifiedValue(builder, indents + 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Tag::getCanonicalName(TagType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TagType::String:
|
||||
return "TAG_String";
|
||||
case TagType::List:
|
||||
return "TAG_List";
|
||||
case TagType::LongArray:
|
||||
return "TAG_LongArray";
|
||||
case TagType::Long:
|
||||
return "TAG_Long";
|
||||
case TagType::IntArray:
|
||||
return "TAG_IntArray";
|
||||
case TagType::Int:
|
||||
return "TAG_Int";
|
||||
case TagType::Compound:
|
||||
return "TAG_Compound";
|
||||
case TagType::ByteArray:
|
||||
return "TAG_ByteArray";
|
||||
case TagType::Byte:
|
||||
return "TAG_Byte";
|
||||
case TagType::Double:
|
||||
return "TAG_Double";
|
||||
case TagType::Float:
|
||||
return "TAG_Float";
|
||||
case TagType::Short:
|
||||
return "TAG_Short";
|
||||
case TagType::End:
|
||||
return "TAG_End";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
TagType Tag::getStringifiedTagType(StringReader &str)
|
||||
{
|
||||
str.startSeek();
|
||||
TagType ret = TagType::End;
|
||||
bool isNumber = true;
|
||||
bool isAlpha = true; // Is digits only
|
||||
|
||||
while (str.canRead() && ret == TagType::End)
|
||||
{
|
||||
char val = str.next();
|
||||
val = std::toupper(val); // Convert to uppercase
|
||||
|
||||
std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
if (alphabet.find(val) == std::string::npos)
|
||||
{
|
||||
isAlpha = false;
|
||||
}
|
||||
|
||||
switch (val)
|
||||
{
|
||||
case '{':
|
||||
ret = TagType::Compound;
|
||||
break;
|
||||
case '[':
|
||||
{
|
||||
// Check for a type Prefix
|
||||
std::string X = str.readUntil(';');
|
||||
std::transform(X.begin(), X.end(), X.begin(), ::toupper); // Convert to uppercase
|
||||
if (X == "B")
|
||||
{
|
||||
ret = TagType::ByteArray;
|
||||
}
|
||||
else if (X == "I")
|
||||
{
|
||||
ret = TagType::IntArray;
|
||||
}
|
||||
else if (X == "L")
|
||||
{
|
||||
ret = TagType::LongArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = TagType::List;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'B':
|
||||
ret = TagType::Byte;
|
||||
break;
|
||||
case 'D':
|
||||
ret = TagType::Double;
|
||||
break;
|
||||
case 'F':
|
||||
ret = TagType::Float;
|
||||
break;
|
||||
case 'I':
|
||||
ret = TagType::Int;
|
||||
break;
|
||||
case 'L':
|
||||
ret = TagType::Long;
|
||||
break;
|
||||
case 'S':
|
||||
ret = TagType::Short;
|
||||
break;
|
||||
case '\"':
|
||||
ret = TagType::String;
|
||||
break;
|
||||
case ',':
|
||||
case '\n':
|
||||
if (str.getSeeked() >= 1)
|
||||
ret = TagType::String;
|
||||
if (isNumber)
|
||||
ret = TagType::Int;
|
||||
break;
|
||||
default:
|
||||
if (!str.isDigit(val))
|
||||
{
|
||||
if (isNumber)
|
||||
isNumber = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
str.endSeek();
|
||||
if (!isNumber && isAlpha)
|
||||
ret = TagType::String;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
129
src/nbt/Tag.h
Normal file
129
src/nbt/Tag.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
#ifndef LIBNBT_TAG_H
|
||||
#define LIBNBT_TAG_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include "../utils/ByteLayer.h"
|
||||
#include "../utils/StringBuilder.h"
|
||||
#include "../utils/StringReader.h"
|
||||
#include "../types/dynamic.h"
|
||||
|
||||
using namespace libac;
|
||||
using namespace std;
|
||||
|
||||
namespace nbt
|
||||
{
|
||||
|
||||
enum class TagType
|
||||
{
|
||||
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
|
||||
|
||||
};
|
||||
class Tag
|
||||
{
|
||||
public:
|
||||
virtual ~Tag() = default;
|
||||
|
||||
int getType() const
|
||||
{
|
||||
return static_cast<int>(getTagType());
|
||||
}
|
||||
|
||||
virtual TagType getTagType() const = 0;
|
||||
|
||||
bool hasParent() const
|
||||
{
|
||||
return _parentTag != nullptr;
|
||||
}
|
||||
|
||||
static TagType getStringifiedTagType(StringReader &str);
|
||||
|
||||
void updateParent(std::shared_ptr<Tag> tag)
|
||||
{
|
||||
if (tag == nullptr)
|
||||
{
|
||||
_parentTag.reset();
|
||||
setParentTagType(TagType::End);
|
||||
}
|
||||
else
|
||||
{
|
||||
_parentTag = tag;
|
||||
setParentTagType(tag->getTagType());
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Tag> getParent() const
|
||||
{
|
||||
return _parentTag;
|
||||
}
|
||||
|
||||
TagType getParentTagType() const
|
||||
{
|
||||
return _parentTagType;
|
||||
}
|
||||
|
||||
void setParentTagType(TagType type)
|
||||
{
|
||||
_parentTagType = type;
|
||||
}
|
||||
|
||||
virtual void writeValue(ByteLayer &data) const = 0;
|
||||
virtual void readValue(ByteLayer &data) = 0;
|
||||
|
||||
std::string getKey() const
|
||||
{
|
||||
return _key.empty() ? "" : _key;
|
||||
}
|
||||
|
||||
void setKey(const std::string &key)
|
||||
{
|
||||
_key = key;
|
||||
}
|
||||
|
||||
virtual void writeStringifiedValue(StringBuilder &stream, int indent, bool isList) const = 0;
|
||||
virtual void readStringifiedValue(StringReader &reader) = 0;
|
||||
virtual void writeValue(ByteLayer &data);
|
||||
virtual void setValue(const dynamic &val);
|
||||
virtual void prettyPrint(int indent, bool recurse) const;
|
||||
virtual void readStringifiedValue(StringReader &reader);
|
||||
virtual dynamic getValue() const;
|
||||
virtual void setValue(int val);
|
||||
|
||||
virtual bool equals(const Tag &other) const
|
||||
{
|
||||
return getType() == other.getType() && getKey() == other.getKey();
|
||||
}
|
||||
|
||||
static std::shared_ptr<Tag> readNamedTag(ByteLayer &data);
|
||||
static void writeNamedTag(Tag &tag, ByteLayer &data);
|
||||
static std::shared_ptr<Tag> readStringifiedNamedTag(StringReader &string);
|
||||
static void writeStringifiedNamedTag(Tag &tag, StringBuilder &builder, int indents);
|
||||
|
||||
static std::shared_ptr<Tag> makeTagOfType(TagType type);
|
||||
|
||||
static std::string getCanonicalName(TagType type);
|
||||
bool shouldQuoteName();
|
||||
static bool shouldQuote(const string &value);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Tag> _parentTag;
|
||||
TagType _parentTagType = TagType::End;
|
||||
std::string _key;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue