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