summaryrefslogtreecommitdiffstats
path: root/source/NBT.h
blob: a05e574de81efea51bfe1ae88ab8e0449ad9c303 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

// 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) const {return NULL; }
	const cNBTTag * FindChildByPath(const AString & a_Path) const;
} ;

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





///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Dumping the tree (DEBUG-only)

#ifdef _DEBUG
void DumpTree(const cNBTTree * a_Tree, int a_Level = 0);
#endif  // _DEBUG