LCOV - code coverage report
Current view: top level - pairinteraction - ConfParser.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 50 50 100.0 %
Date: 2024-04-29 00:41:50 Functions: 27 27 100.0 %

          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

Generated by: LCOV version 1.14