FeatherMC/src/nbt/NBT.h

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);
}
}