Ejemplo n.º 1
0
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;
}