diff C++/Parser.cpp @ 203:1ffe6d4937b7

Update parser for more convenience and types security #224
author David Demelier <markand@malikania.fr>
date Thu, 23 Jan 2014 14:56:50 +0100
parents 600754c27c88
children 9f22ce5f1b39 706f861c4c6d
line wrap: on
line diff
--- a/C++/Parser.cpp	Sat Jan 04 18:02:06 2014 +0100
+++ b/C++/Parser.cpp	Thu Jan 23 14:56:50 2014 +0100
@@ -16,22 +16,14 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cstring>
+#include <cerrno>
 #include <iostream>
 #include <fstream>
 
 #include "Parser.h"
 
 /* --------------------------------------------------------
- * Option public members
- * -------------------------------------------------------- */
-
-bool operator==(const Option &o1, const Option &o2)
-{
-	return o1.m_key == o2.m_key &&
-	    o1.m_value == o2.m_value;
-}
-
-/* --------------------------------------------------------
  * Section public members
  * -------------------------------------------------------- */
 
@@ -40,108 +32,50 @@
 {
 }
 
+Section::Section(const std::string &name)
+	: m_name(name)
+	, m_allowed(true)
+{
+
+}
+
 const std::string &Section::getName() const
 {
 	return m_name;
 }
 
-const std::string Section::findOption(const std::string &name) const
+bool Section::hasOption(const std::string &name) const
 {
-	std::string ret;
-
-	for (const Option &o : m_options)
-		if (o.m_key == name) {
-			ret = o.m_value;
-			break;
-		}
-
-	return ret;
+	return m_options.count(name) >= 1;
 }
 
-template <>
-bool Section::getValue(const std::string &name) const
+Section::Map::iterator Section::begin()
 {
-	bool result = false;
-
-	if (hasOption(name)) {
-		std::string value = findOption(name);
-
-		if (value == "yes" || value == "true"|| value == "1")
-			result = true;
-		else if (value == "no" || value == "false" || value == "0")
-			result = false;
-	}
-
-	return result;
+	return m_options.begin();
 }
 
-template <>
-int Section::getValue(const std::string &name) const
+Section::Map::const_iterator Section::cbegin() const
 {
-	int result = -1;
-
-	if (hasOption(name))
-		result = atoi(findOption(name).c_str());
-
-	return result;
+	return m_options.cbegin();
 }
 
-template <>
-std::string Section::getValue(const std::string &name) const
+Section::Map::iterator Section::end()
 {
-	std::string result;
-
-	if (hasOption(name))
-		result = findOption(name);
-
-	return result;
-}
-
-const std::vector<Option> &Section::getOptions() const
-{
-	return m_options;
+	return m_options.end();
 }
 
-bool Section::hasOption(const std::string &name) const
+Section::Map::const_iterator Section::cend() const
 {
-	for (const Option &o : m_options)
-		if (o.m_key == name)
-			return true;
-
-	return false;
-}
-
-bool operator==(const Section &s1, const Section &s2)
-{
-	if (s1.m_name != s2.m_name)	
-		return false;
-
-	return s1.m_options == s2.m_options;
+	return m_options.end();
 }
 
 /* --------------------------------------------------------
  * Parser private members
  * -------------------------------------------------------- */
 
-void Parser::addSection(const std::string &name)
-{
-	Section section;
-
-	section.m_name = name;
-	section.m_allowed = true;
-
-	m_sections.push_back(section);
-}
-
 void Parser::addOption(const std::string &key, const std::string &value)
 {
-	Option option;
-	Section &current = m_sections.back();
-
-	option.m_key = key;
-	option.m_value = value;
-
-	current.m_options.push_back(option);
+	m_sections.back().m_options.insert(std::make_pair(key, value));
 }
 
 void Parser::readSection(int lineno, const std::string &line)
