202 lines
6.1 KiB
C
202 lines
6.1 KiB
C
|
|
||
|
// NBT.h
|
||
|
|
||
|
// Interfaces to the classes used for NBT representation, parsing and serializing
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
typedef long long Int64;
|
||
|
typedef int Int32;
|
||
|
typedef short Int16;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Representation classes:
|
||
|
|
||
|
class cNBTTag abstract // The base class for all NBT tags
|
||
|
{
|
||
|
public:
|
||
|
enum eTagType
|
||
|
{
|
||
|
TAG_Min = 0, // The minimum value for a tag type
|
||
|
TAG_End = 0,
|
||
|
TAG_Byte = 1,
|
||
|
TAG_Short = 2,
|
||
|
TAG_Int = 3,
|
||
|
TAG_Long = 4,
|
||
|
TAG_Float = 5,
|
||
|
TAG_Double = 6,
|
||
|
TAG_ByteArray = 7,
|
||
|
TAG_String = 8,
|
||
|
TAG_List = 9,
|
||
|
TAG_Compound = 10,
|
||
|
TAG_IntArray = 11,
|
||
|
TAG_Max = 11, // The maximum value for a tag type
|
||
|
} ;
|
||
|
|
||
|
protected:
|
||
|
cNBTTag * m_Parent;
|
||
|
eTagType m_Type;
|
||
|
AString m_Name; // tag name, in UTF-8
|
||
|
|
||
|
public:
|
||
|
cNBTTag(cNBTTag * a_Parent, eTagType a_Type) : m_Parent(a_Parent), m_Type(a_Type) {}
|
||
|
cNBTTag(cNBTTag * a_Parent, eTagType a_Type, const AString & a_Name) : m_Parent(a_Parent), m_Type(a_Type), m_Name(a_Name) {}
|
||
|
virtual ~cNBTTag() {} // Force a virtual destructor
|
||
|
|
||
|
cNBTTag * GetParent(void) const {return m_Parent; }
|
||
|
eTagType GetType (void) const {return m_Type; }
|
||
|
const AString & GetName (void) const {return m_Name; }
|
||
|
void SetName (const AString & a_Name) {m_Name = a_Name; }
|
||
|
|
||
|
static cNBTTag * CreateTag(cNBTTag * a_Parent, eTagType a_Type, const AString & a_Name); // Creates a new instance of a tag specified by iType, uses the correct class
|
||
|
|
||
|
virtual cNBTTag * FindChildByName(const AString & a_Name) {return NULL; }
|
||
|
cNBTTag * FindChildByPath(const AString & a_Path);
|
||
|
} ;
|
||
|
|
||
|
typedef cNBTTag cNBTTree;
|
||
|
typedef std::vector<cNBTTag *> cNBTTags;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#define DECLARE_SIMPLE_TAG(TAG,CTYPE) \
|
||
|
class cNBT##TAG : \
|
||
|
public cNBTTag \
|
||
|
{ \
|
||
|
public: \
|
||
|
cNBT##TAG(cNBTTag * a_Parent) : cNBTTag(a_Parent, TAG_##TAG) {} \
|
||
|
cNBT##TAG(cNBTTag * a_Parent, const AString & a_Name) : cNBTTag(a_Parent, TAG_##TAG, a_Name) {} \
|
||
|
cNBT##TAG(cNBTTag * a_Parent, const AString & a_Name, const CTYPE & a_Value) : cNBTTag(a_Parent, TAG_##TAG, a_Name), m_Value(a_Value) {} \
|
||
|
CTYPE m_Value; \
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
DECLARE_SIMPLE_TAG(Byte, char);
|
||
|
DECLARE_SIMPLE_TAG(Short, Int16);
|
||
|
DECLARE_SIMPLE_TAG(Int, Int32);
|
||
|
DECLARE_SIMPLE_TAG(Long, Int64);
|
||
|
DECLARE_SIMPLE_TAG(Float, float);
|
||
|
DECLARE_SIMPLE_TAG(Double, double);
|
||
|
DECLARE_SIMPLE_TAG(ByteArray, AString); // Represent the array as a string for easier manipulation
|
||
|
DECLARE_SIMPLE_TAG(String, AString);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
class cNBTList :
|
||
|
public cNBTTag
|
||
|
{
|
||
|
cNBTTags m_Children;
|
||
|
eTagType m_ChildrenType;
|
||
|
|
||
|
public:
|
||
|
cNBTList(cNBTTag * a_Parent) : cNBTTag(a_Parent, TAG_List), m_ChildrenType(TAG_End) {}
|
||
|
cNBTList(cNBTTag * a_Parent, const AString & a_Name) : cNBTTag(a_Parent, TAG_List, a_Name), m_ChildrenType(TAG_End) {}
|
||
|
virtual ~cNBTList() {Clear(); }
|
||
|
|
||
|
void Clear (void);
|
||
|
int Add (cNBTTag * a_Tag);
|
||
|
cNBTTag * GetChildByIdx (size_t a_Index);
|
||
|
const cNBTTags & GetChildren (void) const {return m_Children; }
|
||
|
size_t GetChildrenCount(void) const {return m_Children.size(); }
|
||
|
virtual cNBTTag * FindChildByName (const AString & a_Name) override;
|
||
|
|
||
|
int SetChildrenType(eTagType a_Type); // Only valid when list empty
|
||
|
eTagType GetChildrenType(void) const {return m_ChildrenType; }
|
||
|
} ;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
class cNBTCompound :
|
||
|
public cNBTTag
|
||
|
{
|
||
|
cNBTTags m_Children;
|
||
|
public:
|
||
|
cNBTCompound(cNBTTag * a_Parent) : cNBTTag(a_Parent, TAG_Compound) {}
|
||
|
cNBTCompound(cNBTTag * a_Parent, const AString & a_Name) : cNBTTag(a_Parent, TAG_Compound, a_Name) {}
|
||
|
virtual ~cNBTCompound() {Clear(); }
|
||
|
|
||
|
void Clear (void);
|
||
|
int Add (cNBTTag * a_Tag);
|
||
|
cNBTTag * GetChildByIdx (size_t a_Index);
|
||
|
const cNBTTags & GetChildren (void) const {return m_Children; }
|
||
|
size_t GetChildrenCount(void) const {return m_Children.size(); }
|
||
|
virtual cNBTTag * FindChildByName (const AString & a_Name) override;
|
||
|
} ;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
class cNBTIntArray :
|
||
|
public cNBTTag
|
||
|
{
|
||
|
typedef cNBTTag super;
|
||
|
|
||
|
std::vector<int> m_Values;
|
||
|
|
||
|
public:
|
||
|
cNBTIntArray(cNBTTag * a_Parent) : super(a_Parent, TAG_IntArray) {}
|
||
|
cNBTIntArray(cNBTTag * a_Parent, const AString & a_Name) : super(a_Parent, TAG_IntArray, a_Name) {}
|
||
|
|
||
|
void Clear(void) {m_Values.clear(); }
|
||
|
void Add (int a_Value) {m_Values.push_back(a_Value); }
|
||
|
int Get (int a_Index) const {return m_Values[a_Index]; }
|
||
|
int Size (void) const {return m_Values.size(); }
|
||
|
const std::vector<int> & GetValues(void) const {return m_Values; }
|
||
|
} ;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// The parser:
|
||
|
|
||
|
class cNBTParser
|
||
|
{
|
||
|
static int ReadTag (const char ** Data, int * Length, cNBTTag::eTagType iType, const AString & a_Name, cNBTTag * iParent, cNBTTag ** oTag); // Helper
|
||
|
|
||
|
static int ReadByte (const char ** Data, int * Length, char & a_Value);
|
||
|
static int ReadInt16 (const char ** Data, int * Length, Int16 & a_Value);
|
||
|
static int ReadInt32 (const char ** Data, int * Length, Int32 & a_Value);
|
||
|
static int ReadInt64 (const char ** Data, int * Length, Int64 & a_Value);
|
||
|
static int ReadFloat (const char ** Data, int * Length, float & a_Value);
|
||
|
static int ReadDouble (const char ** Data, int * Length, double & a_Value);
|
||
|
static int ReadByteArray(const char ** Data, int * Length, AString & a_Value);
|
||
|
static int ReadString (const char ** Data, int * Length, AString & a_Value);
|
||
|
static int ReadList (const char ** Data, int * Length, cNBTList * a_List);
|
||
|
static int ReadCompound (const char ** Data, int * Length, cNBTCompound * a_Compound);
|
||
|
static int ReadIntArray (const char ** Data, int * Length, cNBTIntArray * a_Array);
|
||
|
|
||
|
public:
|
||
|
|
||
|
/// Returns the parsed tree, or NULL on failure
|
||
|
static cNBTTree * Parse(const char * a_Data, int a_Length);
|
||
|
} ;
|
||
|
|
||
|
|
||
|
|
||
|
|