From a4a418a679f1ac760a8763edd856f0178cfc6dde Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Fri, 25 May 2012 07:18:52 +0000 Subject: Merged the composable_generator branch into the trunk git-svn-id: http://mc-server.googlecode.com/svn/trunk@504 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/NBT.cpp | 899 --------------------------------------------------------- 1 file changed, 899 deletions(-) delete mode 100644 source/NBT.cpp (limited to 'source/NBT.cpp') 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 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 & Values = a_Array->GetValues(); - for (std::vector::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) - - - - -- cgit v1.2.3