-
Notifications
You must be signed in to change notification settings - Fork 2
/
config.cpp
157 lines (125 loc) · 3.5 KB
/
config.cpp
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Config.cpp
#include "config.h"
using namespace std;
Config::Config( string filename, string delimiter,
string comment )
: m_Delimiter(delimiter), m_Comment(comment)
{
// Construct a Config, getting keys and values from given file
std::ifstream in( filename.c_str() );
if( !in ) throw File_not_found( filename );
in >> (*this);
}
Config::Config()
: m_Delimiter( string(1,'=') ), m_Comment( string(1,'#') )
{
// Construct a Config without a file; empty
}
bool Config::KeyExists( const string& key ) const
{
// Indicate whether key is found
mapci p = m_Contents.find( key );
return ( p != m_Contents.end() );
}
/* static */
void Config::Trim( string& inout_s )
{
// Remove leading and trailing whitespace
static const char whitespace[] = " \n\t\v\r\f";
inout_s.erase( 0, inout_s.find_first_not_of(whitespace) );
inout_s.erase( inout_s.find_last_not_of(whitespace) + 1U );
}
std::ostream& operator<<( std::ostream& os, const Config& cf )
{
// Save a Config to os
for( Config::mapci p = cf.m_Contents.begin();
p != cf.m_Contents.end();
++p )
{
os << p->first << " " << cf.m_Delimiter << " ";
os << p->second << std::endl;
}
return os;
}
void Config::Remove( const string& key )
{
// Remove key and its value
m_Contents.erase( m_Contents.find( key ) );
return;
}
std::istream& operator>>( std::istream& is, Config& cf )
{
// Load a Config from is
// Read in keys and values, keeping internal whitespace
typedef string::size_type pos;
const string& delim = cf.m_Delimiter; // separator
const string& comm = cf.m_Comment; // comment
const pos skip = delim.length(); // length of separator
string nextline = ""; // might need to read ahead to see where value ends
while( is || nextline.length() > 0 )
{
// Read an entire line at a time
string line;
if( nextline.length() > 0 )
{
line = nextline; // we read ahead; use it now
nextline = "";
}
else
{
std::getline( is, line );
}
// Ignore comments
line = line.substr( 0, line.find(comm) );
// Parse the line if it contains a delimiter
pos delimPos = line.find( delim );
if( delimPos < string::npos )
{
// Extract the key
string key = line.substr( 0, delimPos );
line.replace( 0, delimPos+skip, "" );
// See if value continues on the next line
// Stop at blank line, next line with a key, end of stream,
// or end of file sentry
bool terminate = false;
while( !terminate && is )
{
std::getline( is, nextline );
terminate = true;
string nlcopy = nextline;
Config::Trim(nlcopy);
if( nlcopy == "" ) continue;
nextline = nextline.substr( 0, nextline.find(comm) );
if( nextline.find(delim) != string::npos )
continue;
nlcopy = nextline;
Config::Trim(nlcopy);
if( nlcopy != "" ) line += "\n";
line += nextline;
terminate = false;
}
// Store key and value
Config::Trim(key);
Config::Trim(line);
cf.m_Contents[key] = line; // overwrites if key is repeated
}
}
return is;
}
bool Config::FileExist(std::string filename)
{
bool exist= false;
std::ifstream in( filename.c_str() );
if( in )
exist = true;
return exist;
}
void Config::ReadFile( string filename, string delimiter,
string comment )
{
m_Delimiter = delimiter;
m_Comment = comment;
std::ifstream in( filename.c_str() );
if( !in ) throw File_not_found( filename );
in >> (*this);
}