summaryrefslogtreecommitdiffstats
path: root/source/FastNBT.cpp
diff options
context:
space:
mode:
authorcedeel@gmail.com <cedeel@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-06-14 15:06:06 +0200
committercedeel@gmail.com <cedeel@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-06-14 15:06:06 +0200
commit92c59963f82f81aa3202657e7fdbb2592924ede3 (patch)
treeb7eb2474528a4998fa102e3ec9119b908cee08b4 /source/FastNBT.cpp
parentAdded HOOK_WEATHER_CHANGE. (diff)
downloadcuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar
cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.gz
cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.bz2
cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.lz
cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.xz
cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.zst
cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.zip
Diffstat (limited to 'source/FastNBT.cpp')
-rw-r--r--source/FastNBT.cpp1060
1 files changed, 530 insertions, 530 deletions
diff --git a/source/FastNBT.cpp b/source/FastNBT.cpp
index 9854fe3bc..773aecf62 100644
--- a/source/FastNBT.cpp
+++ b/source/FastNBT.cpp
@@ -1,530 +1,530 @@
-
-// FastNBT.cpp
-
-// Implements the fast NBT parser and writer
-
-#include "Globals.h"
-#include "FastNBT.h"
-
-
-
-
-
-#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while (0)
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cParsedNBT:
-
-#define NEEDBYTES(N) \
- if (m_Length - m_Pos < N) \
- { \
- return false; \
- }
-
-
-
-
-
-cParsedNBT::cParsedNBT(const char * a_Data, int a_Length) :
- m_Data(a_Data),
- m_Length(a_Length),
- m_Pos(0)
-{
- m_IsValid = Parse();
-}
-
-
-
-
-
-bool cParsedNBT::Parse(void)
-{
- if (m_Length < 3)
- {
- // Data too short
- return false;
- }
- if (m_Data[0] != TAG_Compound)
- {
- // The top-level tag must be a Compound
- return false;
- }
-
- m_Tags.reserve(200);
-
- m_Tags.push_back(cFastNBTTag(TAG_Compound, -1));
-
- m_Pos = 1;
-
- RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
- RETURN_FALSE_IF_FALSE(ReadCompound());
-
- return true;
-}
-
-
-
-
-
-bool cParsedNBT::ReadString(int & a_StringStart, int & a_StringLen)
-{
- NEEDBYTES(2);
- a_StringStart = m_Pos + 2;
- a_StringLen = ntohs(*((short *)(m_Data + m_Pos)));
- if (a_StringLen < 0)
- {
- // Invalid string length
- return false;
- }
- m_Pos += 2 + a_StringLen;
- return true;
-}
-
-
-
-
-
-bool cParsedNBT::ReadCompound(void)
-{
- // Reads the latest tag as a compound
- int ParentIdx = m_Tags.size() - 1;
- int PrevSibling = -1;
- while (true)
- {
- NEEDBYTES(1);
- eTagType TagType = (eTagType)(m_Data[m_Pos]);
- m_Pos++;
- if (TagType == TAG_End)
- {
- break;
- }
- m_Tags.push_back(cFastNBTTag(TagType, ParentIdx, PrevSibling));
- if (PrevSibling >= 0)
- {
- m_Tags[PrevSibling].m_NextSibling = m_Tags.size() - 1;
- }
- else
- {
- m_Tags[ParentIdx].m_FirstChild = m_Tags.size() - 1;
- }
- PrevSibling = m_Tags.size() - 1;
- RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
- RETURN_FALSE_IF_FALSE(ReadTag());
- } // while (true)
- m_Tags[ParentIdx].m_LastChild = PrevSibling;
- return true;
-}
-
-
-
-
-
-bool cParsedNBT::ReadList(eTagType a_ChildrenType)
-{
- // Reads the latest tag as a list of items of type a_ChildrenType
-
- // Read the count:
- NEEDBYTES(4);
- int Count = ntohl(*((int *)(m_Data + m_Pos)));
- m_Pos += 4;
- if (Count < 0)
- {
- return false;
- }
-
- // Read items:
- int ParentIdx = m_Tags.size() - 1;
- int PrevSibling = -1;
- for (int i = 0; i < Count; i++)
- {
- m_Tags.push_back(cFastNBTTag(a_ChildrenType, ParentIdx, PrevSibling));
- if (PrevSibling >= 0)
- {
- m_Tags[PrevSibling].m_NextSibling = m_Tags.size() - 1;
- }
- else
- {
- m_Tags[ParentIdx].m_FirstChild = m_Tags.size() - 1;
- }
- PrevSibling = m_Tags.size() - 1;
- RETURN_FALSE_IF_FALSE(ReadTag());
- } // for (i)
- m_Tags[ParentIdx].m_LastChild = PrevSibling;
- return true;
-}
-
-
-
-
-
-#define CASE_SIMPLE_TAG(TAGTYPE, LEN) \
- case TAG_##TAGTYPE: \
- { \
- NEEDBYTES(LEN); \
- Tag.m_DataStart = m_Pos; \
- Tag.m_DataLength = LEN; \
- m_Pos += LEN; \
- return true; \
- }
-
-bool cParsedNBT::ReadTag(void)
-{
- cFastNBTTag & Tag = m_Tags.back();
- switch (Tag.m_Type)
- {
- CASE_SIMPLE_TAG(Byte, 1)
- CASE_SIMPLE_TAG(Short, 2)
- CASE_SIMPLE_TAG(Int, 4)
- CASE_SIMPLE_TAG(Long, 8)
- CASE_SIMPLE_TAG(Float, 4)
- CASE_SIMPLE_TAG(Double, 8)
-
- case TAG_String:
- {
- return ReadString(Tag.m_DataStart, Tag.m_DataLength);
- }
-
- case TAG_ByteArray:
- {
- NEEDBYTES(4);
- int len = ntohl(*((int *)(m_Data + m_Pos)));
- m_Pos += 4;
- if (len < 0)
- {
- // Invalid length
- return false;
- }
- NEEDBYTES(len);
- Tag.m_DataLength = len;
- Tag.m_DataStart = m_Pos;
- m_Pos += len;
- return true;
- }
-
- case TAG_List:
- {
- NEEDBYTES(1);
- eTagType ItemType = (eTagType)m_Data[m_Pos];
- m_Pos++;
- RETURN_FALSE_IF_FALSE(ReadList(ItemType));
- return true;
- }
-
- case TAG_Compound:
- {
- RETURN_FALSE_IF_FALSE(ReadCompound());
- return true;
- }
-
- case TAG_IntArray:
- {
- NEEDBYTES(4);
- int len = ntohl(*((int *)(m_Data + m_Pos)));
- m_Pos += 4;
- if (len < 0)
- {
- // Invalid length
- return false;
- }
- len *= 4;
- NEEDBYTES(len);
- Tag.m_DataLength = len;
- Tag.m_DataStart = m_Pos;
- m_Pos += len;
- return true;
- }
-
- default:
- {
- ASSERT(!"Unhandled NBT tag type");
- return false;
- }
- } // switch (iType)
-}
-
-#undef CASE_SIMPLE_TAG
-
-
-
-
-
-int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength) const
-{
- if (a_Tag < 0)
- {
- return -1;
- }
- if (m_Tags[a_Tag].m_Type != TAG_Compound)
- {
- return -1;
- }
-
- if (a_NameLength == 0)
- {
- a_NameLength = strlen(a_Name);
- }
- for (int Child = m_Tags[a_Tag].m_FirstChild; Child != -1; Child = m_Tags[Child].m_NextSibling)
- {
- if (
- (m_Tags[Child].m_NameLength == a_NameLength) &&
- (memcmp(m_Data + m_Tags[Child].m_NameStart, a_Name, a_NameLength) == 0)
- )
- {
- return Child;
- }
- } // for Child - children of a_Tag
- return -1;
-}
-
-
-
-
-
-int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
-{
- if (a_Tag < 0)
- {
- return -1;
- }
- size_t Begin = 0;
- size_t Length = a_Path.length();
- int Tag = a_Tag;
- for (size_t i = 0; i < Length; i++)
- {
- if (a_Path[i] != '\\')
- {
- continue;
- }
- Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin - 1);
- if (Tag < 0)
- {
- return -1;
- }
- Begin = i + 1;
- } // for i - a_Path[]
-
- if (Begin < Length)
- {
- Tag = FindChildByName(Tag, a_Path.c_str() + Begin, Length - Begin);
- }
- return Tag;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cFastNBTWriter:
-
-cFastNBTWriter::cFastNBTWriter(void) :
- m_CurrentStack(0)
-{
- m_Stack[0].m_Type = TAG_Compound;
- m_Result.reserve(100 * 1024);
- m_Result.push_back(TAG_Compound);
- WriteString("", 0);
-}
-
-
-
-
-
-void cFastNBTWriter::BeginCompound(const AString & a_Name)
-{
- if (m_CurrentStack >= MAX_STACK)
- {
- ASSERT(!"Stack overflow");
- return;
- }
-
- TagCommon(a_Name, TAG_Compound);
-
- ++m_CurrentStack;
- m_Stack[m_CurrentStack].m_Type = TAG_Compound;
-}
-
-
-
-
-
-void cFastNBTWriter::EndCompound(void)
-{
- ASSERT(m_CurrentStack > 0);
- ASSERT(IsStackTopCompound());
-
- m_Result.push_back(TAG_End);
- --m_CurrentStack;
-}
-
-
-
-
-
-void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType)
-{
- if (m_CurrentStack >= MAX_STACK)
- {
- ASSERT(!"Stack overflow");
- return;
- }
-
- TagCommon(a_Name, TAG_List);
-
- m_Result.push_back((char)a_ChildrenType);
- m_Result.append(4, (char)0);
-
- ++m_CurrentStack;
- m_Stack[m_CurrentStack].m_Type = TAG_List;
- m_Stack[m_CurrentStack].m_Pos = m_Result.size() - 4;
- m_Stack[m_CurrentStack].m_Count = 0;
-}
-
-
-
-
-
-void cFastNBTWriter::EndList(void)
-{
- ASSERT(m_CurrentStack > 0);
- ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);
-
- // Update the list count:
- *((int *)(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos)) = htonl(m_Stack[m_CurrentStack].m_Count);
-
- --m_CurrentStack;
-}
-
-
-
-
-
-void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value)
-{
- TagCommon(a_Name, TAG_Byte);
- m_Result.push_back(a_Value);
-}
-
-
-
-
-
-void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
-{
- TagCommon(a_Name, TAG_Short);
- Int16 Value = htons(a_Value);
- m_Result.append((const char *)&Value, 2);
-}
-
-
-
-
-
-void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
-{
- TagCommon(a_Name, TAG_Int);
- Int32 Value = htonl(a_Value);
- m_Result.append((const char *)&Value, 4);
-}
-
-
-
-
-
-void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
-{
- TagCommon(a_Name, TAG_Long);
- Int64 Value = HostToNetwork8(&a_Value);
- m_Result.append((const char *)&Value, 8);
-}
-
-
-
-
-
-void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
-{
- TagCommon(a_Name, TAG_Float);
- Int32 Value = HostToNetwork4(&a_Value);
- m_Result.append((const char *)&Value, 4);
-}
-
-
-
-
-
-void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
-{
- TagCommon(a_Name, TAG_Double);
- Int64 Value = HostToNetwork8(&a_Value);
- m_Result.append((const char *)&Value, 8);
-}
-
-
-
-
-
-void cFastNBTWriter::AddString(const AString & a_Name, const AString & a_Value)
-{
- TagCommon(a_Name, TAG_String);
- Int16 len = htons((short)(a_Value.size()));
- m_Result.append((const char *)&len, 2);
- m_Result.append(a_Value.c_str(), a_Value.size());
-}
-
-
-
-
-
-void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements)
-{
- TagCommon(a_Name, TAG_ByteArray);
- Int32 len = htonl(a_NumElements);
- m_Result.append((const char *)&len, 4);
- m_Result.append(a_Value, a_NumElements);
-}
-
-
-
-
-
-void cFastNBTWriter::AddIntArray(const AString & a_Name, const int * a_Value, size_t a_NumElements)
-{
- TagCommon(a_Name, TAG_IntArray);
- Int32 len = htonl(a_NumElements);
- m_Result.append((const char *)&len, 2);
- int * Elements = (int *)(m_Result.data() + m_Result.size());
- m_Result.append(a_NumElements * 4, (char)0);
- for (size_t i = 0; i < a_NumElements; i++)
- {
- Elements[i] = htonl(a_Value[i]);
- }
-}
-
-
-
-
-void cFastNBTWriter::Finish(void)
-{
- ASSERT(m_CurrentStack == 0);
- m_Result.push_back(TAG_End);
-}
-
-
-
-
-
-void cFastNBTWriter::WriteString(const char * a_Data, short a_Length)
-{
- Int16 Len = htons(a_Length);
- m_Result.append((const char *)&Len, 2);
- m_Result.append(a_Data, a_Length);
-}
-
-
-
-
+
+// FastNBT.cpp
+
+// Implements the fast NBT parser and writer
+
+#include "Globals.h"
+#include "FastNBT.h"
+
+
+
+
+
+#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while (0)
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cParsedNBT:
+
+#define NEEDBYTES(N) \
+ if (m_Length - m_Pos < N) \
+ { \
+ return false; \
+ }
+
+
+
+
+
+cParsedNBT::cParsedNBT(const char * a_Data, int a_Length) :
+ m_Data(a_Data),
+ m_Length(a_Length),
+ m_Pos(0)
+{
+ m_IsValid = Parse();
+}
+
+
+
+
+
+bool cParsedNBT::Parse(void)
+{
+ if (m_Length < 3)
+ {
+ // Data too short
+ return false;
+ }
+ if (m_Data[0] != TAG_Compound)
+ {
+ // The top-level tag must be a Compound
+ return false;
+ }
+
+ m_Tags.reserve(200);
+
+ m_Tags.push_back(cFastNBTTag(TAG_Compound, -1));
+
+ m_Pos = 1;
+
+ RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
+ RETURN_FALSE_IF_FALSE(ReadCompound());
+
+ return true;
+}
+
+
+
+
+
+bool cParsedNBT::ReadString(int & a_StringStart, int & a_StringLen)
+{
+ NEEDBYTES(2);
+ a_StringStart = m_Pos + 2;
+ a_StringLen = ntohs(*((short *)(m_Data + m_Pos)));
+ if (a_StringLen < 0)
+ {
+ // Invalid string length
+ return false;
+ }
+ m_Pos += 2 + a_StringLen;
+ return true;
+}
+
+
+
+
+
+bool cParsedNBT::ReadCompound(void)
+{
+ // Reads the latest tag as a compound
+ int ParentIdx = m_Tags.size() - 1;
+ int PrevSibling = -1;
+ while (true)
+ {
+ NEEDBYTES(1);
+ eTagType TagType = (eTagType)(m_Data[m_Pos]);
+ m_Pos++;
+ if (TagType == TAG_End)
+ {
+ break;
+ }
+ m_Tags.push_back(cFastNBTTag(TagType, ParentIdx, PrevSibling));
+ if (PrevSibling >= 0)
+ {
+ m_Tags[PrevSibling].m_NextSibling = m_Tags.size() - 1;
+ }
+ else
+ {
+ m_Tags[ParentIdx].m_FirstChild = m_Tags.size() - 1;
+ }
+ PrevSibling = m_Tags.size() - 1;
+ RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
+ RETURN_FALSE_IF_FALSE(ReadTag());
+ } // while (true)
+ m_Tags[ParentIdx].m_LastChild = PrevSibling;
+ return true;
+}
+
+
+
+
+
+bool cParsedNBT::ReadList(eTagType a_ChildrenType)
+{
+ // Reads the latest tag as a list of items of type a_ChildrenType
+
+ // Read the count:
+ NEEDBYTES(4);
+ int Count = ntohl(*((int *)(m_Data + m_Pos)));
+ m_Pos += 4;
+ if (Count < 0)
+ {
+ return false;
+ }
+
+ // Read items:
+ int ParentIdx = m_Tags.size() - 1;
+ int PrevSibling = -1;
+ for (int i = 0; i < Count; i++)
+ {
+ m_Tags.push_back(cFastNBTTag(a_ChildrenType, ParentIdx, PrevSibling));
+ if (PrevSibling >= 0)
+ {
+ m_Tags[PrevSibling].m_NextSibling = m_Tags.size() - 1;
+ }
+ else
+ {
+ m_Tags[ParentIdx].m_FirstChild = m_Tags.size() - 1;
+ }
+ PrevSibling = m_Tags.size() - 1;
+ RETURN_FALSE_IF_FALSE(ReadTag());
+ } // for (i)
+ m_Tags[ParentIdx].m_LastChild = PrevSibling;
+ return true;
+}
+
+
+
+
+
+#define CASE_SIMPLE_TAG(TAGTYPE, LEN) \
+ case TAG_##TAGTYPE: \
+ { \
+ NEEDBYTES(LEN); \
+ Tag.m_DataStart = m_Pos; \
+ Tag.m_DataLength = LEN; \
+ m_Pos += LEN; \
+ return true; \
+ }
+
+bool cParsedNBT::ReadTag(void)
+{
+ cFastNBTTag & Tag = m_Tags.back();
+ switch (Tag.m_Type)
+ {
+ CASE_SIMPLE_TAG(Byte, 1)
+ CASE_SIMPLE_TAG(Short, 2)
+ CASE_SIMPLE_TAG(Int, 4)
+ CASE_SIMPLE_TAG(Long, 8)
+ CASE_SIMPLE_TAG(Float, 4)
+ CASE_SIMPLE_TAG(Double, 8)
+
+ case TAG_String:
+ {
+ return ReadString(Tag.m_DataStart, Tag.m_DataLength);
+ }
+
+ case TAG_ByteArray:
+ {
+ NEEDBYTES(4);
+ int len = ntohl(*((int *)(m_Data + m_Pos)));
+ m_Pos += 4;
+ if (len < 0)
+ {
+ // Invalid length
+ return false;
+ }
+ NEEDBYTES(len);
+ Tag.m_DataLength = len;
+ Tag.m_DataStart = m_Pos;
+ m_Pos += len;
+ return true;
+ }
+
+ case TAG_List:
+ {
+ NEEDBYTES(1);
+ eTagType ItemType = (eTagType)m_Data[m_Pos];
+ m_Pos++;
+ RETURN_FALSE_IF_FALSE(ReadList(ItemType));
+ return true;
+ }
+
+ case TAG_Compound:
+ {
+ RETURN_FALSE_IF_FALSE(ReadCompound());
+ return true;
+ }
+
+ case TAG_IntArray:
+ {
+ NEEDBYTES(4);
+ int len = ntohl(*((int *)(m_Data + m_Pos)));
+ m_Pos += 4;
+ if (len < 0)
+ {
+ // Invalid length
+ return false;
+ }
+ len *= 4;
+ NEEDBYTES(len);
+ Tag.m_DataLength = len;
+ Tag.m_DataStart = m_Pos;
+ m_Pos += len;
+ return true;
+ }
+
+ default:
+ {
+ ASSERT(!"Unhandled NBT tag type");
+ return false;
+ }
+ } // switch (iType)
+}
+
+#undef CASE_SIMPLE_TAG
+
+
+
+
+
+int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength) const
+{
+ if (a_Tag < 0)
+ {
+ return -1;
+ }
+ if (m_Tags[a_Tag].m_Type != TAG_Compound)
+ {
+ return -1;
+ }
+
+ if (a_NameLength == 0)
+ {
+ a_NameLength = strlen(a_Name);
+ }
+ for (int Child = m_Tags[a_Tag].m_FirstChild; Child != -1; Child = m_Tags[Child].m_NextSibling)
+ {
+ if (
+ (m_Tags[Child].m_NameLength == a_NameLength) &&
+ (memcmp(m_Data + m_Tags[Child].m_NameStart, a_Name, a_NameLength) == 0)
+ )
+ {
+ return Child;
+ }
+ } // for Child - children of a_Tag
+ return -1;
+}
+
+
+
+
+
+int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
+{
+ if (a_Tag < 0)
+ {
+ return -1;
+ }
+ size_t Begin = 0;
+ size_t Length = a_Path.length();
+ int Tag = a_Tag;
+ for (size_t i = 0; i < Length; i++)
+ {
+ if (a_Path[i] != '\\')
+ {
+ continue;
+ }
+ Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin - 1);
+ if (Tag < 0)
+ {
+ return -1;
+ }
+ Begin = i + 1;
+ } // for i - a_Path[]
+
+ if (Begin < Length)
+ {
+ Tag = FindChildByName(Tag, a_Path.c_str() + Begin, Length - Begin);
+ }
+ return Tag;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cFastNBTWriter:
+
+cFastNBTWriter::cFastNBTWriter(void) :
+ m_CurrentStack(0)
+{
+ m_Stack[0].m_Type = TAG_Compound;
+ m_Result.reserve(100 * 1024);
+ m_Result.push_back(TAG_Compound);
+ WriteString("", 0);
+}
+
+
+
+
+
+void cFastNBTWriter::BeginCompound(const AString & a_Name)
+{
+ if (m_CurrentStack >= MAX_STACK)
+ {
+ ASSERT(!"Stack overflow");
+ return;
+ }
+
+ TagCommon(a_Name, TAG_Compound);
+
+ ++m_CurrentStack;
+ m_Stack[m_CurrentStack].m_Type = TAG_Compound;
+}
+
+
+
+
+
+void cFastNBTWriter::EndCompound(void)
+{
+ ASSERT(m_CurrentStack > 0);
+ ASSERT(IsStackTopCompound());
+
+ m_Result.push_back(TAG_End);
+ --m_CurrentStack;
+}
+
+
+
+
+
+void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType)
+{
+ if (m_CurrentStack >= MAX_STACK)
+ {
+ ASSERT(!"Stack overflow");
+ return;
+ }
+
+ TagCommon(a_Name, TAG_List);
+
+ m_Result.push_back((char)a_ChildrenType);
+ m_Result.append(4, (char)0);
+
+ ++m_CurrentStack;
+ m_Stack[m_CurrentStack].m_Type = TAG_List;
+ m_Stack[m_CurrentStack].m_Pos = m_Result.size() - 4;
+ m_Stack[m_CurrentStack].m_Count = 0;
+}
+
+
+
+
+
+void cFastNBTWriter::EndList(void)
+{
+ ASSERT(m_CurrentStack > 0);
+ ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);
+
+ // Update the list count:
+ *((int *)(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos)) = htonl(m_Stack[m_CurrentStack].m_Count);
+
+ --m_CurrentStack;
+}
+
+
+
+
+
+void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value)
+{
+ TagCommon(a_Name, TAG_Byte);
+ m_Result.push_back(a_Value);
+}
+
+
+
+
+
+void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
+{
+ TagCommon(a_Name, TAG_Short);
+ Int16 Value = htons(a_Value);
+ m_Result.append((const char *)&Value, 2);
+}
+
+
+
+
+
+void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
+{
+ TagCommon(a_Name, TAG_Int);
+ Int32 Value = htonl(a_Value);
+ m_Result.append((const char *)&Value, 4);
+}
+
+
+
+
+
+void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
+{
+ TagCommon(a_Name, TAG_Long);
+ Int64 Value = HostToNetwork8(&a_Value);
+ m_Result.append((const char *)&Value, 8);
+}
+
+
+
+
+
+void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
+{
+ TagCommon(a_Name, TAG_Float);
+ Int32 Value = HostToNetwork4(&a_Value);
+ m_Result.append((const char *)&Value, 4);
+}
+
+
+
+
+
+void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
+{
+ TagCommon(a_Name, TAG_Double);
+ Int64 Value = HostToNetwork8(&a_Value);
+ m_Result.append((const char *)&Value, 8);
+}
+
+
+
+
+
+void cFastNBTWriter::AddString(const AString & a_Name, const AString & a_Value)
+{
+ TagCommon(a_Name, TAG_String);
+ Int16 len = htons((short)(a_Value.size()));
+ m_Result.append((const char *)&len, 2);
+ m_Result.append(a_Value.c_str(), a_Value.size());
+}
+
+
+
+
+
+void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements)
+{
+ TagCommon(a_Name, TAG_ByteArray);
+ Int32 len = htonl(a_NumElements);
+ m_Result.append((const char *)&len, 4);
+ m_Result.append(a_Value, a_NumElements);
+}
+
+
+
+
+
+void cFastNBTWriter::AddIntArray(const AString & a_Name, const int * a_Value, size_t a_NumElements)
+{
+ TagCommon(a_Name, TAG_IntArray);
+ Int32 len = htonl(a_NumElements);
+ m_Result.append((const char *)&len, 2);
+ int * Elements = (int *)(m_Result.data() + m_Result.size());
+ m_Result.append(a_NumElements * 4, (char)0);
+ for (size_t i = 0; i < a_NumElements; i++)
+ {
+ Elements[i] = htonl(a_Value[i]);
+ }
+}
+
+
+
+
+void cFastNBTWriter::Finish(void)
+{
+ ASSERT(m_CurrentStack == 0);
+ m_Result.push_back(TAG_End);
+}
+
+
+
+
+
+void cFastNBTWriter::WriteString(const char * a_Data, short a_Length)
+{
+ Int16 Len = htons(a_Length);
+ m_Result.append((const char *)&Len, 2);
+ m_Result.append(a_Data, a_Length);
+}
+
+
+
+