#include "../../include/kfile/KDataObject.h" #include "../../include/kfile/KFiler.h" #include "../../include/toolkit/safe_function.h" #include #include namespace { char whitespacechr[] = { '\n', '\r', '{', ' ', '\t', '}' , ',' }; char whitespacechr2[] = { '\n', '\r', ' ', '\t', ',' }; // 공백문자들을 건너뛰고 나서 처음 나오는 문자가 '{' 임을 확인 bool isNextOBrace( KStream &stream ) { char chr; bool isWhiteSpace; do { isWhiteSpace = false; if ( stream.Read( &chr, 1 ) ) { for (int i = 0; i < _countof(whitespacechr); i++ ) { if ( chr == whitespacechr[i] ) { if ( chr == '{' ) { return true; } else if (chr == '}') { return false; } else { isWhiteSpace = true; } } } if (!isWhiteSpace) return false; } else { return false; } } while (isWhiteSpace); return false; } // 공백문자들을 건너뛰고 나서 처음 나오는 문자가 '}' 임을 확인 bool isNextCBrace( KStream &stream ) { char chr; bool isWhiteSpace; do { isWhiteSpace = false; if ( stream.Read( &chr, 1 ) ) { for (int i = 0; i < _countof(whitespacechr); i++ ) { if ( chr == whitespacechr[i] ) { if ( chr == '}' ) { return true; } else if (chr == '{') { return false; } else { isWhiteSpace = true; } } } if (!isWhiteSpace) return false; } else { return false; } } while (isWhiteSpace); return false; } // 공백문자들 다음에 나오는 문자열 token을 얻는다. bool getNextToken( KStream &stream, std::string &token ) { char chr; bool isWhiteSpace; token.erase(); // whitespacechr에 정의된 공백부분을 읽고 지나치다가 공백이 아닌 문자가 나오면 정지 do { isWhiteSpace = false; if ( stream.Read( &chr, 1 ) ) { for ( int i=0 ; i<_countof(whitespacechr2) ; i++ ) { if ( chr == whitespacechr2[i] ) { isWhiteSpace = true; break; } } } else return false; } while ( isWhiteSpace == true ); if( chr == '{' || chr == '}' ) return false; // 다음 공백이 나올때까지 문자를 읽어서 token에 저장 stream.Seek( -1, KStream::seekCur ); while (1) { if ( stream.Read ( &chr, 1 ) ) { for ( int i=0 ; i<_countof(whitespacechr) ; i++ ) { if ( chr == whitespacechr[i] ) { isWhiteSpace = true; break; } } } else return false; if ( !isWhiteSpace ) token += chr; else break; } stream.Seek( -1, KStream::seekCur ); return true; } // 공백문자들 다음에 나오는 따옴표로 둘러싸인 문자열을 얻는다. bool getNextString( KStream &stream, std::string &token ) { char chr; bool isQuote = false; token.erase(); // 쌍따옴표 (")가 나올때까지 읽고 지나감 do { if ( stream.Read( &chr, 1 ) ) { if ( chr == 34 ) isQuote = true; } else return false; } while ( !isQuote ); // 다음 쌍따옴표가 나올때까지 문자를 읽어서 token에 저장 isQuote = false; do { if ( stream.Read ( &chr, 1 ) ) { if ( chr == 34 ) isQuote = true; } else return false; if ( !isQuote ) token += chr; } while ( !isQuote ) ; return true; } } void KDataObject::AddDataObject( KDataObject *obj ) { m_pDataObjects.push_back( obj ); } // SimpleDataObject KSimpleDataObject::KSimpleDataObject( CLASSTYPEID idclass) : KDataObject( idclass ) { switch( idclass ) { case CLASSTYPEID_WORD: m_nSize = 2; break; case CLASSTYPEID_DWORD: case CLASSTYPEID_FLOAT: m_nSize = 4; break; case CLASSTYPEID_CHAR: case CLASSTYPEID_UCHAR: m_nSize = 1; break; case CLASSTYPEID_STRING: m_nSize = 0; break; default: m_nSize = 0; } m_pStr = NULL; m_data._4byteint = 0; } KSimpleDataObject::~KSimpleDataObject() { if ( m_pStr ) delete[] m_pStr; } bool KSimpleDataObject::SetDWORD( DWORD data ) { if ( m_idClassType == CLASSTYPEID_DWORD ) { m_data._4byteint = data; m_nSize = 4; return true; } return false; } bool KSimpleDataObject::SetWORD( WORD data ) { if ( m_idClassType == CLASSTYPEID_WORD ) { m_data._2byteint = data; m_nSize = 2; return true; } return false; } bool KSimpleDataObject::SetFloat( float data ) { if ( m_idClassType == CLASSTYPEID_FLOAT ) { m_data._4bytefloat = data; m_nSize = 4; return true; } return false; } bool KSimpleDataObject::SetUChar( unsigned char data ) { if ( m_idClassType == CLASSTYPEID_UCHAR ) { m_data._1byteuchar = data; m_nSize = 1; return true; } return false; } bool KSimpleDataObject::SetChar( char data ) { if ( m_idClassType == CLASSTYPEID_CHAR ) { m_data._1bytechar = data; m_nSize = 1; return true; } return false; } bool KSimpleDataObject::SetString( const char *data, int nLen ) { if ( m_idClassType == CLASSTYPEID_STRING ) { if ( m_pStr ) delete[] m_pStr; m_pStr = new char[nLen+1]; m_pStr[nLen] = '\0'; s_memcpy( m_pStr, nLen, data, nLen ); m_nSize = nLen+1; return true; } return false; } bool KSimpleDataObject::SetData(const void *data, int nSize) { if ( m_idClassType == CLASSTYPEID_STRING ) { if ( m_pStr ) delete[] m_pStr; m_pStr = new char[nSize+1]; m_pStr[nSize] = '\0'; s_memcpy( m_pStr, nSize, data, nSize ); m_nSize = nSize+1; return true; } else if ( nSize == m_nSize ) { switch( m_idClassType ) { case CLASSTYPEID_WORD: s_memcpy( &m_data._2byteint, sizeof( m_data._2byteint ), data, m_nSize ); break; case CLASSTYPEID_DWORD: case CLASSTYPEID_FLOAT: s_memcpy( &m_data._4byteint, sizeof( m_data._4byteint ), data, m_nSize ); break; case CLASSTYPEID_CHAR: case CLASSTYPEID_UCHAR: s_memcpy( &m_data._1byteuchar, sizeof( m_data._1byteuchar ), data, m_nSize ); break; default: return false; } return true; } return false; } bool KSimpleDataObject::Save( KStream &stream, FileMode filemode ) { if ( SaveHeader( stream, filemode ) ) { return SaveBody( stream, filemode ); } return false; } bool KSimpleDataObject::Load( KStream &stream, FileMode filemode ) { if( LoadHeader( stream, filemode ) ) { return LoadBody( stream, filemode ); } return false; } bool KSimpleDataObject::SaveHeader( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { switch( m_idClassType ) { case CLASSTYPEID_WORD: stream.Write( &KTOKEN_WORD, 1 ); break; case CLASSTYPEID_DWORD: stream.Write( &KTOKEN_DWORD, 1 ); break; case CLASSTYPEID_FLOAT: stream.Write( &KTOKEN_FLOAT, 1 ); break; case CLASSTYPEID_CHAR: stream.Write( &KTOKEN_CHAR, 1 ); break; case CLASSTYPEID_UCHAR: stream.Write( &KTOKEN_UCHAR, 1 ); break; case CLASSTYPEID_STRING: stream.Write( &KTOKEN_STRING, 1 ); break; default: return false; } return true; } else if ( filemode == KDFM_ASCII ) { return true; } return false; } bool KSimpleDataObject::LoadHeader( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { char typetoken; stream.Read( &typetoken, 1 ); switch( typetoken ) { case KTOKEN_WORD: m_idClassType = CLASSTYPEID_WORD; m_nSize = 2; break; case KTOKEN_DWORD: m_idClassType = CLASSTYPEID_DWORD; m_nSize = 4; break; case KTOKEN_FLOAT: m_idClassType = CLASSTYPEID_FLOAT; m_nSize = 4; break; case KTOKEN_CHAR: m_idClassType = CLASSTYPEID_CHAR; m_nSize = 1; break; case KTOKEN_UCHAR: m_idClassType = CLASSTYPEID_UCHAR; m_nSize = 1; break; case KTOKEN_STRING: m_idClassType = CLASSTYPEID_STRING; break; default: return false; } return true; } else if ( filemode == KDFM_ASCII ) { return true; } return false; } bool KSimpleDataObject::SaveBody( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { int writesize; switch( m_idClassType ) { case CLASSTYPEID_WORD: writesize = static_cast(stream.Write( &m_data._2byteint, m_nSize )); break; case CLASSTYPEID_DWORD: writesize = static_cast(stream.Write( &m_data._4byteint, m_nSize )); break; case CLASSTYPEID_FLOAT: writesize = static_cast(stream.Write( &m_data._4bytefloat, m_nSize )); break; case CLASSTYPEID_CHAR: writesize = static_cast(stream.Write( &m_data._1bytechar, m_nSize )); break; case CLASSTYPEID_UCHAR: writesize = static_cast(stream.Write( &m_data._1byteuchar, m_nSize )); break; case CLASSTYPEID_STRING: stream.Write( &m_nSize, sizeof(m_nSize) ); writesize = static_cast(stream.Write( m_pStr, m_nSize )); break; default: return false; } return ( writesize == m_nSize ); } else if ( filemode == KDFM_ASCII ) { char buff[512]; switch( m_idClassType ) { case CLASSTYPEID_WORD: s_sprintf(buff, _countof( buff ), "%d", int( m_data._2byteint )); stream.Write( buff, strlen(buff)); break; case CLASSTYPEID_DWORD: s_sprintf(buff, _countof( buff ), "%d", m_data._4byteint); stream.Write( buff, strlen(buff)); break; case CLASSTYPEID_FLOAT: s_sprintf(buff, _countof( buff ), "%f", m_data._4bytefloat); stream.Write( buff, strlen(buff)); break; case CLASSTYPEID_CHAR: s_sprintf(buff, _countof( buff ), "%d", int( m_data._1bytechar ) ); stream.Write( buff, strlen(buff)); break; case CLASSTYPEID_UCHAR: s_sprintf(buff, _countof( buff ), "%d", int( m_data._1byteuchar ) ); stream.Write( buff, strlen(buff)); break; case CLASSTYPEID_STRING: s_sprintf(buff, _countof( buff ), "\"%s\"", m_pStr); stream.Write(buff,strlen(buff)); break; default: return false; } return true; } return false; } bool KSimpleDataObject::LoadBody( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { int readsize; switch( m_idClassType ) { case CLASSTYPEID_WORD: readsize = static_cast(stream.Read( &m_data._2byteint, m_nSize )); break; case CLASSTYPEID_DWORD: readsize = static_cast(stream.Read( &m_data._4byteint, m_nSize )); break; case CLASSTYPEID_FLOAT: readsize = static_cast(stream.Read( &m_data._4bytefloat, m_nSize )); break; case CLASSTYPEID_CHAR: readsize = static_cast(stream.Read( &m_data._1bytechar, m_nSize )); break; case CLASSTYPEID_UCHAR: readsize = static_cast(stream.Read( &m_data._1byteuchar, m_nSize )); break; case CLASSTYPEID_STRING: stream.Read( &m_nSize, sizeof(m_nSize) ); if ( m_pStr ) delete[] m_pStr; m_pStr = new char[m_nSize+1]; m_pStr[m_nSize] = '\0'; readsize = static_cast(stream.Read( m_pStr, m_nSize )); break; default: return false; } return ( readsize == m_nSize ); } else if ( filemode == KDFM_ASCII ) { std::string token; if ( m_idClassType == CLASSTYPEID_STRING ) { if ( !getNextString( stream, token ) ) return false; } else { if (! getNextToken( stream, token ) ) return false; } switch( m_idClassType ) { case CLASSTYPEID_WORD: SetWORD((unsigned short)atoi(token.c_str() )); break; case CLASSTYPEID_DWORD: SetDWORD((unsigned long)atoi( token.c_str() )); break; case CLASSTYPEID_FLOAT: SetFloat((float)atof( token.c_str() )); break; case CLASSTYPEID_CHAR: { int value = atoi( token.c_str() ); SetChar( char( value ) ); } break; case CLASSTYPEID_UCHAR: { int value = atoi( token.c_str() ); SetUChar( unsigned char( value ) ); } break; case CLASSTYPEID_STRING: SetString( token.c_str(), static_cast(token.size()) ); break; default: return false; } return true; } return false; } bool KSimpleDataObject::LoadFast(KStream& stream) { assert(m_idClassType != CLASSTYPEID_NONE); stream.Seek(1,KStream::seekCur); return LoadBody(stream); } int KSimpleDataObject::GetIndexValue() { switch( m_idClassType ) { case CLASSTYPEID_WORD: return static_cast(m_data._2byteint); case CLASSTYPEID_DWORD: return static_cast(m_data._4byteint); case CLASSTYPEID_FLOAT: return static_cast(m_data._4bytefloat); case CLASSTYPEID_CHAR: return static_cast(m_data._1bytechar); case CLASSTYPEID_UCHAR: return static_cast(m_data._1byteuchar); } return -1; } KDataObject* KSimpleDataObject::CloneTypeInfo(KTemplateDataObject* pParent) { KSimpleDataObject* pObject = new KSimpleDataObject(m_idClassType); pObject->m_nSize = m_nSize; return pObject; } bool KSimpleDataArrayObject::SetDataString( int index, const char *str ) { if ( m_idClassType == CLASSTYPEID_ARRAY_STRING ) { m_vecStringArray[index] = str; return true; } return false; } bool KSimpleDataArrayObject::SetDataChar( int index, const char *data, int nCount ) { if ( m_idClassType == CLASSTYPEID_ARRAY_CHAR ) { if ( m_pArrayData ) { m_nDataSize = 1; size_t byte_offset = m_nDataSize*index; size_t data_size = GetDataCount() * m_nDataSize; s_memcpy( m_pArrayData + byte_offset, data_size - byte_offset, data, m_nDataSize*nCount ); return true; } } return false; } bool KSimpleDataArrayObject::SetDataUChar( int index, const unsigned char *data, int nCount ) { if ( m_idClassType == CLASSTYPEID_ARRAY_UCHAR ) { if ( m_pArrayData ) { m_nDataSize = 1; size_t byte_offset = m_nDataSize*index; size_t data_size = GetDataCount() * m_nDataSize; s_memcpy( m_pArrayData + byte_offset, data_size - byte_offset, data, m_nDataSize*nCount ); return true; } } return false; } bool KSimpleDataArrayObject::SetDataDWORD( int index, const DWORD *data, int nCount ) { if ( m_idClassType == CLASSTYPEID_ARRAY_DWORD ) { if ( m_pArrayData ) { m_nDataSize = 4; size_t byte_offset = m_nDataSize*index; size_t data_size = GetDataCount() * m_nDataSize; s_memcpy( m_pArrayData + byte_offset, data_size - byte_offset, data, m_nDataSize*nCount ); return true; } } return false; } bool KSimpleDataArrayObject::SetDataWORD( int index, const WORD *data, int nCount ) { if ( m_idClassType == CLASSTYPEID_ARRAY_WORD ) { if ( m_pArrayData ) { m_nDataSize = 2; size_t byte_offset = m_nDataSize*index; size_t data_size = GetDataCount() * m_nDataSize; s_memcpy( m_pArrayData + byte_offset, data_size - byte_offset, data, m_nDataSize*nCount ); return true; } } return false; } bool KSimpleDataArrayObject::SetDataFloat( int index, const float *data, int nCount ) { if ( m_idClassType == CLASSTYPEID_ARRAY_FLOAT ) { if ( m_pArrayData ) { m_nDataSize = 4; size_t byte_offset = m_nDataSize*index; size_t data_size = GetDataCount() * m_nDataSize; s_memcpy( m_pArrayData + byte_offset, data_size - byte_offset, data, m_nDataSize*nCount ); return true; } } return false; } void KSimpleDataArrayObject::SetArrayInfo( int nCount, const char *varCount, KTemplateDataObject *pParent ) { m_nDataCount = nCount; m_pParent = pParent; if ( m_nDataCount == -1 ) { m_strVarCount = varCount; m_varCount = m_pParent->GetMemberObject( varCount ); } RefreshArray(); } void KSimpleDataArrayObject::RefreshArray() { if ( m_idClassType == CLASSTYPEID_STRING || m_idClassType == CLASSTYPEID_ARRAY_STRING ) { m_vecStringArray.resize(GetDataCount()); if ( m_pArrayData ) delete[] m_pArrayData; m_pArrayData = NULL; } else { m_vecStringArray.clear(); switch( m_idClassType ) { case CLASSTYPEID_UCHAR: case CLASSTYPEID_ARRAY_UCHAR: m_nDataSize = 1; m_idClassType = CLASSTYPEID_ARRAY_UCHAR; break; case CLASSTYPEID_CHAR: case CLASSTYPEID_ARRAY_CHAR: m_nDataSize = 1; m_idClassType = CLASSTYPEID_ARRAY_CHAR; break; case CLASSTYPEID_WORD: case CLASSTYPEID_ARRAY_WORD: m_nDataSize = 2; m_idClassType = CLASSTYPEID_ARRAY_WORD; break; case CLASSTYPEID_DWORD: case CLASSTYPEID_ARRAY_DWORD: m_idClassType = CLASSTYPEID_ARRAY_DWORD; m_nDataSize = 4; break; case CLASSTYPEID_FLOAT: case CLASSTYPEID_ARRAY_FLOAT: m_idClassType = CLASSTYPEID_ARRAY_FLOAT; m_nDataSize = 4; break; default: return; } if ( m_pArrayData ) delete[] m_pArrayData; m_pArrayData = new char[GetDataCount() * m_nDataSize]; } } bool KSimpleDataArrayObject::Save( KStream &stream, FileMode filemode ) { if ( SaveHeader( stream, filemode ) ) { return SaveBody( stream, filemode ); } return false; } bool KSimpleDataArrayObject::Load( KStream &stream, FileMode filemode ) { if ( LoadHeader( stream, filemode ) ) { return LoadBody( stream, filemode ); } return false; } bool KSimpleDataArrayObject::SaveHeader( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { stream.Write( &KTOKEN_ARRAY, 1 ); switch( m_idClassType ) { case CLASSTYPEID_ARRAY_STRING: stream.Write( &KTOKEN_STRING, 1 ); break; case CLASSTYPEID_ARRAY_UCHAR: stream.Write( &KTOKEN_UCHAR, 1 ); break; case CLASSTYPEID_ARRAY_CHAR: stream.Write( &KTOKEN_CHAR, 1 ); break; case CLASSTYPEID_ARRAY_WORD: stream.Write( &KTOKEN_WORD, 1 ); break; case CLASSTYPEID_ARRAY_DWORD: stream.Write( &KTOKEN_DWORD, 1 ); break; case CLASSTYPEID_ARRAY_FLOAT: stream.Write( &KTOKEN_FLOAT, 1 ); break; default: return false; } int nCount = GetDataCount(); stream.Write( &nCount, 4 ); if ( m_nDataCount == -1 ) { int strCount = static_cast(m_strVarCount.size()) + 1; stream.Write( &strCount, 4 ); stream.Write( m_strVarCount.c_str(), strCount ); } else { int strCount = 0; stream.Write( &strCount, 4 ); } return true; } if ( filemode == KDFM_ASCII ) { return true; } return false; } bool KSimpleDataArrayObject::LoadHeader( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { char token; stream.Read( &token, 1 ); if ( token == KTOKEN_ARRAY ) { stream.Read( &token, 1 ); switch( token ) { case KTOKEN_UCHAR: m_idClassType = CLASSTYPEID_ARRAY_UCHAR; m_nDataSize = 1; break; case KTOKEN_CHAR: m_idClassType = CLASSTYPEID_ARRAY_CHAR; m_nDataSize = 1; break; case KTOKEN_WORD: m_idClassType = CLASSTYPEID_ARRAY_WORD; m_nDataSize = 2; break; case KTOKEN_DWORD: m_idClassType = CLASSTYPEID_ARRAY_DWORD; m_nDataSize = 4; break; case KTOKEN_FLOAT: m_idClassType = CLASSTYPEID_ARRAY_FLOAT; m_nDataSize = 4; break; case KTOKEN_STRING: m_idClassType = CLASSTYPEID_ARRAY_STRING; m_nDataSize = 0; break; default: return false; } stream.Read( &m_nDataCount, 4 ); // 이만큼 읽을 필요 없음. stream.Read( &m_strLength, 4 ); stream.Seek(m_strLength, KStream::seekCur); RefreshArray(); return true; } } else if ( filemode == KDFM_ASCII ) { RefreshArray(); return true; } return false; } bool KSimpleDataArrayObject::SaveBody( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { int nCount = GetDataCount(); if ( m_idClassType == CLASSTYPEID_ARRAY_STRING ) { for ( int i=0 ; i(m_vecStringArray[i].size()) + 1; stream.Write( &len, 4 ); stream.Write( str, len ); } return true; } return stream.Write( m_pArrayData, m_nDataSize*nCount ) == (size_t)m_nDataSize*nCount; } if ( filemode == KDFM_ASCII ) { char buff[512]; int nCount = GetDataCount(); if ( m_idClassType == CLASSTYPEID_ARRAY_STRING ) { s_sprintf(buff, _countof( buff ), "{ "); stream.Write(buff,strlen("{ ")); for ( int i=0 ; i tempstr; for ( int i=0 ; im_nDataSize = m_nDataSize; pObject->m_strLength = m_strLength; return pObject; } KTemplateDataArrayObject::~KTemplateDataArrayObject() { Clear(); } void KTemplateDataArrayObject::Clear() { std::vector::iterator it = m_vectorData.begin(); for ( ; it != m_vectorData.end() ; ++it ) { delete (*it); } m_vectorData.clear(); } void KTemplateDataArrayObject::SetArrayInfo( int nCount, const char *varCount, KTemplateDataObject *pParent ) { m_nDataCount = nCount; m_varCount = NULL; if ( m_nDataCount == -1 ) { m_strVarCount = varCount; m_pParent = pParent; m_varCount = m_pParent->GetMemberObject( m_strVarCount.c_str() ); } RefreshArray(); } void KTemplateDataArrayObject::RefreshArray() { Clear(); KTemplateDataObject *temp; m_vectorData.resize( GetDataCount() ); for ( int i=0 ; iLoad( streamData, filemode ); } } void KTemplateDataArrayObject::ChangeGUID(const GUID& uuid) { m_uuidTemplateType = uuid; } bool KTemplateDataArrayObject::Save( KStream &stream, FileMode filemode ) { return SaveHeader( stream, filemode ); } bool KTemplateDataArrayObject::Load( KStream &stream, FileMode filemode ) { return LoadHeader( stream, filemode ); } bool KTemplateDataArrayObject::SaveHeader( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { stream.Write( &KTOKEN_ARRAY, 1 ); stream.Write( &KTOKEN_TEMPLATE, 1 ); stream.Write( &m_uuidTemplateType, sizeof(m_uuidTemplateType) ); int count = GetDataCount(); stream.Write( &count, 4 ); if ( m_nDataCount == -1 ) { int strCount = static_cast(m_strVarCount.size()) + 1; stream.Write( &strCount, 4 ); stream.Write( m_strVarCount.c_str(), strCount ); } else { int strCount = 0; stream.Write( &strCount, 4 ); } for ( int i=0 ; iSave( stream, filemode ) == false ) return false; } return true; } else if ( filemode == KDFM_ASCII ) { char buff[512]; s_sprintf(buff, _countof( buff ), "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",m_uuidTemplateType.Data1,m_uuidTemplateType.Data2,m_uuidTemplateType.Data3,m_uuidTemplateType.Data4[0],m_uuidTemplateType.Data4[1],m_uuidTemplateType.Data4[2],m_uuidTemplateType.Data4[3],m_uuidTemplateType.Data4[4],m_uuidTemplateType.Data4[5],m_uuidTemplateType.Data4[6],m_uuidTemplateType.Data4[7]); stream.Write( buff , strlen(buff) ); int count = GetDataCount(); PrintTab(stream,filemode); s_sprintf(buff, _countof( buff ), "{\n",GetTab()); stream.Write(buff,strlen(buff)); SetTab(GetTab()+1); for ( int i=0 ; iSetTab(GetTab()); if ( temp->Save( stream, filemode ) == false ) return false; if ( i!=count-1 ) stream.Write(",\n",strlen(",\n")); } SetTab(GetTab()-1); stream.Write("\n",strlen("\n")); PrintTab(stream,filemode); stream.Write("}",strlen("}")); return true; } return false; } bool KTemplateDataArrayObject::LoadHeader( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { char token; Clear(); stream.Read( &token, 1 ); if ( token == KTOKEN_ARRAY ) { stream.Read( &token, 1 ); if ( token == KTOKEN_TEMPLATE ) { stream.Read( &m_uuidTemplateType, sizeof(m_uuidTemplateType) ); stream.Read( &m_nDataCount, 4 ); stream.Read( &m_strLength, 4 ); stream.Seek(m_strLength, KStream::seekCur); return LoadBody(stream); } } } else if ( filemode == KDFM_ASCII ) { char cTemp[256]; std::string token; int count; if( !isNextOBrace( stream ) ) return false; // Read Template UID if ( !getNextToken( stream, token ) ) return false; // Template 이름으로 알아낸 UID와 파일에서 직접 읽은 UID가 같은지 확인 s_sprintf(cTemp, _countof( cTemp ), "%08X-%04hX-%04hX-%04X-%04X%04X%04X", m_uuidTemplateType.Data1, m_uuidTemplateType.Data2, m_uuidTemplateType.Data3, m_uuidTemplateType.Data4[0]*256 + m_uuidTemplateType.Data4[1], m_uuidTemplateType.Data4[2]*256 + m_uuidTemplateType.Data4[3], m_uuidTemplateType.Data4[4]*256 + m_uuidTemplateType.Data4[5], m_uuidTemplateType.Data4[6]*256 + m_uuidTemplateType.Data4[7]); if ( strcmp(token.c_str(), cTemp) != 0 ) return false; if( !isNextCBrace( stream ) ) return false; Clear(); count = GetDataCount(); if( !isNextOBrace( stream ) ) return false; for ( int i=0 ; iLoad( stream, filemode ) == false) return false; m_vectorData.push_back( tempobj ); } if( !isNextCBrace( stream ) ) return false; return true; } return false; } bool KTemplateDataArrayObject::LoadBody( KStream &stream, FileMode filemode ) { //for ( int i=0 ; iLoad( stream, filemode ); // m_vectorData.push_back( tempobj ); //} //return true; // 조금이나마 속도 향상을 위해서 if(m_nDataCount > 0) { m_vectorData.resize( m_nDataCount ); m_vectorData[0] = new KTemplateDataObject(stream, filemode); for ( int i = 1 ; i < m_nDataCount ; ++i ) { m_vectorData[i] = static_cast( m_vectorData[0]->CloneTypeInfo(NULL) ); m_vectorData[i]->LoadFast(stream); } } return true; } bool KTemplateDataArrayObject::LoadFast(KStream& stream) { // TYPE + TYPE + GUID const long OFFSET = 2 + sizeof(GUID); stream.Seek(OFFSET,KStream::seekCur); stream.Read( &m_nDataCount, 4 ); // strCount + strVar 길이 만큼 스킵 stream.Seek(4 + m_strLength, KStream::seekCur); return LoadBody(stream); } KDataObject* KTemplateDataArrayObject::CloneTypeInfo(KTemplateDataObject* pParent) { KTemplateDataArrayObject *pObject = new KTemplateDataArrayObject(pParent); pObject->m_uuidTemplateType = m_uuidTemplateType; pObject->m_strLength = m_strLength; return pObject; } KTemplateDataObject::~KTemplateDataObject() { clearMembers(); } void KTemplateDataObject::clearMembers() { std::vector::iterator it = m_vectorMemberObjects.begin(); for ( ; it != m_vectorMemberObjects.end() ; ++it ) { delete *it; } m_vectorMemberObjects.clear(); //m_hashByName.clear(); } void KTemplateDataObject::ChangeTemplateInfo(KTemplateInfo* pNewInfo) { m_memberInfo = pNewInfo; m_uuidTemplate = m_memberInfo->GetTemplateGUID(); } int KTemplateDataObject::GetExtraMemberCount() { return static_cast(m_vectorMemberObjects.size()) - m_memberInfo->GetMemberCount(); } KTemplateDataObject* KTemplateDataObject::GetExtraMember( int index ) { return reinterpret_cast(m_vectorMemberObjects[m_memberInfo->GetMemberCount() + index]); } const char *KTemplateDataObject::GetExtraMemberName( int index ) { KTemplateDataObject *obj = reinterpret_cast(m_vectorMemberObjects[m_memberInfo->GetMemberCount() + index]); return obj->GetTemplateName(); } // enumeration KSimpleDataObject* GetSimpleDataMemberObject( const char *name ); KSimpleDataArrayObject* GetSimpleDataArrayMemberObject( const char *name ); KTemplateDataObject* GetTemplateDataMemberObject( const char *name ); KTemplateDataArrayObject* GetTemplateDataArrayMemberObject( const char *name ); void KTemplateDataObject::ExtendMemberVector(const char* name, size_t count) { size_t curSize = GetMemberCount(); size_t newSize = curSize + count; std::vector newVector(newSize); newVector.resize(newSize); size_t index = m_memberInfo->GetMemberIndex(name); for(size_t i = 0; i < index; ++i) { newVector.at( i ) = m_vectorMemberObjects.at(i); } for(size_t i = index + count; i < newSize; ++i) { newVector.at(i) = m_vectorMemberObjects.at( i - count ); } m_vectorMemberObjects = newVector; } void KTemplateDataObject::SetMemberObject(size_t index, KDataObject* pMemberObject) { m_vectorMemberObjects.at(index) = pMemberObject; } void KTemplateDataObject::AddMemberObject(KDataObject* pNewObj) { m_vectorMemberObjects.push_back(pNewObj); } bool KTemplateDataObject::Save( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { stream.Write( &KTOKEN_TEMPLATE, 1 ); stream.Write( &m_uuidTemplate, sizeof(m_uuidTemplate) ); int nMembers = static_cast(m_vectorMemberObjects.size()); stream.Write( &nMembers, sizeof(nMembers) ); std::vector::iterator it = m_vectorMemberObjects.begin(); for( ; it != m_vectorMemberObjects.end() ; ++it ) { if ( (*it)->Save( stream, filemode ) == false ) return false; } return true; } else if ( filemode == KDFM_ASCII ) { //Template 이름, UUID AsciiType으로 저장 char buff[512]; s_sprintf(buff, _countof( buff ), GetTemplateName()); stream.Write( buff , strlen(buff) ); stream.Write( "\n", strlen("\n")); s_sprintf(buff, _countof( buff ), "{%08X-%04hX-%04hX-%04X-%04X%04X%04X}\n", m_uuidTemplate.Data1, m_uuidTemplate.Data2, m_uuidTemplate.Data3, m_uuidTemplate.Data4[0]*256 + m_uuidTemplate.Data4[1], m_uuidTemplate.Data4[2]*256 + m_uuidTemplate.Data4[3], m_uuidTemplate.Data4[4]*256 + m_uuidTemplate.Data4[5], m_uuidTemplate.Data4[6]*256 + m_uuidTemplate.Data4[7]); PrintTab(stream,filemode); stream.Write( buff , strlen(buff) ); PrintTab(stream,filemode); stream.Write( "{\n", strlen("{\n") ); //Member objects를 하나씩 저장 std::vector::iterator it = m_vectorMemberObjects.begin(); this->SetTab(this->GetTab()+1); for( ; it != m_vectorMemberObjects.end() ; ) { PrintTab(stream,filemode); (*it)->SetTab(this->GetTab()); if ( (*it)->Save( stream, filemode ) == false ) return false; ++it; if( it!= m_vectorMemberObjects.end() ) stream.Write(",\n",strlen(",\n")); } this->SetTab(this->GetTab()-1); stream.Write("\n",strlen("\n")); PrintTab(stream,filemode); stream.Write("}",strlen("}")); return true; } return false; } bool KTemplateDataObject::Load( KStream &stream, FileMode filemode ) { if ( filemode == KDFM_BINARY ) { char token; stream.Read( &token, 1 ); if ( token == KTOKEN_TEMPLATE ) { KDataObject *dataobj = NULL; stream.Read( &m_uuidTemplate, sizeof(m_uuidTemplate) ); clearMembers(); getMemberData(false); int nMembers; stream.Read( &nMembers, sizeof(nMembers) ); //assert( nMembers == GetMemberCount() ); for ( int i=0 ; i< nMembers ; ++i ) { stream.Read( &token, 1 ); if ( token == KTOKEN_ARRAY ) { stream.Read( &token, 1 ); stream.Seek( -2, KStream::seekCur ); switch( token ) { case KTOKEN_TEMPLATE: dataobj = new KTemplateDataArrayObject( stream, filemode, this ); break; case KTOKEN_WORD: case KTOKEN_DWORD: case KTOKEN_FLOAT: case KTOKEN_CHAR: case KTOKEN_UCHAR: case KTOKEN_STRING: dataobj = new KSimpleDataArrayObject( CLASSTYPEID_NONE, this ); dataobj->Load( stream, filemode ); break; } } else { stream.Seek( -1, KStream::seekCur ); switch( token ) { case KTOKEN_WORD: case KTOKEN_DWORD: case KTOKEN_FLOAT: case KTOKEN_CHAR: case KTOKEN_UCHAR: case KTOKEN_STRING: dataobj = new KSimpleDataObject( CLASSTYPEID_NONE ); dataobj->Load( stream, filemode ); break; case KTOKEN_TEMPLATE: dataobj = new KTemplateDataObject( stream, filemode ); break; } } m_vectorMemberObjects.push_back( dataobj ); const char *name; if ( i < GetMemberCount() ) { assert( dataobj && dataobj->GetClassType() == m_memberInfo->GetMemberClassID(i) ); name = m_memberInfo->GetMemberName(i); } else { KTemplateDataObject *obj = reinterpret_cast(dataobj); name = obj->GetTemplateName(); } //m_hashByName.add( name, dataobj ); } } } else if ( filemode == KDFM_ASCII ) { std::string token; char cTemp[256]; KTemplateInfo *pTemplateInfo; GUID uuidTemp; int nCount; // Read Template Name if ( !getNextToken( stream, token ) ) return false; if ( ( pTemplateInfo = KFiler::GetTemplateInfo( token.c_str() ) ) == NULL ) return false; if( !isNextOBrace( stream ) ) return false; if( !getNextToken( stream, token) ) return false; // Template 이름으로 알아낸 UID와 파일에서 직접 읽은 UID가 같은지 확인 uuidTemp = pTemplateInfo->GetTemplateGUID(); s_sprintf(cTemp, _countof( cTemp ), "%08X-%04hX-%04hX-%04X-%04X%04X%04X", uuidTemp.Data1, uuidTemp.Data2, uuidTemp.Data3, uuidTemp.Data4[0]*256 + uuidTemp.Data4[1], uuidTemp.Data4[2]*256 + uuidTemp.Data4[3], uuidTemp.Data4[4]*256 + uuidTemp.Data4[5], uuidTemp.Data4[6]*256 + uuidTemp.Data4[7]); if ( strcmp(token.c_str(), cTemp) != 0 ) return false; if( !isNextCBrace( stream ) ) return false; m_uuidTemplate = uuidTemp; clearMembers(); getMemberData(true); nCount = m_memberInfo->GetMemberCount(); if( !isNextOBrace( stream ) ) return false; for (int i = 0; i < nCount ; i++ ) { KDataObject *dataobj = m_vectorMemberObjects[i]; if (dataobj->Load( stream, filemode ) == false) return false; } if( !isNextCBrace( stream ) ) return false; return true; } return false; } bool KTemplateDataObject::LoadFast(KStream& stream) { // type + GUID + member count const long OFFSET = 1 + sizeof(GUID) + sizeof(int); stream.Seek(OFFSET, KStream::seekCur ); for(size_t i = 0; i < m_vectorMemberObjects.size(); ++i) { // 이미 type 정보들이 복사 되어 있으므로.. m_vectorMemberObjects[i]->LoadFast(stream); } return true; } KDataObject* KTemplateDataObject::CloneTypeInfo(KTemplateDataObject* pParent) { KTemplateDataObject* pObject = new KTemplateDataObject; pObject->m_uuidTemplate = m_uuidTemplate; pObject->m_memberInfo = m_memberInfo; size_t count = m_vectorMemberObjects.size(); pObject->m_vectorMemberObjects.resize(count); for(size_t i = 0; i m_vectorMemberObjects[i] = m_vectorMemberObjects[i]->CloneTypeInfo(pObject); } return pObject; } void KTemplateDataObject::getMemberData( bool bCreateMember ) { m_memberInfo = KFiler::GetTemplateInfo( m_uuidTemplate ); m_uuidTemplate = m_memberInfo->GetTemplateGUID(); if ( bCreateMember == true ) { m_vectorMemberObjects.clear(); //m_hashByName.clear(); int count = m_memberInfo->GetMemberCount(); m_vectorMemberObjects.resize( count ); for ( int i=0 ; iCreateMember( i, this ); m_vectorMemberObjects[i] = obj; //m_hashByName.add( m_memberInfo->GetMemberName(i), obj ); } } } //ascii모드에서 tab 출력위해 void KTemplateDataArrayObject::PrintTab( KStream &stream,FileMode filemode ) { if(filemode==KDFM_ASCII) { int t_size=GetTab(); for(int i=0;i