Makes some stuff work

This commit is contained in:
zontreck 2024-07-30 22:30:55 -07:00
parent 43e16ce945
commit e5a3717e64
24 changed files with 2048 additions and 1 deletions

40
src/nbt/Accountant.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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