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
|
#include "Config.h"
#include <fstream>
#include "Assert.h"
namespace LibUtil
{
Config::Config(const String& delimiter_, const String& comment_, const String& sentry_)
: mDelimiter(delimiter_), mComment(comment_), mSentry(sentry_)
{}
Config::Config(const Config& config_)
: StringMap(config_)
{
mDelimiter = config_.mDelimiter;
mComment = config_.mComment;
mSentry = config_.mSentry;
}
Config::~Config()
{}
Config* Config::clone() const
{
return new Config(*this);
}
void Config::readFile(const String& filename_)
{
std::ifstream fin(filename_.c_str());
ASSERT(fin, "File not found: " + filename_);
fin >> (*this);
return;
}
void Config::readString(const String& str_)
{
String newString = str_;
newString.substitute(";", "\n");
std::istringstream iss(newString, std::istringstream::in);
iss >> (*this);
}
std::ostream& operator<<(std::ostream& ost_, const Config& config_)
{
Config::ConstIterator it;
for(it = config_.begin(); it != config_.end(); it++)
{
ost_ << it->first << " " << config_.mDelimiter << " ";
ost_ << it->second << std::endl;
}
return ost_;
}
std::istream& operator>>(std::istream& ist_, Config& config_)
{
// Set a Config from ist_
// Read in keys and values, keeping internal whitespace
typedef String::size_type pos;
const String& delim = config_.mDelimiter; // separator
const String& comm = config_.mComment; // comment
const String& sentry = config_.mSentry; // end of file sentry
const pos skip = delim.length(); // length of separator
String nextline = ""; // might need to read ahead to see where value ends
while(ist_ || 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(ist_, line);
safeGetline(ist_, line);
}
// Ignore comments and the spaces on both ends
line = line.substr(0, line.find(comm));
line.trim();
// Check for end of file sentry
if((sentry != "") && (line.find(sentry) != String::npos)) return ist_;
if(line.length() == 0)
continue;
// Parse the line if it contains a delimiter
pos delimPos = line.find(delim);
ASSERT((delimPos < String::npos), "Invalid config line: '" + line + "'");
// 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 && ist_)
{
if(line.at(line.size() - 1) == '\\')
line.erase(line.size() - 1);
else
break;
//std::getline(ist_, nextline);
safeGetline(ist_, nextline);
terminate = true;
String nlcopy = nextline;
nlcopy.trim();
if(nlcopy == "") continue;
nextline = nextline.substr(0, nextline.find(comm));
//if(nextline.find(delim) != String::npos)
// continue;
if((sentry != "") && (nextline.find(sentry) != String::npos))
continue;
//nlcopy = nextline;
//nlcopy.trim();
//if(nlcopy != "") line += "\n";
line += nextline;
nextline = "";
terminate = false;
}
// Store key and value
key.trim();
line.trim();
config_.set(key, line); // overwrites if key is repeated
}
return ist_;
}
}
|