summaryrefslogblamecommitdiffstats
path: root/source/NBT.h
blob: 5bad0492caab5422ff0b05a47e1ed2c1e62bbc1c (plain) (tree)








































































































































































































                                                                                                                                                                                

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