#include <vector>
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
// trim from start
static inline std::string <rim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int>(isspace))));
return s;
}
// trim from end
static inline std::string &rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int>(isspace))).base(), s.end());
return s;
}
// trim from both ends
static inline std::string &trim(std::string &s) {
return ltrim(rtrim(s));
}
// split string into (multiple) parts
void split( vector<string> & theStringVector, // Altered/returned value
const string & theString,
const string & theDelimiter)
{
_ASSERT(theDelimiter.size() > 0);
size_t start = 0, end = 0;
while (end != string::npos) {
end = theString.find( theDelimiter, start);
// If at end, use length=maxLength. Else use length=end-start.
theStringVector.push_back(theString.substr(start,
(end == string::npos) ? string::npos : end - start));
// If at end, use start=maxSize. Else use start=end+delimiter.
start = ( ( end > (string::npos - theDelimiter.size()) )
? string::npos : end + theDelimiter.size());
}
}
// THE function ;)
int parseLine (
const std::string &s, ///< (in) input string
std::string &key, ///< (out) receives clean 'key'
std::string &val, ///< (out) receives clean 'value'
std::string &com = string() ///< (out,optional) receives clean 'comment'
)
{
vector<string> v, v2;
int num = 0;
key.erase(); val.erase(); com.erase();
// 'remove' comment
split(v, s, ";");
if (v.size()) {
// Handle 'pre-comment' part (v[0])
split(v2, trim(v[0]), "=");
if (v2.size())
{
key = trim(v2[0]);
if (v2.size() == 2) {
val = trim(v2[1]);
}
}
// Handle 'comment' parts (v[1],...,v[n])
if (v.size() >= 2)
{
com = ltrim(v[1]);
for (size_t i = 2; i < v.size(); i++) {
(com += ";") += v[i];
}
trim(com);
}
}
if (!key.empty()) num |= 0x01;
if (!val.empty()) num |= 0x02;
if (!com.empty()) num |= 0x04;
return num;
}
int main(int argc, char* argv[])
{
// test-list
const char* lst[] = {
"name = Hello World ; this is a comment with a = and a ; symbol ",
"a",
"this should not work = but it does ;)",
"b\t\r\n\t ", // multi-line should not be fed, but should also create no errors ;)
"a\t \t o",
"syntax-error ; with = in comment",
"; name = Hello World",
"name = Hello World",
// Block
"WHATEVER",
"END",
NULL // end-of-list marker
};
string k, v, c;
for (int i=0; lst[i]; i++) {
int n = parseLine(lst[i], k, v, c);
printf( "line %2d : '%s'\n", i, lst[i]);
if (n & 1) printf(" key : '%s'\n", k.c_str());
if (n & 2) printf(" value : '%s'\n", v.c_str());
if (n & 4) printf(" comment: '%s'\n", c.c_str());
printf( "\n");
}
return 0;
}