summaryrefslogtreecommitdiffstats
path: root/source/NBT.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/NBT.cpp899
1 files changed, 0 insertions, 899 deletions
diff --git a/source/NBT.cpp b/source/NBT.cpp
deleted file mode 100644
index ba2f3d0f6..000000000
--- a/source/NBT.cpp
+++ /dev/null
@@ -1,899 +0,0 @@
-
-// NBT.cpp
-
-// Implements the classes used for NBT representation, parsing and serializing
-
-/*
-This file has been retrofitted from a different project of mine (_Xoft(o)) and melded here, so it is not strictyl MCS-styled
-Also the project used error codes, which MCS doesn't need, so they were declared locally only.
-The code is not strictly safe, it could leak pointers when exceptions are thrown. It could use a RAII redesign.
-*/
-
-#include "Globals.h"
-#include "NBT.h"
-#include "Endianness.h"
-
-
-
-
-
-// Error codes
-// Unused by MCS
-enum
-{
- ERROR_PRIVATE_BASE = 0x00040000,
-
- ERROR_PRIVATE_NBTPARSER_BADTYPE, // The parsed type is not recognized
- ERROR_PRIVATE_NBTPARSER_INVALIDLENGTH, // The parsed name has an invalid length (negative-length string etc.)
- ERROR_PRIVATE_NBTPARSER_UNEXPECTEDTAG, // The parser has encountered a tag that should not be at such a point
- ERROR_PRIVATE_NBTPARSER_TOOSHORT, // The parser was invoked on data that is too short
-
- ERROR_PRIVATE_NBT_UNINITIALIZEDLIST, // NBTList needs its ChildType set before adding items to it
- ERROR_PRIVATE_NBT_TYPEMISMATCH, // NBTList must have all of its children of the same type
- ERROR_PRIVATE_NBT_UNEXPECTEDTAG, // NBTList and NBTCompound cannot contain a TAG_End
- ERROR_PRIVATE_NBT_BADTYPE, // NBTList's children type cannot be set to such a value
- ERROR_PRIVATE_NBT_LISTNOTEMPTY, // NBTList must be empty to allow setting children type
- ERROR_PRIVATE_NBT_INDEXOUTOFRANGE, // Requesting an item with invalid index from a list or a compound
-
- ERROR_PRIVATE_UNKNOWN, // Unknown error
-} ;
-
-#ifndef ERROR_SUCCESS
- // This constant is actually #defined in the WinAPI; it cannot be put into the above enum, but needs to be #defined (for *nix)
- #define ERROR_SUCCESS 0
-#endif // ERROR_SUCCCESS
-
-#ifndef ERROR_NOT_ENOUGH_MEMORY
- // This constant is actually #defined in the WinAPI; it cannot be put into the above enum, but needs to be #defined (for *nix)
- #define ERROR_NOT_ENOUGH_MEMORY 8
-#endif // ERROR_NOT_ENOUGH_MEMORY
-
-
-
-
-
-#define RETURN_INT_IF_FAILED(X) {int r = X; if (r != ERROR_SUCCESS) return r; }
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cNBTTag:
-
-cNBTTag * cNBTTag::CreateTag(cNBTTag * a_Parent, eTagType a_Type, const AString & a_Name)
-{
- // Creates a new instance of a tag specified by a_Type, uses the correct class
- switch (a_Type)
- {
- case TAG_Byte: return new cNBTByte (a_Parent, a_Name);
- case TAG_Short: return new cNBTShort (a_Parent, a_Name);
- case TAG_Int: return new cNBTInt (a_Parent, a_Name);
- case TAG_Long: return new cNBTLong (a_Parent, a_Name);
- case TAG_Float: return new cNBTFloat (a_Parent, a_Name);
- case TAG_Double: return new cNBTDouble (a_Parent, a_Name);
- case TAG_ByteArray: return new cNBTByteArray(a_Parent, a_Name);
- case TAG_String: return new cNBTString (a_Parent, a_Name);
- case TAG_List: return new cNBTList (a_Parent, a_Name, TAG_End);
- case TAG_Compound: return new cNBTCompound (a_Parent, a_Name);
- default:
- {
- ASSERT(!"Unknown TAG type requested");
- return NULL;
- }
- }
-}
-
-
-
-
-
-const cNBTTag * cNBTTag::FindChildByPath(const AString & iPath) const
-{
- size_t PrevIdx = 0;
- size_t idx = iPath.find('\\');
- const cNBTTag * res = this;
- while ((res != NULL) && (idx != AString::npos))
- {
- res = res->FindChildByName(AString(iPath, PrevIdx, idx - PrevIdx));
- PrevIdx = idx + 1;
- idx = iPath.find('\\', PrevIdx);
- }
- if (res != NULL)
- {
- res = res->FindChildByName(AString(iPath, PrevIdx));
- }
- return res;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cNBTList:
-
-void cNBTList::Clear(void)
-{
- for (cNBTTags::iterator itr = m_Children.begin(); itr != m_Children.end(); ++itr)
- {
- delete *itr;
- }
- m_Children.clear();
-}
-
-
-
-
-int cNBTList::Add(cNBTTag * iTag)
-{
- // Catch usage errors while debugging:
- ASSERT(m_ChildrenType != TAG_End); // Didn't call SetChildrenType()
- ASSERT(iTag->GetType() == m_ChildrenType); // Child of different type
-
- // Catch errors while running:
- if (m_ChildrenType == TAG_End)
- {
- return ERROR_PRIVATE_NBT_UNINITIALIZEDLIST;
- }
- if (iTag->GetType() != m_ChildrenType)
- {
- return ERROR_PRIVATE_NBT_TYPEMISMATCH;
- }
-
- m_Children.push_back(iTag);
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTList::SetChildrenType(cNBTTag::eTagType a_Type)
-{
- // Catch usage errors while debugging:
- ASSERT(a_Type != TAG_End); // Invalid, though not specifically in the NBT spec
- ASSERT(m_Children.size() == 0); // Can change only when empty
-
- // Catch runtime errors:
- if (a_Type == TAG_End)
- {
- return ERROR_PRIVATE_NBT_BADTYPE;
- }
- if (m_Children.size() != 0)
- {
- return ERROR_PRIVATE_NBT_LISTNOTEMPTY;
- }
-
- m_ChildrenType = a_Type;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-cNBTTag * cNBTList::GetChildByIdx(size_t iIndex)
-{
- // Catch usage errors while debugging:
- ASSERT((iIndex >= 0) && (iIndex < m_Children.size()));
-
- // Catch runtime errors:
- if ((iIndex < 0) || (iIndex >= m_Children.size()))
- {
- return NULL;
- }
-
- return m_Children[iIndex];
-}
-
-
-
-
-
-cNBTTag * cNBTList::FindChildByName(const AString & a_Name) const
-{
- for (cNBTTags::const_iterator itr = m_Children.begin(); itr != m_Children.end(); ++itr)
- {
- if ((*itr)->GetName() == a_Name)
- {
- return *itr;
- }
- }
- return NULL;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cNBTCompound:
-
-void cNBTCompound::Clear(void)
-{
- for (cNBTTags::iterator itr = m_Children.begin(); itr != m_Children.end(); ++itr)
- {
- delete *itr;
- }
- m_Children.clear();
-}
-
-
-
-
-
-int cNBTCompound::Add(cNBTTag * iTag)
-{
- // Catch usage errors while debugging:
- ASSERT(iTag->GetType() != TAG_End);
-
- // Catch runtime errors:
- if (iTag->GetType() == TAG_End)
- {
- return ERROR_PRIVATE_NBT_UNEXPECTEDTAG;
- }
-
- m_Children.push_back(iTag);
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-cNBTTag * cNBTCompound::GetChildByIdx(size_t iIndex)
-{
- // Catch usage errors while debugging:
- ASSERT((iIndex >= 0) && (iIndex < m_Children.size()));
-
- // Catch runtime errors:
- if ((iIndex < 0) || (iIndex >= m_Children.size()))
- {
- return NULL;
- }
-
- return m_Children[iIndex];
-}
-
-
-
-
-
-cNBTTag * cNBTCompound::FindChildByName(const AString & a_Name) const
-{
- for (cNBTTags::const_iterator itr = m_Children.begin(); itr != m_Children.end(); ++itr)
- {
- if ((*itr)->GetName() == a_Name)
- {
- return *itr;
- }
- }
- return NULL;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cNBTParser:
-
-int cNBTParser::ReadByte(const char ** a_Data, int * a_Length, char & a_Value)
-{
- if (*a_Length < 1)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- a_Value = **a_Data;
- *a_Data += 1;
- *a_Length -= 1;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadInt16(const char ** a_Data, int * a_Length, Int16 & a_Value)
-{
- if (*a_Length < 2)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- a_Value = ntohs(*((Int16 *)*a_Data));
- *a_Data += 2;
- *a_Length -= 2;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadInt32(const char ** a_Data, int * a_Length, Int32 & a_Value)
-{
- if (*a_Length < 4)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- a_Value = ntohl(*((Int32 *)*a_Data));
- *a_Data += 4;
- *a_Length -= 4;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadInt64(const char ** a_Data, int * a_Length, Int64 & a_Value)
-{
- if (*a_Length < 8)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- a_Value = NetworkToHostLong8(*a_Data);
- *a_Data += 8;
- *a_Length -= 8;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadFloat(const char ** a_Data, int * a_Length, float & a_Value)
-{
- if (*a_Length < 4)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- // Read as a 32-bit integer, converting endianness, then reinterpret as float:
- Int32 tmp = ntohl(*((Int32 *)*a_Data));
- a_Value = *((float *)&tmp);
- *a_Data += 4;
- *a_Length -= 4;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadDouble(const char ** a_Data, int * a_Length, double & a_Value)
-{
- if (*a_Length < 8)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- a_Value = NetworkToHostDouble8(*a_Data);
- *a_Data += 8;
- *a_Length -= 8;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadByteArray(const char ** a_Data, int * a_Length, AString & a_String)
-{
- // Reads the short-counted string, adjusts a_Data and a_Length accordingly
- Int32 Len;
- RETURN_INT_IF_FAILED(ReadInt32(a_Data, a_Length, Len));
- if (Len < 0)
- {
- return ERROR_PRIVATE_NBTPARSER_INVALIDLENGTH;
- }
- if (*a_Length < Len)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- a_String.assign(*a_Data, Len);
- *a_Data += Len;
- *a_Length -= Len;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadString(const char ** a_Data, int * a_Length, AString & a_String)
-{
- // Reads the short-counted string, adjusts a_Data and a_Length accordingly
- if (*a_Length < 2)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- Int16 val = *((Int16 *)*a_Data);
- Int16 Len = ntohs(val);
- if (Len < 0)
- {
- return ERROR_PRIVATE_NBTPARSER_INVALIDLENGTH;
- }
- *a_Data += 2;
- *a_Length -= 2;
- if (*a_Length < Len)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- a_String.assign(*a_Data, Len);
- *a_Data += Len;
- *a_Length -= Len;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadList(const char ** a_Data, int * a_Length, cNBTList * a_List)
-{
- // Reads a_List's contents from a_Data; up to a_Length bytes may be used; adjusts a_Data and a_Length for after the list
- Int32 ItemCount;
- RETURN_INT_IF_FAILED(ReadInt32(a_Data, a_Length, ItemCount));
- for (Int32 i = 0; i < ItemCount; i++)
- {
- cNBTTag * child = NULL;
- RETURN_INT_IF_FAILED(ReadTag(a_Data, a_Length, a_List->GetChildrenType(), "", a_List, &child));
- if (child == NULL)
- {
- return ERROR_PRIVATE_UNKNOWN;
- }
- RETURN_INT_IF_FAILED(a_List->Add(child));
- } // for i - Items[]
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-int cNBTParser::ReadCompound(const char ** a_Data, int * a_Length, cNBTCompound * a_Compound)
-{
- // Reads a_Compound's contents from a_Data; up to a_Length bytes may be used; adjusts a_Data and a_Length for after the compound
- while (true)
- {
- char TagType = **a_Data;
- *a_Data += 1;
- *a_Length -= 1;
- if (TagType == cNBTTag::TAG_End)
- {
- return ERROR_SUCCESS;
- }
- AString Name;
- RETURN_INT_IF_FAILED(ReadString(a_Data, a_Length, Name));
- cNBTTag * child = NULL;
- RETURN_INT_IF_FAILED(ReadTag(a_Data, a_Length, (cNBTTag::eTagType)TagType, Name, a_Compound, &child));
- if (child == NULL)
- {
- return ERROR_PRIVATE_UNKNOWN;
- }
- RETURN_INT_IF_FAILED(a_Compound->Add(child));
- } // while (true)
-}
-
-
-
-
-int cNBTParser::ReadIntArray(const char ** a_Data, int * a_Length, cNBTIntArray * a_Array)
-{
- if (*a_Length < 4)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- int Count = ntohl(*((int *)*a_Data));
- *a_Data += 4;
- *a_Length -= 4;
- if (*a_Length < 4 * Count)
- {
- return ERROR_PRIVATE_NBTPARSER_TOOSHORT;
- }
- for (int i = 0; i < Count; i++)
- {
- int Value = ntohl(*((int *)*a_Data));
- a_Array->Add(Value);
- *a_Data += 4;
- }
- *a_Length -= 4 * Count;
- return ERROR_SUCCESS;
-}
-
-
-
-
-
-#define CASE_SIMPLE_TAG(TAGTYPE,CTYPE,FUNC) \
- case cNBTTag::TAG_##TAGTYPE: \
- { \
- CTYPE val; \
- RETURN_INT_IF_FAILED(Read##FUNC(a_Data, a_Length, val)); \
- *a_Tag = new cNBT##TAGTYPE(a_Parent, a_Name, val); \
- if (*a_Tag == NULL) \
- { \
- return ERROR_NOT_ENOUGH_MEMORY; \
- } \
- return ERROR_SUCCESS;\
- }
-
-int cNBTParser::ReadTag(const char ** a_Data, int * a_Length, cNBTTag::eTagType a_Type, const AString & a_Name, cNBTTag * a_Parent, cNBTTag ** a_Tag)
-{
- switch (a_Type)
- {
- CASE_SIMPLE_TAG(Byte, char, Byte)
- CASE_SIMPLE_TAG(Short, Int16, Int16)
- CASE_SIMPLE_TAG(Int, Int32, Int32)
- CASE_SIMPLE_TAG(Long, Int64, Int64)
- CASE_SIMPLE_TAG(Float, float, Float)
- CASE_SIMPLE_TAG(Double, double, Double)
- CASE_SIMPLE_TAG(ByteArray, AString, ByteArray)
- CASE_SIMPLE_TAG(String, AString, String)
-
- case cNBTTag::TAG_List:
- {
- char ItemType;
- RETURN_INT_IF_FAILED(ReadByte (a_Data, a_Length, ItemType));
- cNBTList * List = new cNBTList(a_Parent, a_Name, (cNBTTag::eTagType)ItemType);
- if (List == NULL)
- {
- return ERROR_NOT_ENOUGH_MEMORY;
- }
- RETURN_INT_IF_FAILED(ReadList(a_Data, a_Length, List));
- *a_Tag = List;
- return ERROR_SUCCESS;
- }
-
- case cNBTTag::TAG_Compound:
- {
- cNBTCompound * Compound = new cNBTCompound(a_Parent, a_Name);
- if (Compound == NULL)
- {
- return ERROR_NOT_ENOUGH_MEMORY;
- }
- RETURN_INT_IF_FAILED(ReadCompound(a_Data, a_Length, Compound));
- *a_Tag = Compound;
- return ERROR_SUCCESS;
- }
-
- case cNBTTag::TAG_IntArray:
- {
- cNBTIntArray * Array = new cNBTIntArray(a_Parent, a_Name);
- if (Array == NULL)
- {
- return ERROR_NOT_ENOUGH_MEMORY;
- }
- RETURN_INT_IF_FAILED(ReadIntArray(a_Data, a_Length, Array));
- *a_Tag = Array;
- return ERROR_SUCCESS;
- }
-
- default:
- {
- #if (defined(_DEBUG) && defined(_WIN32))
- OutputDebugString("Unhandled NBT tag type\n");
- cNBTTag * Parent = a_Parent, * Cur = a_Parent;
- while (Parent != NULL)
- {
- OutputDebugString("Parent:\n");
- Cur = Parent;
- Parent = Parent->GetParent();
- DumpTree(Cur);
- }
- OutputDebugString("Done\n");
- #endif // _DEBUG
- ASSERT(!"Unhandled NBT tag type");
- break;
- }
- } // switch (iType)
-
- return ERROR_PRIVATE_NBTPARSER_BADTYPE;
-}
-
-#undef CASE_SIMPLE_TAG
-
-
-
-
-cNBTTree * cNBTParser::Parse(const char * a_Data, int a_Length)
-{
- // Creates a NBT from a_Data
- if (a_Length < 3)
- {
- return NULL;
- }
- if (a_Data[0] != cNBTTag::TAG_Compound)
- {
- return NULL;
- }
- a_Data++;
- a_Length--;
- AString Name;
- if (ReadString(&a_Data, &a_Length, Name) != 0)
- {
- return NULL;
- }
- std::auto_ptr<cNBTCompound> Root(new cNBTCompound(NULL, Name));
- if (Root.get() == NULL)
- {
- return NULL;
- }
- if (ReadCompound(&a_Data, &a_Length, Root.get()) == 0)
- {
- return Root.release();
- }
- return NULL;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cNBTSerializer:
-
-void cNBTSerializer::WriteByte(AString & a_Out, const char a_Value)
-{
- a_Out.push_back(a_Value);
-}
-
-
-
-
-
-void cNBTSerializer::WriteInt16(AString & a_Out, const Int16 a_Value)
-{
- Int16 Val = htons(a_Value);
- a_Out.append((char *)&Val, 2);
-}
-
-
-
-
-
-void cNBTSerializer::WriteInt32(AString & a_Out, const Int32 a_Value)
-{
- Int32 Val = htonl(a_Value);
- a_Out.append((char *)&Val, 4);
-}
-
-
-
-
-
-void cNBTSerializer::WriteInt64(AString & a_Out, const Int64 a_Value)
-{
- Int64 Val = HostToNetwork8(&a_Value);
- a_Out.append((char *)&Val, 8);
-}
-
-
-
-
-
-void cNBTSerializer::WriteFloat(AString & a_Out, const float a_Value)
-{
- Int32 Val = htonl(*((u_long *)&a_Value));
- a_Out.append((char *)&Val, 4);
-}
-
-
-
-
-
-void cNBTSerializer::WriteDouble(AString & a_Out, const double a_Value)
-{
- Int64 Val = HostToNetwork8(&a_Value);
- a_Out.append((char *)&Val, 8);
-}
-
-
-
-
-
-void cNBTSerializer::WriteByteArray(AString & a_Out, const AString & a_Value)
-{
- WriteInt32(a_Out, a_Value.size());
- a_Out.append(a_Value);
-}
-
-
-
-
-
-void cNBTSerializer::WriteString(AString & a_Out, const AString & a_String)
-{
- WriteInt16(a_Out, a_String.length());
- a_Out.append(a_String);
-}
-
-
-
-
-
-void cNBTSerializer::WriteList(AString & a_Out, const cNBTList * a_List)
-{
- WriteInt32(a_Out, a_List->GetChildrenCount());
- const cNBTTags & Children = a_List->GetChildren();
- for (cNBTTags::const_iterator itr = Children.begin(); itr != Children.end(); ++itr)
- {
- WriteTag(a_Out, *itr);
- } // for itr - Children[]
-}
-
-
-
-
-
-void cNBTSerializer::WriteIntArray(AString & a_Out, const cNBTIntArray * a_Array)
-{
- WriteInt32(a_Out, a_Array->GetValues().size());
- const std::vector<int> & Values = a_Array->GetValues();
- for (std::vector<int>::const_iterator itr = Values.begin(); itr != Values.end(); ++itr)
- {
- WriteInt32(a_Out, *itr);
- } // for itr - Values[]
-}
-
-
-
-
-
-void cNBTSerializer::WriteCompound(AString & a_Out, const cNBTCompound * a_Compound)
-{
- const cNBTTags & Children = a_Compound->GetChildren();
- for (cNBTTags::const_iterator itr = Children.begin(); itr != Children.end(); ++itr)
- {
- a_Out.push_back((*itr)->GetType());
- WriteString(a_Out, (*itr)->GetName());
- WriteTag(a_Out, *itr);
- } // for itr - Children[]
- a_Out.push_back(cNBTTag::TAG_End);
-}
-
-
-
-
-
-#define CASE_SIMPLE_TAG(TAGTYPE,CTYPE,FUNC) \
- case cNBTTag::TAG_##TAGTYPE: \
- { \
- Write##FUNC(a_Out, ((const cNBT##TAGTYPE *)a_Tag)->m_Value ); \
- return;\
- }
-
-void cNBTSerializer::WriteTag(AString & a_Out, const cNBTTag * a_Tag)
-{
- switch (a_Tag->GetType())
- {
- CASE_SIMPLE_TAG(Byte, char, Byte)
- CASE_SIMPLE_TAG(Short, Int16, Int16)
- CASE_SIMPLE_TAG(Int, Int32, Int32)
- CASE_SIMPLE_TAG(Long, Int64, Int64)
- CASE_SIMPLE_TAG(Float, float, Float)
- CASE_SIMPLE_TAG(Double, double, Double)
- CASE_SIMPLE_TAG(ByteArray, AString, ByteArray)
- CASE_SIMPLE_TAG(String, AString, String)
-
- case cNBTTag::TAG_List:
- {
- a_Out.push_back((char)((const cNBTList *)a_Tag)->GetChildrenType());
- WriteList(a_Out, (const cNBTList *)a_Tag);
- return;
- }
-
- case cNBTTag::TAG_Compound:
- {
- WriteCompound(a_Out, (const cNBTCompound *)a_Tag);
- return;
- }
-
- case cNBTTag::TAG_IntArray:
- {
- WriteIntArray(a_Out, (const cNBTIntArray *)a_Tag);
- return;
- }
- } // switch (iType)
-
- ASSERT(!"Unhandled NBT tag type");
-}
-
-#undef CASE_SIMPLE_TAG
-
-
-
-
-void cNBTSerializer::Serialize(const cNBTTree * a_Tree, AString & a_Out)
-{
- a_Out.clear();
- a_Out.push_back(cNBTTag::TAG_Compound);
- WriteString(a_Out, a_Tree->GetName());
- WriteCompound(a_Out, (const cNBTCompound *)a_Tree);
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Dumping the NBT tree (debug-only)
-
-#if (defined(_DEBUG) && defined(_WIN32))
-
-#define CASE_SIMPLE_TAG(TYPE,FMT) \
- case cNBTTag::TAG_##TYPE: \
- { \
- AString out; \
- Printf(out, "%sTAG_" TEXT(#TYPE) TEXT("(\"%hs\"): %") TEXT(FMT) TEXT("\n"), Indent.c_str(), a_Tree->GetName().c_str(), ((cNBT##TYPE *)a_Tree)->m_Value); \
- OutputDebugString(out.c_str()); \
- break; \
- }
-
-void DumpTree(const cNBTTree * a_Tree, int a_Level)
-{
- AString Indent(a_Level, TEXT(' '));
- switch (a_Tree->GetType())
- {
- CASE_SIMPLE_TAG(Byte, "d")
- CASE_SIMPLE_TAG(Short, "d")
- CASE_SIMPLE_TAG(Int, "d")
- CASE_SIMPLE_TAG(Long, "I64d")
- CASE_SIMPLE_TAG(Float, "f")
- CASE_SIMPLE_TAG(Double, "f")
-
- case cNBTTag::TAG_ByteArray:
- {
- AString out;
- Printf(out, "%sTAG_ByteArray(\"%hs\"): %d bytes\n", Indent.c_str(), a_Tree->GetName().c_str(), ((cNBTByteArray *)a_Tree)->m_Value.size());
- OutputDebugString(out.c_str());
- break;
- }
-
- case cNBTTag::TAG_String:
- {
- AString out;
- Printf(out, "%sTAG_String(\"%hs\"): %d bytes: \"%hs\"\n", Indent.c_str(), a_Tree->GetName().c_str(), ((cNBTString *)a_Tree)->m_Value.size(), ((cNBTString *)a_Tree)->m_Value.c_str());
- OutputDebugString(out.c_str());
- break;
- }
-
- case cNBTTag::TAG_List:
- {
- const cNBTTags & Children = ((cNBTList *)a_Tree)->GetChildren();
- AString out;
- Printf(out, "%sTAG_List(\"%hs\"): %d items of type %d\n%s{\n", Indent.c_str(), a_Tree->GetName().c_str(), Children.size(), ((cNBTList *)a_Tree)->GetChildrenType(), Indent.c_str());
- OutputDebugString(out.c_str());
- for (cNBTTags::const_iterator itr = Children.begin(); itr != Children.end(); ++itr)
- {
- DumpTree(*itr, a_Level + 1);
- } // for itr - Children[]
- Printf(out, "%s}\n", Indent.c_str());
- OutputDebugString(out.c_str());
- break;
- }
-
- case cNBTTag::TAG_Compound:
- {
- const cNBTTags & Children = ((cNBTCompound *)a_Tree)->GetChildren();
- AString out;
- Printf(out, "%sTAG_Compound(\"%hs\"): %d items\n%s{\n", Indent.c_str(), a_Tree->GetName().c_str(), Children.size(), Indent.c_str());
- OutputDebugString(out.c_str());
- for (cNBTTags::const_iterator itr = Children.begin(); itr != Children.end(); ++itr)
- {
- DumpTree(*itr, a_Level + 1);
- } // for itr - Children[]
- Printf(out, "%s}\n", Indent.c_str());
- OutputDebugString(out.c_str());
- break;
- }
- }
-}
-
-#undef CASE_SIMPLE_TAG
-
-#endif // (_DEBUG && _WIN32)
-
-
-
-