@@ -150,7 +84,7 @@
 
 	if ((end = line.find_first_of(']')) != std::string::npos) {
 		if (end > 1) {
-			std::string name = line.substr(1, end - 1);
+			auto name = line.substr(1, end - 1);
 
 			/*
 			 * Check if we can add a section, if redefinition is
@@ -162,8 +96,9 @@
 				if (!(m_tuning & DisableVerbosity))
 					log(lineno, name, "redefinition not allowed");
 				m_sections.back().m_allowed = false;
-			} else
-				addSection(name);
+			} else {
+				m_sections.push_back(Section(name));
+			}
 		} else if (!(m_tuning & DisableVerbosity)) {
 			/*
 			 * Do not add options at this step because it will
@@ -177,9 +112,9 @@
 
 void Parser::readOption(int lineno, const std::string &line)
 {
+	auto &current = m_sections.back();
 	size_t epos;
 	std::string key, value;
-	Section &current = m_sections.back();
 
 	// Error on last section?
 	if (!current.m_allowed) {
@@ -267,6 +202,22 @@
 
 const char Parser::DEFAULT_COMMENT_CHAR = '#';
 
+void Parser::open()
+{
+	std::ifstream file;
+	std::string line;
+	int lineno = 1;
+
+	file.open(m_path.c_str());
+	if (!file.is_open())
+		throw std::runtime_error(m_path + std::string(std::strerror(errno)));
+
+	while (std::getline(file, line))
+		readLine(lineno++, line);
+
+	file.close();
+}
+
 Parser::Parser()
 {
 }
@@ -276,60 +227,48 @@
 	, m_tuning(tuning)
 	, m_commentChar(commentToken)
 {
-	Section root;
+	Section s("");
 
-	// Add a default root section
-	root.m_name = "";
-	root.m_allowed = (tuning & DisableRootSection) ? false : true;
+	s.m_allowed = (tuning & DisableRootSection) ? false : true;
 
-	m_sections.push_back(root);
+	m_sections.push_back(s);
+	open();
 }
 
 Parser::~Parser()
 {
 }
 
-bool Parser::open()
+Parser::List::iterator Parser::begin()
 {
-	std::ifstream file;
-	std::string line;
-	int lineno = 1;
-
-	file.open(m_path.c_str());
-	if (!file.is_open()) {
-		m_error = "could not open file " + m_path;	// XXX: add a real error
-		return false;
-	}
-
-	// Avoid use of C getline
-	while (std::getline(file, line))
-		readLine(lineno++, line);
-
-	file.close();
-
-	return true;
+	return m_sections.begin();
 }
 
-const std::string &Parser::getError() const
+Parser::List::const_iterator Parser::cbegin() const
 {
-	return m_error;
+	return m_sections.cbegin();
 }
 
-const std::vector<Section> &Parser::getSections() const
+Parser::List::iterator Parser::end()
 {
-	return m_sections;
+	return m_sections.end();
+}
+
+Parser::List::const_iterator Parser::cend() const
+{
+	return m_sections.end();
 }
 
 void Parser::findSections(const std::string &name, FindFunc func) const
 {
-	for (const Section &s : m_sections)
+	for (const auto &s : m_sections)
 		if (s.m_name == name)
 			func(s);
 }
 
 bool Parser::hasSection(const std::string &name) const
 {
-	for (const Section &s : m_sections)
+	for (const auto &s : m_sections)
 		if (s.m_name == name)
 			return true;
 
@@ -338,34 +277,14 @@
 
 const Section &Parser::getSection(const std::string &name) const
 {
-	for (const Section &s : m_sections)
+	for (const auto &s : m_sections)
 		if (s.m_name == name)
 			return s;
 
-	throw NotFoundException(name);
+	throw std::out_of_range(name + " not found");
 }
 
 void Parser::log(int number, const std::string &, const std::string &message)
 {
 	std::cout << "line " << number << ": " << message << std::endl;
 }
-
-void Parser::dump()
-{
-	for (auto s : m_sections) {
-		dumpSection(s);
-
-		for (auto o : s.m_options)
-			dumpOption(o);
-	}
-}
-
-void Parser::dumpSection(const Section &section)
-{
-	std::cout << "Section " << section.m_name << std::endl;
-}
-
-void Parser::dumpOption(const Option &option)
-{
-	std::cout << "    Option " << option.m_key << " = " << option.m_value << std::endl;
-}