diff C++/Ini.h @ 325:d52a69f9f029

Add Ini, brand new replacement for Parser
author David Demelier <markand@malikania.fr>
date Sat, 28 Feb 2015 18:53:27 +0100
parents
children 78e8f9a3b233
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/Ini.h	Sat Feb 28 18:53:27 2015 +0100
@@ -0,0 +1,255 @@
+/*
+ * Ini.h -- .ini file parsing
+ *
+ * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _INI_H_
+#define _INI_H_
+
+#include <algorithm>
+#include <deque>
+#include <fstream>
+#include <istream>
+#include <stdexcept>
+#include <string>
+
+/**
+ * @class IniOption
+ * @brief Option definition
+ */
+class IniOption {
+private:
+	std::string m_key;
+	std::string m_value;
+
+public:
+	inline IniOption(std::string key, std::string value)
+		: m_key(std::move(key))
+		, m_value(std::move(value))
+	{
+	}
+
+	inline const std::string &key() const noexcept
+	{
+		return m_key;
+	}
+
+	inline const std::string &value() const noexcept
+	{
+		return m_value;
+	}
+};
+
+/**
+ * @class IniSection
+ * @brief Section that contains one or more options
+ */
+class IniSection {
+private:
+	std::string m_key;
+	std::deque<IniOption> m_options;
+
+	template <typename T>
+	T find(const std::string &key) const
+	{
+		auto it = std::find_if(m_options.begin(), m_options.end(), [&] (const IniOption &o) {
+			return o.key() == key;
+		});
+
+		if (it == m_options.end())
+			throw std::out_of_range("option " + key + " not found");
+
+		return const_cast<T>(*it);
+	}
+
+public:
+	IniSection() = default;
+
+	inline IniSection(std::string key, std::deque<IniOption> options = {})
+		: m_key(std::move(key))
+		, m_options(std::move(options))
+	{
+	}
+
+	inline const std::string &key() const noexcept
+	{
+		return m_key;
+	}
+
+	inline auto begin() noexcept
+	{
+		return m_options.begin();
+	}
+
+	inline auto begin() const noexcept
+	{
+		return m_options.begin();
+	}
+
+	inline auto cbegin() const noexcept
+	{
+		return m_options.cbegin();
+	}
+
+	inline auto end() noexcept
+	{
+		return m_options.end();
+	}
+
+	inline auto end() const noexcept
+	{
+		return m_options.end();
+	}
+
+	inline auto cend() const noexcept
+	{
+		return m_options.cend();
+	}
+
+	inline void push_back(IniOption option)
+	{
+		m_options.push_back(std::move(option));
+	}
+
+	inline void push_front(IniOption option)
+	{
+		m_options.push_front(std::move(option));
+	}
+
+	inline unsigned size() const noexcept
+	{
+		return m_options.size();
+	}
+
+	inline IniOption &operator[](int index) noexcept
+	{
+		return m_options[index];
+	}
+
+	inline const IniOption &operator[](int index) const noexcept
+	{
+		return m_options[index];
+	}
+
+	inline IniOption &operator[](const std::string &key)
+	{
+		return find<IniOption &>(key);
+	}
+
+	inline const IniOption &operator[](const std::string &key) const
+	{
+		return find<const IniOption &>(key);
+	}
+};
+
+/**
+ * @class Ini
+ * @brief Ini config file loader
+ */
+class Ini {
+private:
+	std::deque<IniSection> m_sections;
+
+	template <typename T>
+	T find(const std::string &key) const
+	{
+		auto it = std::find_if(m_sections.begin(), m_sections.end(), [&] (const IniSection &s) {
+			return s.key() == key;
+		});
+
+		if (it == m_sections.end())
+			throw std::out_of_range("section " + key + " not found");
+
+		return const_cast<T>(*it);
+	}
+
+public:
+	Ini() = default;
+
+	Ini(std::istream &stream);
+
+	inline Ini(std::istream &&stream)
+		: Ini(stream)
+	{
+	}
+
+	inline auto begin() noexcept
+	{
+		return m_sections.begin();
+	}
+
+	inline auto begin() const noexcept
+	{
+		return m_sections.begin();
+	}
+
+	inline auto cbegin() const noexcept
+	{
+		return m_sections.cbegin();
+	}
+
+	inline auto end() noexcept
+	{
+		return m_sections.end();
+	}
+
+	inline auto end() const noexcept
+	{
+		return m_sections.end();
+	}
+
+	inline auto cend() const noexcept
+	{
+		return m_sections.cend();
+	}
+
+	inline unsigned size() const noexcept
+	{
+		return m_sections.size();
+	}
+
+	inline void push_back(IniSection section)
+	{
+		m_sections.push_back(std::move(section));
+	}
+
+	inline void push_front(IniSection section)
+	{
+		m_sections.push_front(std::move(section));
+	}
+
+	inline IniSection &operator[](int index) noexcept
+	{
+		return m_sections[index];
+	}
+
+	inline const IniSection &operator[](int index) const noexcept
+	{
+		return m_sections[index];
+	}
+
+	inline IniSection &operator[](const std::string &key)
+	{
+		return find<IniSection &>(key);
+	}
+
+	inline const IniSection &operator[](const std::string &key) const
+	{
+		return find<IniSection &>(key);
+	}
+};
+
+#endif // !_INI_H_