// -*- C++ header-*-
//=============================================================================
/**
* @file config.h
*
* config.h,2005/04/19 slayer
*
* @author slayer <slay78@hotmail.com>
*/
//=============================================================================
#ifndef _config_h_
#define _config_h_
#include "stdafx.h"
#include <hash_map>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
using namespace stdext;
class _key;
typedef class _Value
{
friend class _ini;
public:
_Value(){};
~_Value(){};
_Value(const string& value):_value(value){};
inline _Value& operator=(const string& value){
_value=value; return *this;};
inline _Value& operator=(const int& value){
_caster.clear(); _caster << value;
_value = _caster.str(); return *this;};
inline _Value& operator=(const long& value){
_caster.clear(); _caster << value;
_value = _caster.str(); return *this;};
inline _Value& operator=(const double& value){
_caster.clear(); _caster << value;
_value = _caster.str(); return *this;};
inline _Value& operator=(const float& value){
_caster.clear(); _caster << value;
_value = _caster.str(); return *this;};
inline _Value& operator=(const char *value){
_caster.clear(); _caster << value;
_value = _caster.str(); return *this;};
inline operator string() const {return _value;};
inline operator int() const {return atoi(_value.c_str());};
inline operator long() const {return atol(_value.c_str());};
inline operator float() const
{return static_cast<float>(atof(_value.c_str()));};
inline operator double() const {return atof(_value.c_str());};
private:
string _value;
stringstream _caster;//for convert
}Value;
inline ostream& operator<<(ostream& o, const Value& v){
o << static_cast<string>(v); return o;};
typedef class _Key
{
typedef hash_map<string, Value> valueMap;
friend class _ini;
public:
_Key(){};
inline void clear(){_values.clear();};
inline Value& operator[](const string& key){return _values[key];};
inline _Key& operator+=(const _Key& k)
{
valueMap::const_iterator i;
for (i = k._values.begin(); i != k._values.end(); i++)
_values[i->first] = (string)i->second;
return *this;
};
private:
valueMap _values;
}Key;
typedef class _Section
{
typedef hash_map<string, Key> keyMap;
friend class _ini;
public:
_Section(){};
inline Key& operator[](const string& section){return _keys[section];};
inline void clear(){_keys.clear();};
inline _Section& operator+=(const _Section& s)
{
keyMap::const_iterator i;
for (i = s._keys.begin(); i != s._keys.end(); i++)
_keys[i->first] += i->second;
return *this;
};
private:
keyMap _keys;
}Section;
typedef class _ini
{
public:
_ini(const string& file):_file(file){};
_ini(){_file.clear();};
inline int load(Section& secs){return load(secs,_file);};
int load(Section& secs,const string& file)
{
ifstream f(file.c_str(),ios::in);
if(!f.is_open())return -1;
secs.clear();
string section,key,value;
string line;
while(!f.eof())
{
getline(f,line);
const char* s=line.c_str();
if(line.size()<3)continue;
line=line.substr(line.find_first_not_of(" /t"));
if(line.size()<3)continue;
if(is_comment(line))continue;
if(is_section(line,section))continue;
if(section.empty())continue; // unknow line
if(!parse_line(line,key,value))continue;
cout<<section<<","<<key<<","<<value<<","<<endl;
secs[section][key]=value;
}
return 0;
}
int save(Section& secs,const string& file)
{
ofstream f(file.c_str(),ios::trunc);
const _Section::keyMap& keys=secs._keys;
_Section::keyMap::const_iterator kit;
for(kit=keys.begin();kit!=keys.end();kit++)
{
f<<endl<<"["<<kit->first<<"]"<<endl;
const _Key::valueMap& values=kit->second._values;
_Key::valueMap::const_iterator vit;
for(vit=values.begin();vit!=values.end();vit++)
{
f<<vit->first<<"="<<vit->second<<endl;
}
}
return 0;
}
private:
bool parse_line(const string& line,string& key,string& value)
{
key.clear();value.clear();
size_t n=line.find_first_of('=');
if(n == string::npos)return false;
key = line.substr(0,n);
value =line.substr(n+1);
n = key.find_last_not_of(" /t");
key = key.substr(0,n+1);
n = value.find_first_not_of(" /t");
if(n == string::npos)return false;
value=value.substr(n);
n=value.find_last_not_of(" /t");
if(n == string::npos)return false;
value=value.substr(0,n+1);
if( ((n = value.find("/t#" )) != string::npos) ||
((n = value.find(" #" )) != string::npos) ||
((n = value.find("/t//" )) != string::npos) ||
((n = value.find(" //" )) != string::npos))
{
value = value.substr(0, n);
}
n=value.find_last_not_of(" /t");
if(n == string::npos)return false;
value=value.substr(0,n+1);
return true;
}
inline bool is_comment(const string& line){
return line[0]=='#' || (line[0]=='/' && line[1]=='/');}
inline bool is_section(const string& line, string& sec)
{
if(line[0]!='[' || line[1]==']')return false;
size_t n=line.find_first_of(']');
if(n!=string::npos)
sec=line.substr(1,n-1);
return true;
}
private:
string _file;
}Ini;
#endif //_config_h_
///test.cpp/
#include "config.h"
int _tmain(int argc, _TCHAR* argv[])
{
Ini ini;
Section s;
string str="123";
s["system"]["count"]=123;
s["system"]["ip1"]="127.0.0.1";
cout<<s["system"]["ip1"]<<endl;
Section s1;
s1["system"]["123"]="aaa";
s1["abc"]["123"]="aaa";
s+=s1;//merge
ini.save(s,"save.ini");
str=s["system"]["ip1"];
cout<<str<<endl;
s["system"]["double"]=(double)12.311111111111111;
str=s["system"]["int"];
cout<<str<<endl;
float f= s["system"]["int"];
cout << f <<endl;
str=s["system"]["count"];
str=s["system"]["ip1"];
s.clear();
str=s["system"]["count"];
str=s["system"]["ip1"];
ini.load(s,"test.ini");
return 0;
}
test.ini/
#test
[sec1]
value1 = a string value #xxxxxxxxxxxxxxxxxxxx
value 2 = 123 //
value_3 = abc
[system]
ip1 = 127.0.0.1
port1=8000
#thread count
threadcount = 50
[
[]
[1][]
123=3221