From 3fe1622eda7df9c11c1bc798e37629a5defca6b8 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Wed, 4 Apr 2012 12:07:38 +0000 Subject: Fixed a parsing error in NBT classes (doubles weren't parsing correctly); Added a working NBT serialization (verified in another project) git-svn-id: http://mc-server.googlecode.com/svn/trunk@451 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/NBT.cpp | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- source/NBT.h | 28 ++++++++ 2 files changed, 227 insertions(+), 1 deletion(-) diff --git a/source/NBT.cpp b/source/NBT.cpp index da743a8bc..af420cd27 100644 --- a/source/NBT.cpp +++ b/source/NBT.cpp @@ -367,7 +367,7 @@ int cNBTParser::ReadDouble(const char ** a_Data, int * a_Length, double & a_Valu { return ERROR_PRIVATE_NBTPARSER_TOOSHORT; } - a_Value = NetworkToHostDouble8(a_Data); + a_Value = NetworkToHostDouble8(*a_Data); *a_Data += 8; *a_Length -= 8; return ERROR_SUCCESS; @@ -572,6 +572,18 @@ int cNBTParser::ReadTag(const char ** a_Data, int * a_Length, cNBTTag::eTagType 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; } @@ -619,6 +631,192 @@ cNBTTree * cNBTParser::Parse(const char * a_Data, int a_Length) +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// 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) diff --git a/source/NBT.h b/source/NBT.h index 75ff6e361..6d3ecebd9 100644 --- a/source/NBT.h +++ b/source/NBT.h @@ -200,6 +200,34 @@ public: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// The serializer: + +class cNBTSerializer +{ + static void WriteTag (AString & a_Out, const cNBTTag * a_Tag); + + static void WriteByte (AString & a_Out, const char a_Value); + static void WriteInt16 (AString & a_Out, const Int16 a_Value); + static void WriteInt32 (AString & a_Out, const Int32 a_Value); + static void WriteInt64 (AString & a_Out, const Int64 a_Value); + static void WriteFloat (AString & a_Out, const float a_Value); + static void WriteDouble (AString & a_Out, const double a_Value); + static void WriteByteArray(AString & a_Out, const AString & a_Value); + static void WriteString (AString & a_Out, const AString & a_Value); + static void WriteList (AString & a_Out, const cNBTList * a_List); + static void WriteCompound (AString & a_Out, const cNBTCompound * a_Compound); + static void WriteIntArray (AString & a_Out, const cNBTIntArray * a_Array); + +public: + + static void Serialize(const cNBTTree * a_Tree, AString & a_Out); +} ; + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Dumping the tree (DEBUG-only) -- cgit v1.2.3