Line data Source code
1 : /* 2 : * Copyright (c) 2017 Sebastian Weber, Henri Menke. All rights reserved. 3 : * 4 : * This file is part of the pairinteraction library. 5 : * 6 : * The pairinteraction library is free software: you can redistribute it and/or modify 7 : * it under the terms of the GNU Lesser General Public License as published by 8 : * the Free Software Foundation, either version 3 of the License, or 9 : * (at your option) any later version. 10 : * 11 : * The pairinteraction library is distributed in the hope that it will be useful, 12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 : * GNU Lesser General Public License for more details. 15 : * 16 : * You should have received a copy of the GNU Lesser General Public License 17 : * along with the pairinteraction library. If not, see <http://www.gnu.org/licenses/>. 18 : */ 19 : 20 : #ifndef CONF_PARSER_H 21 : #define CONF_PARSER_H 22 : 23 : #include <map> 24 : #include <sstream> 25 : #include <string> 26 : 27 : /** \brief %Configuration storage 28 : * 29 : * This class stores the system configuration. In essence it is a 30 : * wrapper around a `std::map` which `std::string` key and 31 : * `Configuration::value` value. The wrapped value class has some 32 : * advanced features which make it better than a pure `std::string` 33 : * value. 34 : */ 35 : class Configuration { 36 : private: 37 : class value { 38 : std::string m_value; 39 : 40 : public: 41 500 : value() = default; 42 : 43 2873 : std::string const str() const { return m_value; } 44 : 45 5 : bool operator==(value const &rhs) const { return this->m_value == rhs.m_value; } 46 : 47 : template <typename T> 48 120 : value &operator<<(T const &rhs) { 49 120 : std::ostringstream os; 50 120 : os << rhs; 51 120 : m_value = os.str(); 52 240 : return *this; 53 : } 54 : 55 261 : value &operator<<(std::string const &rhs) { 56 261 : m_value = rhs; 57 261 : return *this; 58 : } 59 : 60 17 : value &operator<<(char const *rhs) { 61 17 : m_value = std::string{rhs}; 62 17 : return *this; 63 : } 64 : 65 91 : value &operator>>(int &rhs) { 66 91 : rhs = std::stoi(m_value); 67 91 : return *this; 68 : } 69 : 70 2 : value &operator>>(size_t &rhs) { 71 2 : rhs = std::stoul(m_value); 72 2 : return *this; 73 : } 74 : 75 36 : value &operator>>(float &rhs) { 76 36 : rhs = std::stof(m_value); 77 36 : return *this; 78 : } 79 : 80 70 : value &operator>>(double &rhs) { 81 70 : rhs = std::stod(m_value); 82 70 : return *this; 83 : } 84 : 85 8 : value &operator>>(std::string &rhs) { 86 8 : rhs = m_value; 87 8 : return *this; 88 : } 89 : 90 : value const &operator>>(int &rhs) const { 91 : rhs = std::stoi(m_value); 92 : return *this; 93 : } 94 : 95 : value const &operator>>(size_t &rhs) const { 96 : rhs = std::stoul(m_value); 97 : return *this; 98 : } 99 : 100 : value const &operator>>(float &rhs) const { 101 : rhs = std::stof(m_value); 102 : return *this; 103 : } 104 : 105 : value const &operator>>(double &rhs) const { 106 : rhs = std::stod(m_value); 107 : return *this; 108 : } 109 : 110 : value const &operator>>(std::string &rhs) const { 111 : rhs = m_value; 112 : return *this; 113 : } 114 : 115 73 : value &operator<<(value const &rhs) { 116 73 : m_value = rhs.m_value; 117 73 : return *this; 118 : } 119 : 120 1 : value &operator>>(value &rhs) { 121 1 : rhs.m_value = m_value; 122 1 : return *this; 123 : } 124 : 125 : value const &operator>>(value &rhs) const { 126 : rhs.m_value = m_value; 127 : return *this; 128 : } 129 : }; 130 : 131 : public: 132 : /** \brief Load configuration from JSON file 133 : * 134 : * Loads the configuration from a JSON file using Boost's ptree. 135 : * 136 : * \param[in] filename Path to the JSON file 137 : */ 138 : void load_from_json(std::string const &filename); 139 : 140 : /** \brief Save configuration to JSON file 141 : * 142 : * Saves the configuration to a JSON file using Boost's ptree. 143 : * 144 : * \param[in] filename Path to the JSON file 145 : */ 146 : void save_to_json(std::string const &filename) const; 147 : 148 : /** \brief Constructor */ 149 18 : Configuration() = default; 150 : 151 : /** \brief Number of elements matching specific key 152 : * 153 : * Returns the number of elements matching the key. This can only 154 : * be zero or one, because the wrapped `std::map` does not allow 155 : * duplicates. 156 : * 157 : * \param[in] key Key 158 : * \returns Number of elements machting key 159 : */ 160 35 : size_t count(std::string const &key) const { return params.count(key); } 161 : 162 : /** \brief Number of elements 163 : * 164 : * \returns Number of elements 165 : */ 166 : size_t size() const { return params.size(); } 167 : 168 : /** \brief Append operator 169 : * 170 : * This will append the right hand side to the left hand side. If 171 : * a key exists on both sides, it will be overwritten with the 172 : * value from the right hand side. 173 : * 174 : * \returns Configuration appended to 175 : */ 176 3 : Configuration &operator+=(Configuration const &rhs) { 177 54 : for (auto const &p : rhs) { 178 51 : (*this)[p.first] = p.second; 179 : } 180 3 : return *this; 181 : } 182 : 183 : /** \brief Element access operator 184 : * 185 : * This returns a reference to the element associated to the key 186 : * and will insert it if no such key exists. 187 : * 188 : * \returns Reference to the value 189 : */ 190 491 : value &operator[](std::string const &key) { return params[key]; } 191 : 192 : /** \brief Constant element access operator 193 : * 194 : * This returns a copy of the element associated to the key. It 195 : * throws if no such key exists. 196 : * 197 : * \returns Copy of the value 198 : * \throws std::out_of_range 199 : */ 200 260 : value operator[](std::string const &key) const { return params.at(key); } 201 : 202 : /** \brief Comparison operator 203 : * 204 : * Compares two configurations. 205 : * 206 : * \returns Truth value for equality 207 : */ 208 1 : bool operator==(Configuration const &rhs) const { return this->params == rhs.params; } 209 : 210 : /** \brief Iterator type 211 : * 212 : * Instead of implementing an own iterator we use the existing one 213 : * of the underlying `std::map`. 214 : */ 215 : typedef std::map<std::string, value>::iterator iterator; 216 : 217 : /** \brief Constant iterator type 218 : * 219 : * Instead of implementing an own constant iterator we use the 220 : * existing one of the underlying `std::map`. 221 : */ 222 : typedef std::map<std::string, value>::const_iterator const_iterator; 223 : 224 : /** \brief Iterator pointing to the beginning 225 : * 226 : * \returns iterator 227 : */ 228 98 : iterator begin() { return params.begin(); } 229 : 230 : /** \brief Iterator pointing to the end 231 : * 232 : * \returns iterator 233 : */ 234 98 : iterator end() { return params.end(); } 235 : 236 : /** \brief Constant iterator pointing to the beginning 237 : * 238 : * \returns constant iterator 239 : */ 240 31 : const_iterator begin() const { return params.cbegin(); } 241 : 242 : /** \brief Constant iterator pointing to the end 243 : * 244 : * \returns constant iterator 245 : */ 246 31 : const_iterator end() const { return params.cend(); } 247 : 248 : /** \brief Find an element associated to a key 249 : * 250 : * Attempts to find a key in the map and returns an iterator 251 : * pointing to the element. If no such key exists it returns 252 : * end(). 253 : * 254 : * \returns iterator 255 : */ 256 1 : iterator find(std::string const &key) { return params.find(key); } 257 : 258 : /** \brief Constant version of find(std::string const&) 259 : * 260 : * \returns constant iterator 261 : */ 262 1 : const_iterator find(std::string const &key) const { return params.find(key); } 263 : 264 : private: 265 : std::map<std::string, value> params; 266 : }; 267 : 268 : #endif // CONF_PARSER_H