-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathINIReader.cc
133 lines (119 loc) · 4.21 KB
/
INIReader.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Code for INIReader class and helper functions:
#include "INIReader.hh"
#include "ini.hh"
#include <algorithm>
#include <iostream>
using std::string;
using std::vector;
using std::map;
using namespace INIParser;
// Ctor, read complete ini file here using the built-in handler:
INIReader::INIReader( const string& filename, bool optlower ) :
_optlower( optlower ) {
_error= ini_parse( filename.c_str(), valueHandler, this );
}
// Return error status after reading:
int INIReader::parseError() const {
return _error;
}
// Dump parsed data:
void INIReader::dump() const {
for( map<string,map<string,string> >::const_iterator sectionIter=
_sectionMap.begin(); sectionIter != _sectionMap.end();
sectionIter++ ) {
dumpSection( sectionIter->first );
}
return;
}
void INIReader::dumpSection( const string& section ) const {
std::cout << "dump section " << section << std::endl;
vector<string> names= getNames( section );
for( size_t i= 0; i < names.size(); i++ ) {
string name= names[i];
std::cout << name << " " << get( section, name, "" ) << std::endl;
}
return;
}
// Get value(s) as string, return default if no matching entry
// in map:
string INIReader::get( const string& section, const string& name,
const string& default_value ) const {
string result= default_value;
map<string,map<string,string> >::const_iterator sectionIter=
_sectionMap.find( section );
if( sectionIter != _sectionMap.end() ) {
const map<string,string> nameMap= sectionIter->second;
map<string,string>::const_iterator mapIter= nameMap.find( name );
if( mapIter != nameMap.end() ) result= mapIter->second;
}
return result;
}
// Get all names in a section in a sorted vector, returns
// empty vector when no section map is found or when it is empty:
vector<string> INIReader::getNames( const string& section ) const {
vector<string> names;
map<string,map<string,string> >::const_iterator sectionIter=
_sectionMap.find( section );
if( sectionIter != _sectionMap.end() ) {
const map<string,string> nameMap= sectionIter->second;
for( map<string,string>::const_iterator nameIter= nameMap.begin();
nameIter != nameMap.end(); nameIter++ ) {
names.push_back( nameIter->first );
}
std::sort( names.begin(), names.end() );
}
return names;
}
// A la python ConfigParser: transform option to lowercase by default:
string INIReader::optionxform( const char* option ) const {
string str( option );
if( _optlower ) std::transform( str.begin(), str.end(),
str.begin(), ::tolower );
return str;
}
// Handler as expected by ini.cc, it is called for each parsed line.
// Store value with keys <section> and <key> in map of maps:
int INIReader::valueHandler( void* user, const char* section, const char* key,
const char* value ) {
INIReader* reader= (INIReader*) user;
string keystr= reader->optionxform( key );
string valuestr= reader->optionxform( value );
if( reader->_sectionMap[section][keystr].size() > 0 ) {
reader->_sectionMap[section][keystr]+= "\n";
}
reader->_sectionMap[section][keystr]+= valuestr;
return 1;
}
// Get value string as vector of tokens separated by isspace:
vector<string> INIParser::getTokens( const string& valueStr ) {
string token;
vector<string> tokens;
for( string::const_iterator iter= valueStr.begin();
iter != valueStr.end(); iter++ ) {
const char c= *iter;
if( isspace( c ) ) {
if( token.length() > 0 ) {
tokens.push_back( token );
token.clear();
}
}
else {
token+= c;
}
}
if( token.length() > 0 ) tokens.push_back( token );
return tokens;
}
// Get bool value using specialised template function:
template <>
bool INIParser::stringToType<bool>( const string& text,
bool default_value ) {
string valstr= text;
std::transform( valstr.begin(), valstr.end(), valstr.begin(), ::tolower );
bool result= default_value;
if( valstr == "true" || valstr == "yes" ||
valstr == "on" || valstr == "1" ) result= true;
else if( valstr == "false" || valstr == "no" ||
valstr == "off" || valstr == "0" ) result= false;
return result;
}