#include #include #include #include #include "../../include/toolkit/XEnv.h" #include "../../include/toolkit/nsl.h" #include "../../include/toolkit/ILock.h" #include "../../include/cipher/XEncrypt.h" #include "../../include/toolkit/safe_function.h" const char * XEnvStruct::ENV_FILE_FORMAT_TAG = "EV"; struct TENV { TENV( const char* _szKey, const char* _szData ) { init( _szKey ); SetData( _szData ); } TENV( const char* _szKey, int _nNumber ) { init( _szKey ); SetData( _nNumber ); } TENV( const char* _szKey, int* _pNumber ) { init( _szKey ); Bind( _pNumber ); } TENV( const char* _szKey, short* _pNumber ) { init( _szKey ); Bind( _pNumber ); } TENV( const char* _szKey, float _fNumber ) { init( _szKey ); SetData( _fNumber ); } TENV( const char* _szKey, float* _pNumber ) { init( _szKey ); Bind( _pNumber ); } TENV( const char* _szKey, const XEnvStruct::Vector& v ) { init( _szKey ); SetData( v ); } TENV( const char* _szKey, const XEnvStruct::Quaternion& q ) { init( _szKey ); SetData( q ); } TENV( const char* _szKey, XEnvStruct::Vector* pVector ) { init( _szKey ); Bind( pVector ); } TENV( const char* _szKey, XEnvStruct::Quaternion* pQuaternion ) { init( _szKey ); Bind( pQuaternion ); } TENV( const char* _szKey, bool* _pBoolean ) { init( _szKey ); Bind( _pBoolean ); } TENV( const char* _szKey, int (*_nfn)() ) { init( _szKey ); Bind( _nfn ); } TENV( const char* _szKey, std::string& (*_sfn)() ) { init( _szKey ); Bind( _sfn ); } TENV( const char* _szKey, std::string* str ) { init( _szKey ); Bind( str ); } TENV( const char* _szKey ) { init( _szKey ); } ~TENV() { if ( pChildList ) { for ( std::set< TENV*, TENV::TENVLESS >::iterator it = pChildList->begin(); it != pChildList->end(); ++it ) { delete* it; } delete pChildList; } if ( env_type == STRING && bind_type == NONE ) delete strData; } inline unsigned DoEachData( XEnvStruct::XEnvFunctor& fo, const char* szMask, bool bTranslateDataToString = false ) { unsigned cnt = 0; if ( env_type != CONTAINER ) { if ( nsl::wildcmp( szMask, strFullKey.c_str(), true ) ) { if ( bTranslateDataToString ) { fo.onString( strFullKey, GetString() ); } else { if ( env_type == INTEGER ) fo.onInteger( strFullKey, GetInteger() ); else if ( env_type == SHORT ) fo.onShort( strFullKey, static_cast< short >( GetInteger() ) ); else if ( env_type == FLOAT ) fo.onFloat( strFullKey, GetFloat() ); else if ( env_type == VECTOR ) fo.onVector( strKey, GetVector() ); else if ( env_type == QUATERNION ) fo.onQuaternion( strFullKey, GetQuaternion() ); else fo.onString( strFullKey, GetString() ); } cnt++; } } if ( pChildList ) { for ( std::set< TENV*, TENV::TENVLESS >::iterator it = pChildList->begin(); it != pChildList->end(); ++it ) { cnt += (*it)->DoEachData( fo, szMask, bTranslateDataToString ); } } return cnt; } inline void RemoveChildNode( TENV* p ) { pChildList->erase( p ); } inline void SetData( const char* szData ) { if ( env_type != NONE ) { if ( env_type == VECTOR ) { XEnvStruct::Vector v; sscanf_s( szData, "%f;%f;%f", &v.x, &v.y, &v.z ); SetData( v ); return; } if ( env_type == QUATERNION ) { XEnvStruct::Quaternion q; sscanf_s( szData, "%f;%f;%f;%f", &q.x, &q.y, &q.z, &q.w ); SetData( q ); return; } if ( env_type == SHORT || env_type == INTEGER || env_type == BOOLEAN ) { SetData( atoi( szData ) ); return; } if ( env_type == FLOAT ) { SetData( (float)atof( szData ) ); return; } } if ( !strData ) { strData = new std::string( szData ); bind_type = NONE; } else { *strData = szData; } env_type = STRING; } inline void SetData( float fNumber ) { if ( bind_type != FUNCTION && env_type == STRING ) { nsl::sprintf_str(* strData, "%f", fNumber ); return; } if ( bind_type == VARIABLE && env_type == FLOAT )* pFloat = fNumber; else fFloat[0] = fNumber; env_type = FLOAT; } inline void SetData( const XEnvStruct::Vector& v ) { if ( bind_type != FUNCTION && env_type == STRING ) { nsl::sprintf_str(* strData, "%f;%f;%f", v.x, v.y, v.z ); return; } if ( bind_type == VARIABLE && env_type == VECTOR ) { pQuaternion->x = v.x; pQuaternion->y = v.y; pQuaternion->z = v.z; } if ( bind_type == NONE ) { fFloat[0] = v.x; fFloat[1] = v.y; fFloat[2] = v.z; env_type = VECTOR; } } inline void SetData( const XEnvStruct::Quaternion& q ) { if ( bind_type != FUNCTION && env_type == STRING ) { nsl::sprintf_str(* strData, "%f;%f;%f;%f", q.x, q.y, q.z, q.w ); return; } if ( bind_type == VARIABLE && env_type == QUATERNION ) { pQuaternion->x = q.x; pQuaternion->y = q.y; pQuaternion->z = q.z; pQuaternion->w = q.w; } if ( bind_type == NONE ) { fFloat[0] = q.x; fFloat[1] = q.y; fFloat[2] = q.z; env_type = QUATERNION; } } inline void SetData( int nNumber ) { if ( bind_type != FUNCTION && env_type == STRING ) { nsl::sprintf_str(* strData, "%d", nNumber ); return; } if ( bind_type == VARIABLE ) { if ( env_type == BOOLEAN ) { if( nNumber == 0 ) { *pBoolean = false; } else { *pBoolean = true; } } else if ( env_type == SHORT ) { *pShort = static_cast< short >( nNumber ); } else if ( env_type == INTEGER ) { *pInteger = nNumber; } } else if ( bind_type == NONE ) { nInteger = nNumber; env_type = INTEGER; } } inline float GetFloat() const { if ( bind_type == VARIABLE && env_type == FLOAT ) return* pFloat; if ( bind_type == NONE && env_type == FLOAT ) return fFloat[0]; if ( env_type == STRING ) return (float)atof( GetString().c_str() ); return (float)nInteger; } inline bool GetBoolean() const { if ( bind_type == VARIABLE && env_type == BOOLEAN ) return* pBoolean; return !!(int)nInteger; } inline XEnvStruct::Vector GetVector() const { if ( env_type == STRING && strData ) { XEnvStruct::Vector v; sscanf_s( strData->c_str(), "%f;%f;%f", &v.x, &v.y, &v.z ); return v; } if ( bind_type == VARIABLE && env_type == VECTOR ) return XEnvStruct::Vector( pVector->x, pVector->y, pVector->z ); return XEnvStruct::Vector( fFloat[0], fFloat[1], fFloat[2] ); } inline XEnvStruct::Quaternion GetQuaternion() const { if ( env_type == STRING && strData ) { XEnvStruct::Quaternion q; sscanf_s( strData->c_str(), "%f;%f;%f;%f", &q.x, &q.y, &q.z, &q.w ); return q; } if ( bind_type == VARIABLE && env_type == QUATERNION ) return XEnvStruct::Quaternion( pQuaternion->x, pQuaternion->y, pQuaternion->z, pQuaternion->w ); return XEnvStruct::Quaternion( fFloat[0], fFloat[1], fFloat[2], fFloat[3] ); } inline int GetInteger() const { if ( bind_type == NONE ) return nInteger; if ( bind_type == FUNCTION ) { if ( env_type == INTEGER && nfn ) return nfn(); } if ( bind_type == VARIABLE ) { if ( env_type == BOOLEAN ) return* pBoolean; if ( env_type == INTEGER ) return* pInteger; if ( env_type == SHORT ) return* pShort; } return 0; } inline void Bind( int* pNumber ) { env_type = INTEGER; bind_type = VARIABLE; pInteger = pNumber; } inline void Bind( short* pNumber ) { env_type = SHORT; bind_type = VARIABLE; pShort = pNumber; } inline void Bind( XEnvStruct::Quaternion* _pQuaternion ) { env_type = QUATERNION; bind_type = VARIABLE; pQuaternion = _pQuaternion; } inline void Bind( XEnvStruct::Vector* pfVector ) { env_type = VECTOR; bind_type = VARIABLE; pVector = pfVector; } inline void Bind( float* pNumber ) { env_type = FLOAT; bind_type = VARIABLE; pFloat = pNumber; } inline void Bind( bool* _pBoolean ) { env_type = BOOLEAN; bind_type = VARIABLE; pBoolean = _pBoolean; } inline void Bind( int (*_fn)() ) { env_type = INTEGER; bind_type = FUNCTION; nfn = _fn; } inline void Bind( std::string& (*_fn)() ) { env_type = STRING; bind_type = FUNCTION; sfn = _fn; } inline void Bind( std::string* str ) { env_type = STRING; bind_type = VARIABLE; strData = str; } inline void SetReadOnly() { read_only = true; } inline bool IsReadOnly() { return read_only; } inline const std::string & GetKey() const { return strKey; } inline void SetKey( const char* szKey ) { strKey = szKey; } inline std::string GetString() const { if ( IsContainer() ) return ""; if ( env_type != STRING ) { if ( IsNumber() ) { std::string buf; nsl::sprintf_str( buf, "%d", GetInteger() ); return buf; } if ( IsVector() ) { std::string buf; XEnvStruct::Vector v = GetVector(); nsl::sprintf_str( buf, "%f;%f;%f", v.x, v.y, v.z ); return buf; } if ( IsQuaternion() ) { std::string buf; XEnvStruct::Quaternion q = GetQuaternion(); nsl::sprintf_str( buf, "%f;%f;%f;%f", q.x, q.y, q.z, q.w ); return buf; } if ( IsFloat() ) { std::string buf; nsl::sprintf_str( buf, "%f", GetFloat() ); return buf; } if ( env_type == BOOLEAN ) { std::string buf; nsl::sprintf_str( buf, "%d", GetBoolean() ? 1 : 0 ); return buf; } } if ( bind_type == FUNCTION ) return sfn(); return* strData; } inline bool IsString() const { return env_type == STRING; } inline bool IsInteger() const { return env_type == INTEGER; } inline bool IsShort() const { return env_type == SHORT; } inline bool IsNumber() const { return env_type == INTEGER || env_type == SHORT; } inline bool IsFloat() const { return env_type == FLOAT; } inline bool IsBoolean() const { return env_type == BOOLEAN; } inline bool IsQuaternion() const{ return env_type == QUATERNION;} inline bool IsVector() const { return env_type == VECTOR; } inline bool IsContainer() const { return env_type == CONTAINER; } inline bool IsBinded() const { return ( pVector || pInteger || pShort || pFloat || pBoolean || sfn || nfn ); } inline void SetAsContainer() { env_type = CONTAINER; } struct TENVLESS { inline bool operator()( const TENV* left, TENV* right ) const { return left->GetKey() < right->GetKey(); } }; std::set< TENV*, TENV::TENVLESS > * pChildList; TENV* pParentNode; private: void init( const char* _szKey ) { read_only = false; strFullKey = _szKey; SetKey( _szKey ); bind_type = NONE; strData = NULL; pParentNode = NULL; pChildList = NULL; nInteger = 0; fFloat[0] = 0; fFloat[1] = 0; fFloat[2] = 0; pFloat = NULL; pVector = NULL; pQuaternion = NULL; pInteger = NULL; pShort = NULL; pBoolean = NULL; env_type = NONE; sfn = NULL; nfn = NULL; } std::string strKey; std::string strFullKey; union { std::string & (*sfn)(); int (*nfn)(); bool* pBoolean; std::string* strData; int nInteger; float fFloat[4]; volatile int* pInteger; volatile short* pShort; volatile float* pFloat; volatile XEnvStruct::Vector* pVector; volatile XEnvStruct::Quaternion* pQuaternion; }; enum { NONE = -1, CONTAINER = 0, BOOLEAN, INTEGER, SHORT, FLOAT, VECTOR, STRING, QUATERNION, FUNCTION , VARIABLE }; char env_type; char bind_type; bool read_only; }; typedef std::set< TENV*, TENV::TENVLESS > ENVMAP; struct _XEnvStructImpl { _XEnvStructImpl(); ~_XEnvStructImpl(); template< typename T > void Bind( const char* szKey, T data ) { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) { pNew->Bind( data ); onEnvUpdate(szKey); } else { insert( szKey, new TENV( szKey, data ), m_pSet ); onEnvInsert(szKey); } } void SetReadOnly( const char* szKey ) { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) { pNew->SetReadOnly(); } } template< typename T > void Set( const char* szKey, T data ) { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) { if ( pNew->IsReadOnly() ) return; pNew->SetData( data ); onEnvUpdate( szKey ); } else { insert( szKey, new TENV( szKey, data ), m_pSet ); onEnvInsert( szKey ); } } XEnvStruct::Quaternion GetQuaternion( const char* szKey, float default_x, float default_y, float default_z, float default_w ) const; XEnvStruct::Vector GetVector( const char* szKey, float default_x, float default_y, float default_z ) const; std::string GetString( const char* szKey, const char* szDefault ) const; int GetInt( const char* szKey, int nData ) const; float GetFloat( const char* szKey, float fData ) const; void SetFlag( const char* szKey, int nFlagIndex, bool bFlag ); void SetFlag( const char* szKey, const char* szFlagName, bool bFlag ); void SetConstant( const char* szKey, const char* szName, int nFlagIndex ); int GetConstant( const char* szKey, const char* szName, int nDefault ); bool Remove( const char* szKey ); bool Remove( TENV* p ); bool IsExist( const char* szKey ) const; bool IsContainer( const char* szKey ) const; bool IsBinded( const char* szKey ) const; unsigned DoEachData( XEnvStruct::XEnvFunctor& fo, const char* szMask, bool bTranslateDataToString = false ); TENV* find( const char* szKey, TENV* pSet ) const; void insert( const char* szKey, TENV* pData, TENV* pSet ); void SetEventReceiver( XEnvStruct::XEnvEventReceiver* pReceiver ); void onEnvUpdate( const char* szKey ) { if ( m_pReceiver ) m_pReceiver->onEnvUpdate( szKey ); } void onEnvInsert( const char* szKey ) { if ( m_pReceiver ) m_pReceiver->onEnvInsert( szKey ); } XCriticalSection csLock; private: _XEnvStructImpl( const _XEnvStructImpl& ); _XEnvStructImpl& operator=( const _XEnvStructImpl& ); XEnvStruct::XEnvEventReceiver* m_pReceiver; TENV* m_pSet; std::map< std::string, int > m_mapFlagName; }; _XEnvStructImpl::_XEnvStructImpl() : csLock( "_XEnvStructImpl" ) { m_pSet = new TENV( "ROOT" ); m_pSet->SetAsContainer(); m_pReceiver = NULL; } _XEnvStructImpl::~_XEnvStructImpl() { delete m_pSet; } const char* CONSTANT_SEPARATOR = "\r\t\n"; int _XEnvStructImpl::GetConstant( const char* szKey, const char* szName, int nDefault ) { std::string strKey; if ( szKey ) strKey += szKey; strKey += CONSTANT_SEPARATOR; strKey += szName; std::map< std::string, int >::iterator it = m_mapFlagName.find( strKey ); if ( it == m_mapFlagName.end() ) return nDefault; return it->second; } void _XEnvStructImpl::SetConstant( const char* szKey, const char* szName, int nFlagIndex ) { std::string strKey; if ( szKey ) strKey += szKey; strKey += CONSTANT_SEPARATOR; strKey += szName; m_mapFlagName[ strKey ] = nFlagIndex; } void _XEnvStructImpl::insert( const char* szKey, TENV* pData, TENV* pSet ) { char* p = const_cast< char* >( szKey ); char* szFirstKey = p; const char* pDot; bool bIsTerminal = true; char buf[128]; if ( (pDot = strchr( szKey, '.' )) != NULL ) { s_strncpy( buf, _countof( buf ), szKey, pDot - szKey ); buf[pDot - szKey] = 0; szFirstKey = buf; bIsTerminal = false; } if ( !pSet->pChildList ) { pSet->pChildList = new ENVMAP; } if ( bIsTerminal ) { pData->SetKey( szKey ); pSet->pChildList->insert( pData ); pData->pParentNode = pSet; return; } TENV Key( szFirstKey ); ENVMAP::iterator it = pSet->pChildList->find( &Key ); if ( it == pSet->pChildList->end() ) { TENV* pNew = new TENV( szFirstKey ); pNew->SetAsContainer(); pSet->pChildList->insert( pNew ); pNew->pParentNode = pSet; insert( pDot+1, pData, pNew ); } else { insert( pDot+1, pData,* it ); } } TENV* _XEnvStructImpl::find( const char* szKey, TENV* pSet ) const { const char* pDot; if ( (pDot = strchr( szKey, '.' )) != NULL ) { if ( !pSet->pChildList ) return NULL; char buf[128]; s_strncpy( buf, _countof( buf ), szKey, pDot - szKey ); buf[pDot - szKey] = 0; TENV* pNode = NULL; TENV Key( buf ); ENVMAP::iterator it = pSet->pChildList->find( &Key ); if ( it != pSet->pChildList->end() ) pNode =* it; if ( !pNode ) return NULL; return find( pDot+1, pNode ); } if ( !pSet->pChildList ) { if ( _stricmp( szKey, pSet->GetKey().c_str() ) ) return NULL; return pSet; } TENV Key( szKey ); ENVMAP::iterator it = pSet->pChildList->find( &Key ); if ( it == pSet->pChildList->end() ) { return NULL; } return* it; } void _XEnvStructImpl::SetEventReceiver( XEnvStruct::XEnvEventReceiver* pReceiver ) { m_pReceiver = pReceiver; } XEnvStruct::Vector _XEnvStructImpl::GetVector( const char* szKey, float default_x, float default_y, float default_z ) const { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) return pNew->GetVector(); return XEnvStruct::Vector( default_x, default_y, default_z ); } XEnvStruct::Quaternion _XEnvStructImpl::GetQuaternion( const char* szKey, float default_x, float default_y, float default_z, float default_w ) const { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) return pNew->GetQuaternion(); return XEnvStruct::Quaternion( default_x, default_y, default_z, default_w ); } std::string _XEnvStructImpl::GetString( const char* szKey, const char* szDefault ) const { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) return pNew->GetString(); if ( szDefault ) return std::string( szDefault ); return std::string( "" ); } int _XEnvStructImpl::GetInt( const char* szKey, int nDefault ) const { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) { if ( pNew->IsNumber() ) return pNew->GetInteger(); else if ( pNew->IsFloat() ) return static_cast< int >( pNew->GetFloat() ); return atoi( pNew->GetString().c_str() ); } return nDefault; } float _XEnvStructImpl::GetFloat( const char* szKey, float fDefault ) const { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) { if ( pNew->IsNumber() ) return float( pNew->GetInteger() ); else if ( pNew->IsFloat() ) return pNew->GetFloat(); return static_cast< float >( atof( pNew->GetString().c_str() ) ); } return fDefault; } bool _XEnvStructImpl::Remove( TENV* p ) { if ( !p->pParentNode ) { return true; } p->pParentNode->RemoveChildNode( p ); if ( p->pParentNode->IsContainer() && !p->pParentNode->pChildList->size() ) { Remove( p->pParentNode ); } delete p; return true; } void _XEnvStructImpl::SetFlag( const char* szKey, const char* szFlagName, bool bFlag ) { std::map< std::string, int >::iterator it = m_mapFlagName.find( szKey ); if ( it == m_mapFlagName.end() ) return; return SetFlag( szKey, it->second, bFlag ); } void _XEnvStructImpl::SetFlag( const char* szKey, int nFlagIndex, bool bFlag ) { TENV* pNew = find( szKey, m_pSet ); if ( pNew ) { int nData = pNew->GetInteger(); if ( bFlag ) nData |= ( 1 << nFlagIndex ); else nData &= ~( 1 << nFlagIndex ); pNew->SetData( nData ); onEnvUpdate( szKey ); } else { int nData = 0; if ( bFlag ) nData |= ( 1 << nFlagIndex ); insert( szKey, new TENV( szKey, nData ), m_pSet ); onEnvInsert( szKey ); } } bool _XEnvStructImpl::Remove( const char* szKey ) { TENV* pNew = find( szKey, m_pSet ); if ( !pNew ) return false; return Remove( pNew ); } bool _XEnvStructImpl::IsExist( const char* szKey ) const { return (find( szKey, m_pSet ) != NULL); } bool _XEnvStructImpl::IsContainer( const char* szKey ) const { TENV* pNew = find( szKey, m_pSet ); if ( pNew && pNew->IsContainer() ) return true; return false; } bool _XEnvStructImpl::IsBinded( const char* szKey ) const { TENV* pNew = find( szKey, m_pSet ); if ( pNew && pNew->IsBinded() ) return true; return false; } unsigned _XEnvStructImpl::DoEachData( XEnvStruct::XEnvFunctor& fo, const char* szMask, bool bTranslateDataToString ) { return m_pSet->DoEachData( fo, szMask, bTranslateDataToString ); } XEnvStruct::XEnvStruct() { m_pImpl = new _XEnvStructImpl(); } XEnvStruct::~XEnvStruct() { _XEnvStructImpl * pImpl = m_pImpl; m_pImpl = NULL; delete pImpl; } void XEnvStruct::SetEventReceiver( XEnvStruct::XEnvEventReceiver* pReceiver ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->SetEventReceiver( pReceiver ); } void XEnvStruct::Set( const char* szKey, int nData ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Set( szKey, nData ); } void XEnvStruct::Set( const char* szKey, float fData ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Set( szKey, fData ); } void XEnvStruct::Set( const char* szKey, const char* szData ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Set( szKey, szData ); } void XEnvStruct::SetReadOnly( const char* szKey ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->SetReadOnly( szKey ); } void XEnvStruct::Set( const char* szKey, const Quaternion& q ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Set( szKey, q ); } void XEnvStruct::Set( const char* szKey, const Vector& v ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Set( szKey, v ); } int XEnvStruct::GetConstant( const char* szKey, const char* szName, int nDefault ) { if( !m_pImpl ) return nDefault; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->GetConstant( szKey, szName, nDefault ); } void XEnvStruct::SetConstant( const char* szKey, const char* szName, int nFlagIndex ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->SetConstant( szKey, szName, nFlagIndex ); } void XEnvStruct::SetFlag( const char* szKey, int nFlagIndex, bool bFlag ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->SetFlag( szKey, nFlagIndex, bFlag ); } void XEnvStruct::Bind( const char* szKey, bool* pData ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, pData ); } void XEnvStruct::Bind( const char* szKey, float* pData ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, pData ); } void XEnvStruct::Bind( const char* szKey, XEnvStruct::Vector* pVector ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, pVector ); } void XEnvStruct::Bind( const char* szKey, short* pData ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, pData ); } void XEnvStruct::Bind( const char* szKey, XEnvStruct::Quaternion* pQuaternion ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, pQuaternion ); } void XEnvStruct::Bind( const char* szKey, int* pData ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, pData ); } void XEnvStruct::Bind( const char* szKey, int (*fn)() ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, fn ); } void XEnvStruct::Bind( const char* szKey, std::string& (*fn)() ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, fn ); } void XEnvStruct::Bind( const char* szKey, std::string* str ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); m_pImpl->Bind( szKey, str ); } std::string XEnvStruct::GetString( const char* szKey, const char* szDefault ) const { if( !m_pImpl ) return szDefault; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->GetString( szKey, szDefault ); } XEnvStruct::Vector XEnvStruct::GetVector( const char* szKey, float default_x, float default_y, float default_z ) const { if( !m_pImpl ) return XEnvStruct::Vector( default_x, default_y, default_z ); THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->GetVector( szKey, default_x, default_y, default_z ); } XEnvStruct::Quaternion XEnvStruct::GetQuaternion( const char* szKey, float default_x, float default_y, float default_z, float default_w ) const { if( !m_pImpl ) return XEnvStruct::Quaternion( default_x, default_y, default_z, default_w ); THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->GetQuaternion( szKey, default_x, default_y, default_z, default_w ); } int XEnvStruct::GetInt( const char* szKey, int nDefault ) const { if( !m_pImpl ) return nDefault; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->GetInt( szKey, nDefault ); } float XEnvStruct::GetFloat( const char* szKey, float fDefault ) const { if( !m_pImpl ) return fDefault; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->GetFloat( szKey, fDefault ); } bool XEnvStruct::Remove( const char* szKey ) { if( !m_pImpl ) return false; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->Remove( szKey ); } void XEnvStruct::SetDefaultValue( const char* szKey, int nDefault ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); if ( m_pImpl->IsExist( szKey ) ) return; m_pImpl->Set( szKey, nDefault ); } void XEnvStruct::SetDefaultValue( const char* szKey, const char* szData ) { if( !m_pImpl ) return; THREAD_SYNCRONIZE( &m_pImpl->csLock ); if ( m_pImpl->IsExist( szKey ) ) return; return m_pImpl->Set( szKey, szData ); } unsigned XEnvStruct::DoEachData( XEnvFunctor& fo, const char* szMask, bool bTranslateDataToString ) { if( !m_pImpl ) return 0; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->DoEachData( fo, szMask, bTranslateDataToString ); } XEnvStruct& ENV() { static XEnvStruct env; return env; } bool XEnvStruct::IsExist( const char* szKey ) const { if( !m_pImpl ) return false; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->IsExist( szKey ); } bool XEnvStruct::IsBinded( const char* szKey ) const { if( !m_pImpl ) return false; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->IsBinded( szKey ); } bool XEnvStruct::IsContainer( const char* szKey ) const { if( !m_pImpl ) return false; THREAD_SYNCRONIZE( &m_pImpl->csLock ); return m_pImpl->IsContainer( szKey ); } bool XEnvStruct::SaveToFile( const char* szFileName, const char* szMask, const bool bEncode ) { if( !m_pImpl ) return false; FILE* fp = NULL; if( fopen_s( &fp, szFileName, (bEncode) ? "wb" : "wt" ) != 0 ) return false; if ( !fp ) return false; struct FileCloser { FileCloser( FILE * _fp ) : fp( _fp ) {} ~FileCloser() { fclose( fp ); } FILE * fp; } fc( fp ); std::string strBuffer; struct _M : XEnvFunctor { _M( std::string & strBuffer ) : m_strBuffer( strBuffer ) { ::memset( m_szBuffer, 0, sizeof( m_szBuffer ) ); } virtual void onString( const std::string& strKey, const std::string& strData ) { s_sprintf( m_szBuffer, _countof( m_szBuffer ), "S:%s:%s\n", strKey.c_str(), strData.c_str() ); m_strBuffer += m_szBuffer; } virtual void onFloat( const std::string& strKey, float fNumber ) { s_sprintf( m_szBuffer, _countof( m_szBuffer ), "F:%s:%f\n", strKey.c_str(), fNumber ); m_strBuffer += m_szBuffer; } virtual void onVector( const std::string& strKey, const XEnvStruct::Vector& v ) { s_sprintf( m_szBuffer, _countof( m_szBuffer ), "V:%s:%f;%f;%f\n", strKey.c_str(), v.x, v.y, v.z ); m_strBuffer += m_szBuffer; } virtual void onQuaternion( const std::string& strKey, const XEnvStruct::Quaternion& q ) { s_sprintf( m_szBuffer, _countof( m_szBuffer ), "Q:%s:%f;%f;%f;%f\n", strKey.c_str(), q.x, q.y, q.z, q.w ); m_strBuffer += m_szBuffer; } virtual void onInteger( const std::string& strKey, int nNumber ) { s_sprintf( m_szBuffer, _countof( m_szBuffer ), "N:%s:%d\n", strKey.c_str(), nNumber ); m_strBuffer += m_szBuffer; } virtual void onShort( const std::string& strKey, short nNumber ) { s_sprintf( m_szBuffer, _countof( m_szBuffer ), "T:%s:%d\n", strKey.c_str(), nNumber ); m_strBuffer += m_szBuffer; } std::string & m_strBuffer; char m_szBuffer[1024]; private: const _M& operator=( const _M& ) { return *this; } } _m( strBuffer ); DoEachData( _m, szMask ); size_t nContentsLength = strBuffer.size(); if( bEncode ) { std::vector< BYTE > vEncrypted; if( !XEncrypt::Encrypt( XEncrypt::ET_ZLIB_WITH_SIMPLE_CIPHER, ENV_FILE_FORMAT_TAG, ENV_FILE_VERSION3, strBuffer.c_str(), nContentsLength, vEncrypted ) ) return false; if( fwrite( &vEncrypted.front(), vEncrypted.size(), 1, fp ) != 1 ) { assert( 0 ); return false; } } else { if( nContentsLength && fwrite( strBuffer.data(), 1, nContentsLength, fp ) != nContentsLength ) { assert( 0 ); return false; } } return true; } bool XEnvStruct::LoadFromFile( const char* szFileName, const char* szMask, const bool bEncode, const unsigned int nStrictFileVersion ) { if( !m_pImpl ) return false; THREAD_SYNCRONIZE( &m_pImpl->csLock ); bool bRtn = false; FILE* fp = NULL; if( fopen_s( &fp, szFileName, (bEncode) ? "rb" : "rt" ) != 0 ) return false; if ( !fp ) return false; struct FileCloser { FileCloser( FILE * _fp ) : fp( _fp ) {} ~FileCloser() { fclose( fp ); } FILE * fp; } fc( fp ); std::string strContents; size_t nContentsLength = 0; fseek( fp, 0, SEEK_END ); nContentsLength = ftell( fp ); rewind( fp ); if( !nContentsLength ) return true; if( bEncode ) { // No header if( !nContentsLength ) { assert( 0 ); return false; } BYTE * pBuffer = new BYTE[ nContentsLength ]; struct MemoryDeallocator { MemoryDeallocator( BYTE * _pBuffer ) : pBuffer( _pBuffer ) {} ~MemoryDeallocator() { delete [] pBuffer; } BYTE * pBuffer; } md( pBuffer ); if( fread( pBuffer, nContentsLength, 1, fp ) != 1 ) { assert( 0 ); return false; } const unsigned int nVersion = XEncrypt::GetFormatVersion( ENV_FILE_FORMAT_TAG, pBuffer, nContentsLength ); if( nVersion == XEncrypt::INVALID_VERSION || nStrictFileVersion && nVersion != nStrictFileVersion ) { assert( 0 ); return false; } std::vector< BYTE > vDecrypted; switch( nVersion ) { case ENV_FILE_VERSION: if( !XEncrypt::Decrypt( XEncrypt::ET_ZLIB, ENV_FILE_FORMAT_TAG, ENV_FILE_VERSION, pBuffer, nContentsLength, vDecrypted ) ) { assert( 0 ); return false; } break; case ENV_FILE_VERSION3: if( !XEncrypt::Decrypt( XEncrypt::ET_ZLIB_WITH_SIMPLE_CIPHER, ENV_FILE_FORMAT_TAG, ENV_FILE_VERSION3, pBuffer, nContentsLength, vDecrypted ) ) { assert( 0 ); return false; } break; default: assert( 0 ); return false; } if( vDecrypted.empty() ) return true; vDecrypted.push_back( NULL ); strContents = reinterpret_cast< char * >( &vDecrypted.front() ); } else { strContents.reserve( nContentsLength + 1 ); // Additional 1 byte is added for terminating null. nContentsLength = fread( const_cast< char * >( strContents.data() ), 1, nContentsLength, fp ); if( !nContentsLength ) { assert( 0 ); return false; } const_cast< char * >( strContents.data() )[ nContentsLength ] = '\0'; } char* p; bRtn = true; char * buf = NULL, * next_token = NULL; buf = strtok_s( const_cast< char * >( strContents.data() ), "\n", &next_token ); while( buf ) { p = strchr( &buf[2], ':' ); if ( !p ) { bRtn = false; break; } *p = '\0'; p++; if (* p ) { if ( p[ strlen( p ) - 1 ] == '\n' ) p[ strlen( p ) - 1 ] = '\0'; } char type = buf[0]; char* key = &buf[2]; char* data = p; if ( !nsl::wildcmp( szMask, key, true ) ) continue; Vector v; Quaternion q; v.x = v.y = v.z = 0.0f; q.x = q.y = q.z = q.w = 0.0f; switch( type ) { case 'S': Set( key, data ); break; case 'F': Set( key, (float)atof(data) ); break; case 'V': sscanf_s( data, "%f;%f;%f", &v.x, &v.y, &v.z ); Set( key, v ); break; case 'Q': sscanf_s( data, "%f;%f;%f;%f", &q.x, &q.y, &q.z, &q.w ); Set( key, q ); break; case 'N': Set( key, atoi(data) ); break; case 'T': Set( key, (short)atoi(data) ); break; } buf = strtok_s( NULL, "\n", &next_token ); } return bRtn; } bool XEnvStruct::LoadFromMemory( const void* pBuf, size_t bufSize, const char* szMask ) { if( !m_pImpl ) return false; const char* srcBuf = reinterpret_cast< const char* >( pBuf ); const char* srcBufEnd = srcBuf + bufSize; if ( !srcBuf || bufSize == 0 ) return false; THREAD_SYNCRONIZE( &m_pImpl->csLock ); char buf[1024]; char* p; bool bRtn = true; while ( srcBuf < srcBufEnd ) { { const char* pp = srcBuf; for (; pp < srcBuf + 1023 && pp < srcBufEnd; ++pp ) { if ( *pp == '\n' || *pp == '\r' ) break; } s_memcpy( buf, sizeof( buf ), srcBuf, pp - srcBuf ); buf[ pp - srcBuf ] = 0; for (; pp < srcBufEnd; ++pp ) { if ( *pp != '\n' && *pp != '\r' ) break; } srcBuf = pp; } p = strchr( &buf[2], ':' ); if ( !p ) { bRtn = false; break; } *p = '\0'; p++; if (* p ) { if ( p[ strlen( p ) - 1 ] == '\n' ) p[ strlen( p ) - 1 ] = '\0'; } char type = buf[0]; char* key = &buf[2]; char* data = p; if ( !nsl::wildcmp( szMask, key, true ) ) continue; Vector v; Quaternion q; v.x = v.y = v.z = 0.0f; q.x = q.y = q.z = q.w = 0.0f; switch( type ) { case 'S': Set( key, data ); break; case 'F': Set( key, (float)atof(data) ); break; case 'V': sscanf_s( data, "%f;%f;%f", &v.x, &v.y, &v.z ); Set( key, v ); break; case 'Q': sscanf_s( data, "%f;%f;%f;%f", &q.x, &q.y, &q.z, &q.w ); Set( key, q ); break; case 'N': Set( key, atoi(data) ); break; case 'T': Set( key, (short)atoi(data) ); break; } } return bRtn; } int XEnvStruct::ParseCmdLine( const char* szArgument ) { if( !m_pImpl ) return 0; int unCnt = 0; const char* szCmdLine = szArgument; Set( "app.cmdline", GetCommandLineA() ); if ( !szCmdLine ) szCmdLine = GetCommandLineA(); // { 커맨드 라인 아규먼트 세팅 if ( szCmdLine ) { std::vector< std::string > vArg; nsl::split( szCmdLine, vArg, " " ); // { 바보 바운즈 체커의 워닝을 피하기 위해.. -_- char* p = const_cast< char* >( szCmdLine ); std::string strCmdLine; while (* p ) strCmdLine.push_back(* p++ ); // } char* szArg; for ( unsigned i = 1; i < vArg.size(); i++ ) { szArg = const_cast< char* >( vArg[i].c_str() ); if ( szArg[0] == '/' && strlen( szArg ) > 1 ) { szArg++; std::string strKey; std::string strData; if ( strchr( szArg, ':' ) ) { while (* szArg &&* szArg != ':' ) { strKey += (*szArg++); } if (* szArg == ':' ) { szArg++; strData = szArg; Set( strKey, strData ); } } else if( strchr( szArg, '=' ) ) { while( *szArg && *szArg != '=' ) { strKey += (*szArg++); } if( *szArg == '=' ) { szArg++; strData = szArg; Set( strKey, strData ); } } else { Set( szArg, 1 ); } unCnt++; } } } // } return unCnt; }