Files
2026-06-01 12:46:52 +02:00

1645 lines
34 KiB
C++

#include <algorithm>
#include <vector>
#include <map>
#include <set>
#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 "<NULL>";
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( "<NULL>" );
}
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;
}