142 lines
3.6 KiB
C++
142 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <iterator>
|
|
|
|
struct nbt_node;
|
|
struct list_head;
|
|
|
|
namespace NBT
|
|
{
|
|
// Represents a generic NBT tag of any type
|
|
class Tag
|
|
{
|
|
protected:
|
|
nbt_node* m_node;
|
|
Tag(nbt_node *node) : m_node(node) {}
|
|
|
|
static Tag CreateTag(nbt_node* node);
|
|
static Tag CreateListTag(nbt_node* node);
|
|
public:
|
|
|
|
// This will be "<null>" if the tag is nameless
|
|
const char* GetName() const;
|
|
|
|
// Get the number of iterable immediate children
|
|
size_t GetLength() const;
|
|
|
|
const char* ToString() const;
|
|
};
|
|
|
|
// Operator overload for ostream
|
|
std::ostream& operator<<(std::ostream& stream, const Tag& tag);
|
|
|
|
template <typename T>
|
|
class DataTag : public Tag
|
|
{
|
|
public:
|
|
DataTag<T>(nbt_node* node) : Tag(node) {}
|
|
|
|
T GetValue() const;
|
|
|
|
inline operator T() const { return GetValue(); }
|
|
};
|
|
|
|
// Standard value types
|
|
using ByteTag = DataTag<int8_t>;
|
|
using ShortTag = DataTag<int16_t>;
|
|
using IntTag = DataTag<int32_t>;
|
|
using LongTag = DataTag<int64_t>;
|
|
using FloatTag = DataTag<float>;
|
|
using DoubleTag = DataTag<double>;
|
|
|
|
// Represents a generic array, used for StringTag,
|
|
// ByteArrayTag, IntArrayTag, and LongArrayTag
|
|
template <typename T>
|
|
class ArrayTag : public DataTag<T*>
|
|
{
|
|
public:
|
|
ArrayTag<T>(nbt_node* node) : DataTag<T*>(node) {}
|
|
|
|
const T* GetValue() const;
|
|
|
|
// Methods for range-based for loops
|
|
// TODO: check if this works for IntArrayTag and LongArrayTag
|
|
const T* begin() { return GetValue(); }
|
|
const T* end() { return GetValue() + Tag::GetLength(); }
|
|
};
|
|
|
|
// A string is an array of char. Its length is
|
|
// not stored by cNBT, so Tag::GetLength uses strlen
|
|
using StringTag = ArrayTag<char>;
|
|
|
|
// Standard array types
|
|
using ByteArrayTag = ArrayTag<int8_t>;
|
|
using IntArrayTag = ArrayTag<int32_t>;
|
|
using LongArrayTag = ArrayTag<int64_t>;
|
|
|
|
// Represents a list of nameless tags of the same type
|
|
template <typename T>
|
|
class ListTag : public Tag
|
|
{
|
|
public:
|
|
ListTag<T>(nbt_node *node) : Tag(node) {}
|
|
|
|
T Get(int32_t index) const;
|
|
|
|
inline const T operator[](int32_t index) const { return Get(index); }
|
|
};
|
|
|
|
// A Compound Tag is an unordered list of named tags
|
|
class CompoundTag : public Tag
|
|
{
|
|
public:
|
|
CompoundTag(nbt_node* node) : Tag(node) {}
|
|
|
|
CompoundTag(const char *filename);
|
|
~CompoundTag();
|
|
|
|
template <typename T>
|
|
const ListTag<T> GetList(const char* name) const;
|
|
|
|
template <typename T>
|
|
const T Get(const char* name) const;
|
|
|
|
const Tag operator[](const char* name) const;
|
|
};
|
|
|
|
//==================================================
|
|
|
|
namespace Internal
|
|
{
|
|
nbt_node* FindByName(nbt_node* tree, const char* name);
|
|
nbt_node* ListItem(nbt_node* list, int32_t index);
|
|
}
|
|
|
|
//==================================================
|
|
|
|
template <typename T>
|
|
T ListTag<T>::Get(int32_t index) const
|
|
{
|
|
nbt_node* result = Internal::ListItem(m_node, index);
|
|
return DataTag<T>(result);
|
|
}
|
|
|
|
//==================================================
|
|
|
|
template <typename T>
|
|
const ListTag<T> CompoundTag::GetList(const char *name) const
|
|
{
|
|
nbt_node *result = Internal::FindByName(m_node, name);
|
|
|
|
if (result == NULL)
|
|
return NULL;
|
|
//if (result->type != TAG_LIST)
|
|
// return NULL;
|
|
|
|
return ListTag<T>(result);
|
|
}
|
|
} |