diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9da8cb6..269da2c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,7 @@ add_executable(${PROJECT_NAME} curl_wrapper.cpp index_response.cpp pastie_response.cpp + ini_file.cpp ) target_include_directories(${PROJECT_NAME} SYSTEM diff --git a/src/ini_file.cpp b/src/ini_file.cpp new file mode 100644 index 0000000..77d4874 --- /dev/null +++ b/src/ini_file.cpp @@ -0,0 +1,139 @@ +/* Copyright 2017, Michele Santullo + * This file is part of "tawashi". + * + * "tawashi" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "tawashi" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "tawashi". If not, see . + */ + +#include "ini_file.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace tawashi { + namespace { + typedef std::string string_type; + + template + struct IniGrammar : boost::spirit::qi::grammar { + explicit IniGrammar (const std::string* parString); + boost::spirit::qi::rule start; + boost::spirit::qi::rule section_head; + boost::spirit::qi::rule key; + boost::spirit::qi::rule key_value; + boost::spirit::qi::rule key_values; + const std::string* m_master_string; + Iterator m_begin; + }; + + template + IniGrammar::IniGrammar (const std::string* parString) : + IniGrammar::base_type(start), + m_master_string(parString), + m_begin(m_master_string->cbegin()) + { + assert(m_master_string); + namespace px = boost::phoenix; + using boost::spirit::ascii::space; + using boost::spirit::qi::_val; + using boost::spirit::_1; + using boost::spirit::qi::char_; + using boost::spirit::qi::eol; + typedef IniFile::KeyValueMapType refpair; + + section_head = '[' >> +(char_ - ']') >> ']' >> eol; + key = +(char_ - '='); + key_value = key >> '=' >> *(char_ - eol) >> eol; + key_values = *key_value; + start = *(section_head >> key_values); + + //start %= *(section_head >> key_values); + //key_values %= *key_value; + //key_value = key[px::bind(&refpair::first, _val) = _1] >> '=' >> + // raw[*char_][px::bind(&refpair::second, _val) = px::bind( + // &string_ref::substr, + // px::construct(px::ref(*m_master_string)), + // px::begin(_1) - px::ref(m_begin), px::size(_1) + //)]; + //key = as_string[+(char_ - '=')][_val = px::bind( + // &string_ref::substr, + // px::construct(px::ref(*m_master_string)), + // px::begin(_1) - px::ref(m_begin), px::size(_1) + //)]; + //section_head = '[' >> as_string[(+char_ - ']')][_val = px::bind( + // &string_ref::substr, + // px::construct(px::ref(*m_master_string)), + // px::begin(_1) - px::ref(m_begin), px::size(_1) + //)] >> ']'; + } + + IniFile::IniMapType parse_ini (const std::string* parIni) { + using boost::spirit::qi::blank; + using boost::spirit::qi::blank_type; + + IniGrammar gramm(parIni); + IniFile::IniMapType result; + + std::string::const_iterator start_it = parIni->cbegin(); + /*const bool parse_ok =*/ boost::spirit::qi::phrase_parse( + start_it, + parIni->cend(), + gramm, + blank, + result + ); + + //assert(parse_ok and (parIni->cend() == start_it)); + return result; + } + } //unnamed namespace + + IniFile::IniFile (std::istream_iterator parInputFrom, std::istream_iterator parInputEnd) : + IniFile(std::string(parInputFrom, parInputEnd)) + { + } + + IniFile::IniFile (std::string&& parIniData) : + m_raw_ini(std::move(parIniData)), + m_map(parse_ini(&m_raw_ini)) + { + } + + IniFile::IniFile (IniFile&& parOther) { + auto* const old_data_ptr = parOther.m_raw_ini.data(); + m_raw_ini = std::move(parOther.m_raw_ini); + if (m_raw_ini.data() == old_data_ptr) + m_map = std::move(parOther.m_map); + else + m_map = parse_ini(&m_raw_ini); + } + + IniFile::~IniFile() noexcept { + } +} //namespace tawashi diff --git a/src/ini_file.hpp b/src/ini_file.hpp new file mode 100644 index 0000000..004fbf9 --- /dev/null +++ b/src/ini_file.hpp @@ -0,0 +1,45 @@ +/* Copyright 2017, Michele Santullo + * This file is part of "tawashi". + * + * "tawashi" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "tawashi" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "tawashi". If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace tawashi { + class IniFile { + public: + typedef boost::container::flat_map KeyValueMapType; + typedef boost::container::flat_map IniMapType; + + IniFile (std::istream_iterator parInputFrom, std::istream_iterator parInputEnd); + explicit IniFile (std::string&& parIniData); + IniFile (IniFile&& parOther); + IniFile (const IniFile& parOther) = delete; + ~IniFile() noexcept; + + IniFile& operator== (IniFile&&) = delete; + IniFile& operator== (const IniFile&) = delete; + + const IniMapType& parsed() const { return m_map; } + + private: + std::string m_raw_ini; + IniMapType m_map; + }; +} //namespace tawashi