2012-03-07 03:28:24 -08:00
// 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
2012-03-07 14:09:55 -08:00
virtual cNBTTag * FindChildByName ( const AString & a_Name ) const { return NULL ; }
const cNBTTag * FindChildByPath ( const AString & a_Path ) const ;
2012-03-07 03:28:24 -08:00
} ;
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 ( ) ; }
2012-03-07 14:09:55 -08:00
virtual cNBTTag * FindChildByName ( const AString & a_Name ) const override ;
2012-03-07 03:28:24 -08:00
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 ( ) ; }
2012-03-07 14:09:55 -08:00
virtual cNBTTag * FindChildByName ( const AString & a_Name ) const override ;
2012-03-07 03:28:24 -08:00
} ;
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 ) ;
} ;
2012-03-07 14:09:55 -08:00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Dumping the tree (DEBUG-only)
# ifdef _DEBUG
void DumpTree ( const cNBTTree * a_Tree , int a_Level = 0 ) ;
# endif // _DEBUG