int IniParser::parseConfigFile (std::ifstream *configStream, const char *filename, bool parseFullLine) { int ln = 0; IniSection *sect = NULL; std::string line; while (!configStream->fail ()) { getline (*configStream, line); ln++; if (configStream->fail ()) break; std::string::iterator top = line.begin (); while (isspace (*top) && top != line.end ()) top++; // ignore blank lines and comments if (top == line.end () || *top == ';' || *top == '#') continue; // start new section.. if (*top == '[') { size_t el = line.find (']'); if (el == std::string::npos) { logStream (MESSAGE_ERROR) << "cannot find end delimiter for section '" << line << "' on line " << ln << " infile " << filename << "." << sendLog; return -1; } if (sect) push_back (sect); sect = new IniSection (line.substr (top - line.begin () + 1, el-1).c_str ()); } else { if (!sect) { if (!addDefaultSection) { logStream (MESSAGE_ERROR) << "value without section on line " << ln << ": " << line << sendLog; return -1; } sect = new IniSection (""); } // now create value.. enum { NAME, SUFF, VAL, VAL_QUT, VAL_END, LINE_END} pstate = NAME; std::string valName; std::string valSuffix; std::string val; std::string comment; std::string::iterator es = top; for (; es != line.end () && pstate != LINE_END;) { switch (pstate) { case NAME: case SUFF: if (*es == '.') { if (pstate == SUFF) valName += '.'; valName += line.substr (top - line.begin (), es - top); pstate = SUFF; top = es + 1; } else if (*es == '=' || isspace (*es)) { if (pstate == SUFF) valSuffix = line.substr (top - line.begin (), es - top); else valName = line.substr (top - line.begin (), es - top); pstate = VAL; while (*es != '=' && es != line.end ()) es++; es++; while (es != line.end () && isspace (*es)) es++; if (*es == '"') { pstate = VAL_QUT; top = es + 1; } else { top = es; } } break; case VAL: if (isspace (*es)) { pstate = VAL_END; if (parseFullLine) { es = line.end (); while (isspace (*es)) es--; } val = line.substr (top - line.begin (), es - top); } break; case VAL_QUT: if (*es == '"') { pstate = VAL_END; if (top == es) val = std::string (""); else val = line.substr (top - line.begin (), es - top); } break; case VAL_END: if (*es == ';' || *es == '#') { do { es++; } while (es != line.end () && isspace (*es)); if (es != line.end ()) { comment = line.substr (es - line.begin ()); es = line.end (); } pstate = LINE_END; } break; case LINE_END: break; } if (es != line.end ()) es++; } if (pstate == VAL_QUT) { logStream (MESSAGE_ERROR) << "missing \" on line " << ln << " of file " << filename << sendLog; return -1; } if (pstate == VAL) { val = line.substr (top - line.begin (), es - top); pstate = VAL_END; } if (!(pstate == VAL_END || pstate == LINE_END)) { logStream (MESSAGE_ERROR) << "invalid configuration line " << ln << " of file " << filename << sendLog; return -1; } #ifdef DEBUG_EXTRA std::cout << "Pushing " << valName << " " << valSuffix << " " << val << std::endl; #endif /* DEBUG_EXTRA */ sect->push_back (IniValue (valName, valSuffix, val, comment)); if (valName == "blocked_by") { sect->createBlockedBy (val); } } } if (sect) push_back (sect); return 0; }