#include "C:\tmp\Tool Classes\ParamIO\ParamIO.h"
#include <cassert>
#include <stdarg.h>
///////////////////////////////////////////////////////////////////////////////
//Wrapper around ParamIo by TBW
///////////////////////////////////////////////////////////////////////////////
enum VAL_TYPE
{
VALUE_UNKNOW = -1,
VAIUE_INT,// "int"
VAIUE_STRING,//"string"
VALUE_FLOAT,//"float"
VALUE_BOOL,//"bool"
VALUE_HEX//"hexa"
};
///////////////////////////////////////////////////
//TypeDefine : Definition of Types, and Type Checking of Strings
///////////////////////////////////////////////////
class TypeDefine
{
typedef std::vector< std::pair<std::string, VAL_TYPE > >::iterator type_iterator;
class FindType
{
public:
FindType( std::string strToken ) : m_strToken(strToken){ m_valType = VALUE_UNKNOW; }
FindType( VAL_TYPE valType ){ m_valType = valType; }
bool operator()(std::pair<std::string, VAL_TYPE> &p) const
{
if(m_valType == VALUE_UNKNOW )
{
if( m_strToken.find( p.first ) != std::string::npos )
return true;
}
else
{
return p.second == m_valType;
}
return false;
}
std::string m_strToken;
VAL_TYPE m_valType;
};
public:
TypeDefine()
{
m_vKnownTypes.reserve( 5 );
m_vKnownTypes.push_back( std::make_pair( std::string("int"), VAIUE_INT ) );
m_vKnownTypes.push_back( std::make_pair( std::string("string"), VAIUE_STRING ) );
m_vKnownTypes.push_back( std::make_pair( std::string("float"), VALUE_FLOAT ) );
m_vKnownTypes.push_back( std::make_pair( std::string("bool"), VALUE_BOOL ) );
m_vKnownTypes.push_back( std::make_pair( std::string("hex"), VALUE_HEX ) );
}
VAL_TYPE GetType( std::string& strToken, std::string& strValName )
{
type_iterator iterFound = std::find_if( m_vKnownTypes.begin(), m_vKnownTypes.end(), FindType(strToken) );
if( iterFound != m_vKnownTypes.end() )
{
std::string::size_type TypeEnd = strToken.find( iterFound->first );
std::string::size_type NameEnd = strToken.find( "=" );
size_t iNameStart = iterFound->first.size();
size_t iNameEnd = NameEnd - iNameStart - 1;
strValName = strToken.substr( iNameStart, iNameEnd );
return iterFound->second;
}
else
{
strValName = strToken;
}
return VALUE_UNKNOW;//no match
}
std::string GetValTypePrefix( VAL_TYPE valType )
{
type_iterator iterFound = std::find_if( m_vKnownTypes.begin(), m_vKnownTypes.end(), FindType(valType) );
if( iterFound != m_vKnownTypes.end() )
return iterFound->first;
return "";
}
private:
std::vector< std::pair<std::string, VAL_TYPE > > m_vKnownTypes;
};
///////////////////////////////////////////////////
//Attribute : behaviour of a single Attribute
///////////////////////////////////////////////////
class Attribute
{
public: Attribute( std::string& strTokenString );
template<class T>bool GetValue( T&value )
{
std::stringstream ist(m_strAttributeValue);
if( m_ValType == VALUE_HEX )
ist >> std::hex >>value;//TBW : maybe shall be reomved
else
ist >> value;
return true;
}
bool operator==( const std::string& strAttributeName ) const
{
return m_strAttributeName == strAttributeName;
}
private:
std::string m_strAttributeName;
std::string m_strAttributeValue;
VAL_TYPE m_ValType;
};
//////////////////////////////////////////////////////////////////////////////////////
//ConfigValue : behaviour of a whole Key == ConfigValue - can have multiple Attributes
//////////////////////////////////////////////////////////////////////////////////////
class ConfigValue
{
typedef std::vector< Attribute >::iterator attribute_iterator;
class FindAttribute
{
public:
FindAttribute( std::string strAttribName ) : m_strCmpName(strAttribName){}
bool operator()(Attribute& aAttrib ) const
{
return aAttrib == m_strCmpName;
}
std::string m_strCmpName;
};
friend class CfgValueCont;
private:
ConfigValue( std::string strKeyName, const char* strAttributeString );//parsing of the Attribute string
ConfigValue( std::string strKeyName, Element& aEl );
void ParesAttributeString( std::string& strAttributeString );
template<class T>bool GetValue( int iIndex, T&value, T& defaultVal )//for easy enumerating through loaded values
{
if( (unsigned int)iIndex < m_vFoundValues.size() )
return m_vFoundValues[iIndex].GetValue( value );
value = defaultVal;
return false;
}
template<class T>bool GetValue( std::string& strName, T& value, T& defaultVal )// true search -> by Name - gets the first match if same names in one branch
{
attribute_iterator iterFound = std::find_if( m_vFoundValues.begin(), m_vFoundValues.end(), FindAttribute(strName) );
if( iterFound != m_vFoundValues.end() )
{
(*iterFound).GetValue( value );
}
else
{
value = defaultVal;
return false;
}
return false;
}
std::vector< Attribute > m_vFoundValues;
std::string strKeyName;
};
//////////////////////////////////////////////////////////////////////////////////////
//CfgValueCont : container for ConfigValues
//////////////////////////////////////////////////////////////////////////////////////
class CfgValueCont
{
friend class XmlConfig;
private:
CfgValueCont();
void AddValue( std::string strKeyName, char* strAttributeString );
void AddValue( std::string strKeyName, Element& aEl );
size_t size(void){ return m_vReadCnfgValue.size(); }
void clear(void){ m_vReadCnfgValue.clear(); }
template<class T>bool GetValue( int iIndex, int iAttributeIndex, T&value, T& defaultVal )//for easy enumerating through loaded values
{
return m_vReadCnfgValue[iIndex].GetValue( iAttributeIndex, value, defaultVal );
}
template<class T>bool GetValue( int iIndex, std::string& strValueName, T&value, T& defaultVal )// true search -> by Name
{
assert(iIndex < m_vReadCnfgValue.size() );
return m_vReadCnfgValue[iIndex].GetValue( strValueName, value, defaultVal );
}
std::vector< ConfigValue > m_vReadCnfgValue;
};
//////////////////////////////////////////////////////////////////////////////////////
//XmlConfig : main Wrapper Class around ParamIO
//////////////////////////////////////////////////////////////////////////////////////
class XmlConfig
{
public:
XmlConfig();
XmlConfig( const char* filename );
void DefaultInit(void);//some default Initialisation stuff
virtual ~XmlConfig();
template<class T>bool read(const char *str, T &value, T& defaultVal) const
{
return m_ParamIO.read( str, value, defaultVal );
}
template<class T>bool write(const char *str, T& value)
{
return m_ParamIO.write( str, value );
}
void readFile(const char *filename);
void writeFile(const char *filename) const;
void readStream(std::istream &is);
void readBuffer( char* pstrBuffer );
void writeStream(std::ostream &os) const;
bool erase( char* pstrSubKey );
int erase( char* pstrSubKey, char* pstrAttributeMatchKey, ... );
ParamIO& GetParamIoRef(void){ return m_ParamIO; };
bool ReadSubtree( const char *strSubTree );
size_t ReadCurrentTree( void );//reads the current active Subtree
size_t GetReadValueCount(void){ return m_RedCnfgValues.size(); }
size_t hasSubNodes( char* pstrSubKey, std::string& strNodeName );//has the current extracted Tree a Sub - Node ??
bool enterSubTree( std::string& strSubTree );//enters the Subtree named in strSubTree, acoording to current Position
bool leaveSubTree(void);//leaves the current Subtree
template<class T>int AddAttributes( char* pstrKey, VAL_TYPE valTypeToAdd, char* strAttributeName, T& Attribute, char* pstrAttributeMatchKey, ... )
{
//Build the Search Kriteria vector
va_list marker;
va_start( marker, pstrAttributeMatchKey );
std::vector<string> vKeyString;
while( pstrAttributeMatchKey != 0 )
{
vKeyString.push_back( std::string( pstrAttributeMatchKey ) );
pstrAttributeMatchKey = va_arg( marker, char* );
}
va_end( marker );
std::stringstream ist;
ist << Attribute;
std::string strAtributeString = " ";//always start with a preceding space to avoid anger...
strAtributeString += XmlConfig::m_TypeDefinition.GetValTypePrefix( valTypeToAdd );
strAtributeString += string(strAttributeName);
strAtributeString += " = ";
strAtributeString += '"';
strAtributeString += ist.str();
strAtributeString += '"';
return m_ParamIO.addAttributes( pstrKey, vKeyString, strAtributeString );
}
int AddAttributeString( char* pstrKey, char* pstrAttributeString, char* pstrAttributeMatchKey, ... );
int RemoveAttributes( char* pstrKey, char* strAttributeName, char* pstrAttributeMatchKey, ... );
template<class T>bool GetValue( int iIndex, int iAttributeIndex, T&value, T defaultVal )//for easy enumerating through loaded values
{
return m_RedCnfgValues.GetValue( iIndex, iAttributeIndex, value, defaultVal );
}
template<class T>bool GetValue( int iIndex, std::string& strName, T&value, T defaultVal )//for easy enumerating through loaded values
{
return m_RedCnfgValues.GetValue( iIndex, strName, value, defaultVal );
}
static TypeDefine m_TypeDefinition;//The Definition Tabel of Known Types
void writeCompleteStream( std::ostream &os ) const;//writes a complete outputstream including the header
void SetHeader( char* pstrXmlVersion, char* pstrEncoding );
static std::string CheckStringForLineBreaks( const char* pstrInput );//inserts a \r\n after avery </> Tag, if there is none
static void RemoveString( std::string& strInput, std::string& strSignToRemove );//removes all occurences of strSignToRemove in strInput
private:
std::string m_strXmlVersion;
std::string m_strEncoding;
void WriteHeader( std::ostream &os ) const;//Writes the XML - File - Header : e.g.: <?xml version="1.0" encoding="ISO-8859-1"?>
size_t ExtractElements( XML_Node& aNode );
size_t ExtractNode( XML_Node& aNode );
ParamIO m_ParamIO;
ParamIO m_ActiveTree;
CfgValueCont m_RedCnfgValues;
};