682 lines
24 KiB
C++
682 lines
24 KiB
C++
#pragma once
|
|
|
|
// -
|
|
// - TRF : Template-based Recursive Format
|
|
// -
|
|
// - trfMapper.h
|
|
// -
|
|
// - Lazy TRF stream mapper for low-overhead loading
|
|
// -
|
|
// - 2006.2.14 by Young-Hyun Joo, nFlavor
|
|
// -
|
|
|
|
#include "TrfMetaData.h"
|
|
#include "../toolkit/c_array.h"
|
|
#include <guiddef.h>
|
|
#include <assert.h>
|
|
|
|
namespace trf {
|
|
|
|
|
|
struct MapperObjects
|
|
{
|
|
typedef const class MTemplate* TemplatePtr;
|
|
typedef const class MTemplateArray* TemplateArrayPtr;
|
|
typedef const class MArray* ArrayPtr;
|
|
typedef const class MDict* DictPtr;
|
|
};
|
|
|
|
typedef const class MTemplate* MTemplatePtr;
|
|
typedef const class MTemplateArray* MTemplateArrayPtr;
|
|
typedef const class MArray* MArrayPtr;
|
|
typedef const class MDict* MDictPtr;
|
|
|
|
class Mapper
|
|
{
|
|
public:
|
|
|
|
Mapper( const MetaData* pMetaData, const void* pBuf, int bufSize );
|
|
~Mapper();
|
|
|
|
const MetaData* metaData() { return m_pMetaData; }
|
|
MDictPtr root() { return m_pRoot; }
|
|
|
|
private:
|
|
|
|
friend class MArray;
|
|
friend class MTemplate;
|
|
friend class MTemplateArray;
|
|
friend class MDict;
|
|
|
|
const char* initIdTable( const char* pBuf );
|
|
const char* initStringTable( const char* pBuf );
|
|
const char* getString( int i );
|
|
const wchar_t* getWString( int i );
|
|
const GUID& getId( int i );
|
|
|
|
const MetaData* m_pMetaData;
|
|
MDict* m_pRoot;
|
|
|
|
const char* m_pBuf;
|
|
const char* m_pBufEnd;
|
|
|
|
int m_idCount;
|
|
const GUID* m_pId;
|
|
|
|
c_array< const char* > m_stringTable;
|
|
c_array< const wchar_t* > m_wstringTable;
|
|
|
|
c_array< ATInfo > m_ATIs;
|
|
c_array< short > m_TInfoIndexTable;
|
|
|
|
bool m_bUnpackedDict;
|
|
|
|
const ATInfo* getATI( const GUID& id );
|
|
const ATInfo* getATI( int n ) { return &m_ATIs[ n-1 ]; }
|
|
|
|
MTemplate* createTemplate( const TemplateInfo* pInfo, const char* pBuf, bool bID );
|
|
MTemplateArray* createTemplateArray( const TemplateInfo* pInfo, int fixedCount, const char* pBuf );
|
|
MTemplateArray* createTemplateArray( const TemplateInfo* pInfo, const char* pBuf );
|
|
MArray* createArray( int type, int fixedCount, const char* pBuf );
|
|
MArray* createArray( int type, const char* pBuf );
|
|
MDict* createDict( const char* pBuf );
|
|
|
|
void deleteTemplate( MTemplate* pTemplate );
|
|
void deleteTemplateArray( MTemplateArray* pTemplateArray );
|
|
void deleteArray( MArray* pArray );
|
|
void deleteDict( MDict* pDict );
|
|
};
|
|
|
|
|
|
class MTemplate
|
|
{
|
|
public:
|
|
|
|
// class info
|
|
|
|
const TemplateInfo* info() const { return m_pInfo; }
|
|
const GUID& classId() const { return m_pInfo->id(); }
|
|
const char* className() const { return m_pInfo->name(); }
|
|
int fixedSize() const { return m_pATI->fixedSize; }
|
|
bool isFixed() const { return fixedSize() >= 0; }
|
|
|
|
// field info
|
|
|
|
int count() const { return m_pATI->fieldLimit; }
|
|
|
|
int indexBy( const char* pName ) const { return m_pInfo->indexBy( pName ); }
|
|
const char* nameAt( int i ) const { return m_pInfo->nameAt( i ); }
|
|
|
|
int typeAt( int i ) const { return m_pInfo->typeAt( i ); }
|
|
int fixedCountAt( int i ) const { return m_pInfo->fixedCountAt( i ); }
|
|
int fixedSizeAt( int i ) const { return m_pInfo->fixedSizeAt( i ); }
|
|
|
|
// data read
|
|
|
|
int readFixedData( void* pOutBuf, int bufSize ) const;
|
|
|
|
const void* getSimpleDataAt( int i, int type ) const;
|
|
|
|
char getCharAt( int i ) const { return *reinterpret_cast< const char* >( getSimpleDataAt( i, Type::CHAR ) ); }
|
|
short getShortAt( int i ) const { return *reinterpret_cast< const short* >( getSimpleDataAt( i, Type::SHORT ) ); }
|
|
int getLongAt( int i ) const { return *reinterpret_cast< const int* >( getSimpleDataAt( i, Type::LONG ) ); }
|
|
long long getLLongAt( int i ) const { return *reinterpret_cast< const long long* >( getSimpleDataAt( i, Type::LLONG ) ); }
|
|
unsigned char getByteAt( int i ) const { return *reinterpret_cast< const unsigned char* >( getSimpleDataAt( i, Type::CHAR ) ); }
|
|
unsigned short getWordAt( int i ) const { return *reinterpret_cast< const unsigned short* >( getSimpleDataAt( i, Type::SHORT ) ); }
|
|
unsigned int getDWordAt( int i ) const { return *reinterpret_cast< const unsigned int* >( getSimpleDataAt( i, Type::LONG ) ); }
|
|
unsigned long long getQWordAt( int i ) const { return *reinterpret_cast< const unsigned long long* >( getSimpleDataAt( i, Type::LLONG ) ); }
|
|
float getFloatAt( int i ) const { return *reinterpret_cast< const float* >( getSimpleDataAt( i, Type::FLOAT ) ); }
|
|
double getDoubleAt( int i ) const { return *reinterpret_cast< const double* >( getSimpleDataAt( i, Type::DOUBLE ) ); }
|
|
const char* getStringAt( int i ) const { return getStringValue( *reinterpret_cast< const int* >( getSimpleDataAt( i, Type::STRING ) ) ); }
|
|
const wchar_t* getWStringAt( int i ) const { return getWStringValue( *reinterpret_cast< const int* >( getSimpleDataAt( i, Type::WSTRING ) ) ); }
|
|
MArrayPtr getArrayAt( int i ) const;
|
|
MTemplatePtr getTemplateAt( int i ) const;
|
|
MTemplateArrayPtr getTemplateArrayAt( int i ) const;
|
|
MDictPtr getDictAt( int i ) const;
|
|
|
|
char getCharBy( const char* pName ) const { return getCharAt( indexBy( pName ) ); }
|
|
short getShortBy( const char* pName ) const { return getShortAt( indexBy( pName ) ); }
|
|
int getLongBy( const char* pName ) const { return getLongAt( indexBy( pName ) ); }
|
|
long long getLLongBy( const char* pName ) const { return getLLongAt( indexBy( pName ) ); }
|
|
unsigned char getByteBy( const char* pName ) const { return getByteAt( indexBy( pName ) ); }
|
|
unsigned short getWordBy( const char* pName ) const { return getWordAt( indexBy( pName ) ); }
|
|
unsigned int getDWordBy( const char* pName ) const { return getDWordAt( indexBy( pName ) ); }
|
|
unsigned long long getQWordBy( const char* pName ) const { return getQWordAt( indexBy( pName ) ); }
|
|
float getFloatBy( const char* pName ) const { return getFloatAt( indexBy( pName ) ); }
|
|
double getDoubleBy( const char* pName ) const { return getDoubleAt( indexBy( pName ) ); }
|
|
const char* getStringBy( const char* pName ) const { return getStringAt( indexBy( pName ) ); }
|
|
const wchar_t* getWStringBy( const char* pName ) const { return getWStringAt( indexBy( pName ) ); }
|
|
MArrayPtr getArrayBy( const char* pName ) const { return getArrayAt( indexBy( pName ) ); }
|
|
MTemplatePtr getTemplateBy( const char* pName ) const { return getTemplateAt( indexBy( pName ) ); }
|
|
MTemplateArrayPtr getTemplateArrayBy( const char* pName ) const { return getTemplateArrayAt( indexBy( pName ) ); }
|
|
MDictPtr getDictBy( const char* pName ) const { return getDictAt( indexBy( pName ) ); }
|
|
|
|
// string data & index conversion
|
|
|
|
const char* getStringValue( int strIndex ) const { return m_pParent->getString( strIndex ); }
|
|
const wchar_t* getWStringValue( int wstrIndex ) const { return m_pParent->getWString( wstrIndex ); }
|
|
|
|
private:
|
|
|
|
friend class Mapper;
|
|
|
|
MTemplate() {}
|
|
~MTemplate() {}
|
|
|
|
void init( Mapper* pParent, const TemplateInfo* pInfo, const char* pBuf, bool bID );
|
|
void close();
|
|
|
|
Mapper* m_pParent;
|
|
const TemplateInfo* m_pInfo;
|
|
const ATInfo* m_pATI;
|
|
|
|
struct Field {
|
|
const char* ptr;
|
|
union {
|
|
MTemplate* asTemplate;
|
|
MTemplateArray* asTemplateArray;
|
|
MArray* asArray;
|
|
MDict* asDict;
|
|
};
|
|
};
|
|
|
|
c_array< Field > m_fields;
|
|
};
|
|
|
|
|
|
class MTemplateArray
|
|
{
|
|
public:
|
|
|
|
// element class info & count
|
|
|
|
int count() const { return int( m_fields.size() ); }
|
|
|
|
const TemplateInfo* info() const { return m_pInfo; }
|
|
const GUID& classId() const { return m_pInfo->id(); }
|
|
const char* className() const { return m_pInfo->name(); }
|
|
int fieldCount() const { return m_pATI->fieldLimit; }
|
|
int fixedSize() const { return m_pATI->fixedSize; }
|
|
bool isFixed() const { return fixedSize() >= 0; }
|
|
|
|
// data read interface
|
|
|
|
int readFixedData( int i, int n, void* pOutBuf, int bufSize ) const;
|
|
int readFixedData( void* pOutBuf, int bufSize ) const;
|
|
|
|
MTemplatePtr getTemplateAt( int i ) const;
|
|
const void* getFixedData( int i ) const;
|
|
|
|
protected:
|
|
|
|
friend class Mapper;
|
|
|
|
MTemplateArray()
|
|
: m_pParent( NULL )
|
|
, m_pInfo( NULL )
|
|
, m_pATI( NULL )
|
|
{}
|
|
~MTemplateArray() {}
|
|
|
|
void init( Mapper* pParent, const TemplateInfo* pInfo, int fixedCount, const char* pBuf );
|
|
void init( Mapper* pParent, const TemplateInfo* pInfo, const char* pBuf );
|
|
void close();
|
|
|
|
Mapper* m_pParent;
|
|
const TemplateInfo* m_pInfo;
|
|
const ATInfo* m_pATI;
|
|
|
|
struct Field
|
|
{
|
|
const char* ptr;
|
|
MTemplate* asTemplate;
|
|
};
|
|
|
|
c_varray< Field > m_fields;
|
|
};
|
|
|
|
|
|
class MArray
|
|
{
|
|
public:
|
|
|
|
// element info & count
|
|
|
|
int count() const { return m_count; }
|
|
|
|
int type() const { return m_type; }
|
|
int fixedSize() const { return Type::getTypeSize( m_type ); }
|
|
bool isFixed() const { return true; }
|
|
|
|
// data read interface
|
|
|
|
int readFixedData( int i, int n, void* pOutBuf, int bufSize ) const;
|
|
int readFixedData( void* pOutBuf, int bufSize ) const;
|
|
|
|
const void* getSimpleDataArray( int start, int type ) const;
|
|
|
|
char getCharAt( int i ) const { return *reinterpret_cast< const char* >( getSimpleDataArray( i, Type::CHAR ) ); }
|
|
short getShortAt( int i ) const { return *reinterpret_cast< const short* >( getSimpleDataArray( i, Type::SHORT ) ); }
|
|
int getLongAt( int i ) const { return *reinterpret_cast< const int* >( getSimpleDataArray( i, Type::LONG ) ); }
|
|
long long getLLongAt( int i ) const { return *reinterpret_cast< const long long* >( getSimpleDataArray( i, Type::LLONG ) ); }
|
|
unsigned char getByteAt( int i ) const { return *reinterpret_cast< const unsigned char* >( getSimpleDataArray( i, Type::CHAR ) ); }
|
|
unsigned short getWordAt( int i ) const { return *reinterpret_cast< const unsigned short* >( getSimpleDataArray( i, Type::SHORT ) ); }
|
|
unsigned int getDWordAt( int i ) const { return *reinterpret_cast< const unsigned int* >( getSimpleDataArray( i, Type::LONG ) ); }
|
|
unsigned long long getQWordAt( int i ) const { return *reinterpret_cast< const unsigned long long* >( getSimpleDataArray( i, Type::LLONG ) ); }
|
|
float getFloatAt( int i ) const { return *reinterpret_cast< const float* >( getSimpleDataArray( i, Type::FLOAT ) ); }
|
|
double getDoubleAt( int i ) const { return *reinterpret_cast< const double* >( getSimpleDataArray( i, Type::DOUBLE ) ); }
|
|
const char* getStringAt( int i ) const { return getStringValue( *reinterpret_cast< const int* >( getSimpleDataArray( i, Type::STRING ) ) ); }
|
|
const wchar_t* getWStringAt( int i ) const { return getWStringValue( *reinterpret_cast< const int* >( getSimpleDataArray( i, Type::WSTRING ) ) ); }
|
|
|
|
const char* getCharArray( int start = 0 ) const { return reinterpret_cast< const char* >( getSimpleDataArray( start, Type::CHAR ) ); }
|
|
const short* getShortArray( int start = 0 ) const { return reinterpret_cast< const short* >( getSimpleDataArray( start, Type::SHORT ) ); }
|
|
const int* getLongArray( int start = 0 ) const { return reinterpret_cast< const int* >( getSimpleDataArray( start, Type::LONG ) ); }
|
|
const long long* getLLongArray( int start = 0 ) const { return reinterpret_cast< const long long* >( getSimpleDataArray( start, Type::LLONG ) ); }
|
|
const unsigned char* getByteArray( int start = 0 ) const { return reinterpret_cast< const unsigned char* >( getSimpleDataArray( start, Type::CHAR ) ); }
|
|
const unsigned short* getWordArray( int start = 0 ) const { return reinterpret_cast< const unsigned short* >( getSimpleDataArray( start, Type::SHORT ) ); }
|
|
const unsigned int* getDWordArray( int start = 0 ) const { return reinterpret_cast< const unsigned int* >( getSimpleDataArray( start, Type::LONG ) ); }
|
|
const unsigned long long* getQWordArray( int start = 0 ) const { return reinterpret_cast< const unsigned long long* >( getSimpleDataArray( start, Type::LLONG ) ); }
|
|
const float* getFloatArray( int start = 0 ) const { return reinterpret_cast< const float* >( getSimpleDataArray( start, Type::FLOAT ) ); }
|
|
const double* getDoubleArray( int start = 0 ) const { return reinterpret_cast< const double* >( getSimpleDataArray( start, Type::DOUBLE ) ); }
|
|
|
|
// string data & index conversion
|
|
|
|
const char* getStringValue( int strIndex ) const { return m_pParent->getString( strIndex ); }
|
|
const wchar_t* getWStringValue( int wstrIndex ) const { return m_pParent->getWString( wstrIndex ); }
|
|
|
|
private:
|
|
|
|
friend class Mapper;
|
|
|
|
MArray() {}
|
|
~MArray() {}
|
|
|
|
void init( Mapper* pParent, int type, int fixedCount, const char* pBuf );
|
|
void init( Mapper* pParent, int type, const char* pBuf );
|
|
|
|
Mapper* m_pParent;
|
|
const char* m_pBuf;
|
|
int m_count;
|
|
int m_type;
|
|
};
|
|
|
|
|
|
class MDict
|
|
{
|
|
public:
|
|
|
|
// field / element info
|
|
|
|
int count() const { return int( m_fields.size() ); }
|
|
|
|
const char* nameAt( int i ) const;
|
|
int indexBy( const char* pName ) const;
|
|
|
|
int typeAt( int i ) const;
|
|
int fixedSizeAt( int i ) const;
|
|
|
|
// data read interface
|
|
|
|
const void* getSimpleDataAt( int i, int type ) const;
|
|
|
|
char getCharAt( int i ) const { return *reinterpret_cast< const char* >( getSimpleDataAt( i, Type::CHAR ) ); }
|
|
short getShortAt( int i ) const { return *reinterpret_cast< const short* >( getSimpleDataAt( i, Type::SHORT ) ); }
|
|
int getLongAt( int i ) const { return *reinterpret_cast< const int* >( getSimpleDataAt( i, Type::LONG ) ); }
|
|
long long getLLongAt( int i ) const { return *reinterpret_cast< const long long* >( getSimpleDataAt( i, Type::LLONG ) ); }
|
|
unsigned char getByteAt( int i ) const { return *reinterpret_cast< const unsigned char* >( getSimpleDataAt( i, Type::CHAR ) ); }
|
|
unsigned short getWordAt( int i ) const { return *reinterpret_cast< const unsigned short* >( getSimpleDataAt( i, Type::SHORT ) ); }
|
|
unsigned int getDWordAt( int i ) const { return *reinterpret_cast< const unsigned int* >( getSimpleDataAt( i, Type::LONG ) ); }
|
|
unsigned long long getQWordAt( int i ) const { return *reinterpret_cast< const unsigned long long* >( getSimpleDataAt( i, Type::LLONG ) ); }
|
|
float getFloatAt( int i ) const { return *reinterpret_cast< const float* >( getSimpleDataAt( i, Type::FLOAT ) ); }
|
|
double getDoubleAt( int i ) const { return *reinterpret_cast< const double* >( getSimpleDataAt( i, Type::DOUBLE ) ); }
|
|
const char* getStringAt( int i ) const { return getStringValue( *reinterpret_cast< const int* >( getSimpleDataAt( i, Type::STRING ) ) ); }
|
|
const wchar_t* getWStringAt( int i ) const { return getWStringValue( *reinterpret_cast< const int* >( getSimpleDataAt( i, Type::WSTRING ) ) ); }
|
|
MArrayPtr getArrayAt( int i ) const;
|
|
MTemplatePtr getTemplateAt( int i ) const;
|
|
MTemplateArrayPtr getTemplateArrayAt( int i ) const;
|
|
MDictPtr getDictAt( int i ) const;
|
|
|
|
char getCharBy( const char* pName ) const { return getCharAt( indexBy( pName ) ); }
|
|
short getShortBy( const char* pName ) const { return getShortAt( indexBy( pName ) ); }
|
|
int getLongBy( const char* pName ) const { return getLongAt( indexBy( pName ) ); }
|
|
long long getLLongBy( const char* pName ) const { return getLLongAt( indexBy( pName ) ); }
|
|
unsigned char getByteBy( const char* pName ) const { return getByteAt( indexBy( pName ) ); }
|
|
unsigned short getWordBy( const char* pName ) const { return getWordAt( indexBy( pName ) ); }
|
|
unsigned int getDWordBy( const char* pName ) const { return getDWordAt( indexBy( pName ) ); }
|
|
unsigned long long getQWordBy( const char* pName ) const { return getQWordAt( indexBy( pName ) ); }
|
|
float getFloatBy( const char* pName ) const { return getFloatAt( indexBy( pName ) ); }
|
|
double getDoubleBy( const char* pName ) const { return getDoubleAt( indexBy( pName ) ); }
|
|
const char* getStringBy( const char* pName ) const { return getStringAt( indexBy( pName ) ); }
|
|
const wchar_t* getWStringBy( const char* pName ) const { return getWStringAt( indexBy( pName ) ); }
|
|
MArrayPtr getArrayBy( const char* pName ) const { return getArrayAt( indexBy( pName ) ); }
|
|
MTemplatePtr getTemplateBy( const char* pName ) const { return getTemplateAt( indexBy( pName ) ); }
|
|
MTemplateArrayPtr getTemplateArrayBy( const char* pName ) const { return getTemplateArrayAt( indexBy( pName ) ); }
|
|
MDictPtr getDictBy( const char* pName ) const { return getDictAt( indexBy( pName ) ); }
|
|
|
|
// string data & index conversion
|
|
|
|
const char* getStringValue( int strIndex ) const { return m_pParent->getString( strIndex ); }
|
|
const wchar_t* getWStringValue( int wstrIndex ) const { return m_pParent->getWString( wstrIndex ); }
|
|
|
|
private:
|
|
|
|
friend class Mapper;
|
|
|
|
MDict() {}
|
|
~MDict() {}
|
|
|
|
void init( Mapper* pParent, const char* pBuf );
|
|
void close();
|
|
|
|
Mapper* m_pParent;
|
|
|
|
#pragma pack(push,1)
|
|
|
|
union FieldHdr {
|
|
int _typeAndName;
|
|
struct Hdr{
|
|
char _dummy[3];
|
|
unsigned char _type;
|
|
} hdr;
|
|
};
|
|
|
|
struct UnpackedFieldHdr {
|
|
int _name;
|
|
unsigned char _type;
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
|
|
struct Field {
|
|
const FieldHdr* ptr;
|
|
union {
|
|
MTemplate* asTemplate;
|
|
MTemplateArray* asTemplateArray;
|
|
MArray* asArray;
|
|
MDict* asDict;
|
|
};
|
|
};
|
|
|
|
c_varray< Field > m_fields;
|
|
|
|
const char* _getFieldData( const MDict::FieldHdr* ptr ) const;
|
|
int _getFieldName( const MDict::FieldHdr* ptr ) const;
|
|
unsigned char _getFieldType( const MDict::FieldHdr* ptr ) const;
|
|
};
|
|
|
|
|
|
|
|
|
|
// =================================================================================================
|
|
// inline method implementations
|
|
|
|
|
|
inline const char* Mapper::getString( int i )
|
|
{
|
|
assert( i >= 0 && i <= int( m_stringTable.size() ) );
|
|
return i == 0 ? NULL : m_stringTable[ i-1 ];
|
|
}
|
|
|
|
inline const wchar_t* Mapper::getWString( int i )
|
|
{
|
|
assert( i >= 0 && i <= int( m_wstringTable.size() ) );
|
|
return i == 0 ? NULL : m_wstringTable[ i-1 ];
|
|
}
|
|
|
|
inline const GUID& Mapper::getId( int i )
|
|
{
|
|
assert( i > 0 && i <= m_idCount );
|
|
return m_pId[ i-1 ];
|
|
}
|
|
|
|
inline const ATInfo* Mapper::getATI( const GUID& id )
|
|
{
|
|
const TemplateInfo* pInfo = m_pMetaData->getTemplateInfo( id );
|
|
int i = m_TInfoIndexTable[ pInfo->getMetaDataIndex() ];
|
|
return i == -1 ? NULL : &m_ATIs[ i ];
|
|
}
|
|
|
|
inline const void* MTemplate::getSimpleDataAt( int i, int type ) const
|
|
{
|
|
assert( i >= 0 && i < count() && type == typeAt( i ) );
|
|
return m_fields[ i ].ptr;
|
|
}
|
|
|
|
inline int MTemplate::readFixedData( void* pOutBuf, int bufSize ) const
|
|
{
|
|
int size = fixedSize();
|
|
if ( size < 0 )
|
|
return -1;
|
|
if ( bufSize < size )
|
|
return 0;
|
|
|
|
s_memcpy( pOutBuf, bufSize, m_fields.front().ptr, size );
|
|
return size;
|
|
}
|
|
|
|
inline MArrayPtr MTemplate::getArrayAt( int i ) const
|
|
{
|
|
assert( i >= 0 && i < count() && Type::isSimpleArrayType( typeAt( i ) ) );
|
|
|
|
Field& v = const_cast< Field& >( m_fields[ i ] );
|
|
if ( v.asArray == NULL )
|
|
{
|
|
if ( fixedSizeAt( i ) > 0 )
|
|
v.asArray = m_pParent->createArray( Type::getElementType( typeAt( i ) ), fixedCountAt( i ), m_fields[ i ].ptr );
|
|
else
|
|
v.asArray = m_pParent->createArray( Type::getElementType( typeAt( i ) ), m_fields[ i ].ptr );
|
|
}
|
|
return v.asArray;
|
|
}
|
|
|
|
inline MTemplatePtr MTemplate::getTemplateAt( int i ) const
|
|
{
|
|
assert( i >= 0 && i < count() && Type::TEMPLATE == typeAt( i ) );
|
|
|
|
Field& v = const_cast< Field& >( m_fields[ i ] );
|
|
if ( v.asTemplate == NULL )
|
|
{
|
|
v.asTemplate = m_pParent->createTemplate( info()->infoAt( i ), m_fields[ i ].ptr, false );
|
|
}
|
|
return v.asTemplate;
|
|
}
|
|
|
|
inline MTemplateArrayPtr MTemplate::getTemplateArrayAt( int i ) const
|
|
{
|
|
assert( i >= 0 && i < count() && Type::TEMPLATE_ARRAY == typeAt( i ) );
|
|
|
|
Field& v = const_cast< Field& >( m_fields[ i ] );
|
|
if ( v.asTemplateArray == NULL )
|
|
{
|
|
if ( fixedSizeAt( i ) > 0 )
|
|
v.asTemplateArray = m_pParent->createTemplateArray( info()->infoAt( i ), fixedCountAt( i ), m_fields[ i ].ptr );
|
|
else
|
|
v.asTemplateArray = m_pParent->createTemplateArray( info()->infoAt( i ), m_fields[ i ].ptr );
|
|
}
|
|
return v.asTemplateArray;
|
|
}
|
|
|
|
inline MDictPtr MTemplate::getDictAt( int i ) const
|
|
{
|
|
assert( i >= 0 && i < count() && Type::DICT == typeAt( i ) );
|
|
|
|
Field& v = const_cast< Field& >( m_fields[ i ] );
|
|
if ( v.asDict == NULL )
|
|
{
|
|
v.asDict = m_pParent->createDict( m_fields[ i ].ptr );
|
|
}
|
|
return v.asDict;
|
|
}
|
|
|
|
inline int MTemplateArray::readFixedData( int i, int n, void* pOutBuf, int bufSize ) const
|
|
{
|
|
int size = fixedSize();
|
|
if ( size < 0 || i < 0 || n < 0 || bufSize <= 0 )
|
|
return -1;
|
|
|
|
if ( bufSize > 0 && (i+n)*size > bufSize )
|
|
n = bufSize/size - i;
|
|
|
|
if ( n > 0 )
|
|
s_memcpy( pOutBuf, bufSize, m_fields.front().ptr + i * size, n * size );
|
|
return n * size;
|
|
}
|
|
|
|
inline int MTemplateArray::readFixedData( void* pOutBuf, int bufSize ) const
|
|
{
|
|
return readFixedData( 0, count(), pOutBuf, bufSize );
|
|
}
|
|
|
|
inline const void* MTemplateArray::getFixedData( int i ) const
|
|
{
|
|
int size = fixedSize();
|
|
if ( size < 0 || i < 0 || i >= count() )
|
|
return NULL;
|
|
|
|
return m_fields.front().ptr + i * size;
|
|
}
|
|
|
|
inline MTemplatePtr MTemplateArray::getTemplateAt( int i ) const
|
|
{
|
|
assert( i >= 0 && i < int( m_fields.size() ) );
|
|
Field& f = const_cast< Field& >( m_fields[ i ] );
|
|
|
|
if ( f.asTemplate == NULL ) {
|
|
f.asTemplate = m_pParent->createTemplate( m_pInfo, f.ptr, false );
|
|
}
|
|
return f.asTemplate;
|
|
}
|
|
|
|
inline int MArray::readFixedData( int i, int n, void* pOutBuf, int bufSize ) const
|
|
{
|
|
if ( i < 0 || n < 0 || i >= count() || pOutBuf == NULL || bufSize <= 0 )
|
|
return 0;
|
|
|
|
if ( i+n > count() )
|
|
n = count()-i;
|
|
|
|
int elemSize = fixedSize();
|
|
|
|
if ( bufSize > 0 && bufSize < n * elemSize )
|
|
n = bufSize / elemSize;
|
|
|
|
if ( n > 0 )
|
|
s_memcpy( pOutBuf, bufSize, m_pBuf + i * elemSize, n * elemSize );
|
|
return n * elemSize;
|
|
}
|
|
|
|
inline int MArray::readFixedData( void* pOutBuf, int bufSize ) const
|
|
{
|
|
return readFixedData( 0, count(), pOutBuf, bufSize );
|
|
}
|
|
|
|
inline const void* MArray::getSimpleDataArray( int start, int type ) const
|
|
{
|
|
assert( type == m_type );
|
|
return m_pBuf + start * Type::getTypeSize( type );
|
|
}
|
|
|
|
inline const char* MDict::_getFieldData( const MDict::FieldHdr* ptr ) const
|
|
{
|
|
return reinterpret_cast< const char* >( ptr ) + (m_pParent->m_bUnpackedDict ? sizeof(UnpackedFieldHdr) : sizeof(FieldHdr) );
|
|
}
|
|
|
|
inline int MDict::_getFieldName( const MDict::FieldHdr* ptr ) const
|
|
{
|
|
return m_pParent->m_bUnpackedDict ? reinterpret_cast< const UnpackedFieldHdr* >( ptr )->_name : ptr->_typeAndName & 0xffffff;
|
|
}
|
|
|
|
inline unsigned char MDict::_getFieldType( const MDict::FieldHdr* ptr ) const
|
|
{
|
|
return m_pParent->m_bUnpackedDict ? reinterpret_cast< const UnpackedFieldHdr* >( ptr )->_type : ptr->hdr._type;
|
|
}
|
|
|
|
inline const char* MDict::nameAt( int i ) const
|
|
{
|
|
return m_pParent->getString( _getFieldName( m_fields[ i ].ptr ) );
|
|
}
|
|
|
|
inline int MDict::typeAt( int i ) const
|
|
{
|
|
return _getFieldType( m_fields[ i ].ptr );
|
|
}
|
|
|
|
inline int MDict::indexBy( const char* pName ) const
|
|
{
|
|
if ( pName == NULL )
|
|
return -1;
|
|
|
|
for ( int i = 0, n = int( m_fields.size() ); i < n; i++ )
|
|
{
|
|
const char* pFieldName = m_pParent->getString( _getFieldName( m_fields[ i ].ptr ) );
|
|
if ( !strcmp( pFieldName, pName ) )
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline int MDict::fixedSizeAt( int i ) const
|
|
{
|
|
int type = typeAt( i );
|
|
|
|
if ( Type::isSimpleType( type ) )
|
|
return Type::getTypeSize( type );
|
|
else if ( type == Type::TEMPLATE )
|
|
return getTemplateAt( i )->fixedSize();
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
inline const void* MDict::getSimpleDataAt( int i, int type ) const
|
|
{
|
|
assert( i >= 0 && i < int( m_fields.size() ) && type == _getFieldType( m_fields[ i ].ptr ) );
|
|
return _getFieldData( m_fields[ i ].ptr );
|
|
}
|
|
|
|
inline MArrayPtr MDict::getArrayAt( int i ) const
|
|
{
|
|
int type = typeAt( i );
|
|
assert( Type::isSimpleArrayType( type ) );
|
|
|
|
MArray*& pArray = const_cast< MArray*& >( m_fields[ i ].asArray );
|
|
if ( pArray == NULL ) {
|
|
pArray = m_pParent->createArray( type, _getFieldData( m_fields[ i ].ptr ) );
|
|
}
|
|
return pArray;
|
|
}
|
|
|
|
inline MTemplatePtr MDict::getTemplateAt( int i ) const
|
|
{
|
|
assert( typeAt( i ) == Type::TEMPLATE );
|
|
|
|
MTemplate*& pTpl = const_cast< MTemplate*& >( m_fields[ i ].asTemplate );
|
|
if ( pTpl == NULL ) {
|
|
pTpl = m_pParent->createTemplate( NULL, _getFieldData( m_fields[ i ].ptr ), true );
|
|
}
|
|
return pTpl;
|
|
}
|
|
|
|
inline MTemplateArrayPtr MDict::getTemplateArrayAt( int i ) const
|
|
{
|
|
assert( typeAt( i ) == Type::TEMPLATE_ARRAY );
|
|
|
|
MTemplateArray*& pTplArray = const_cast< MTemplateArray*& >( m_fields[ i ].asTemplateArray );
|
|
if ( pTplArray == NULL ) {
|
|
pTplArray = m_pParent->createTemplateArray( NULL, _getFieldData( m_fields[ i ].ptr ) );
|
|
}
|
|
return pTplArray;
|
|
}
|
|
|
|
inline MDictPtr MDict::getDictAt( int i ) const
|
|
{
|
|
assert( typeAt( i ) == Type::DICT );
|
|
|
|
MDict*& pDict = const_cast< MDict*& >( m_fields[ i ].asDict );
|
|
if ( pDict == NULL ) {
|
|
pDict = m_pParent->createDict( _getFieldData( m_fields[ i ].ptr ) );
|
|
}
|
|
return pDict;
|
|
}
|
|
|
|
} // namespace trf
|