Mercurial > code
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_