LCOV - code coverage report
Current view: top level - include/app - iniFile.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 90.6 % 32 29
Test Date: 2026-08-30 22:23:37 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /** \file iniFile.hpp
       2              :  * \author Jared R. Males
       3              :  * \brief Declares and defines an ini-style (toml) file parser
       4              :  *
       5              :  * \ingroup mxApp_files
       6              :  *
       7              :  */
       8              : 
       9              : //***********************************************************************//
      10              : // Copyright 2015, 2016, 2017, 2018 Jared R. Males (jaredmales@gmail.com)
      11              : //
      12              : // This file is part of mxlib.
      13              : //
      14              : // mxlib is free software: you can redistribute it and/or modify
      15              : // it under the terms of the GNU General Public License as published by
      16              : // the Free Software Foundation, either version 3 of the License, or
      17              : // (at your option) any later version.
      18              : //
      19              : // mxlib is distributed in the hope that it will be useful,
      20              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      21              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      22              : // GNU General Public License for more details.
      23              : //
      24              : // You should have received a copy of the GNU General Public License
      25              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      26              : //***********************************************************************//
      27              : 
      28              : #ifndef iniFile_hpp
      29              : #define iniFile_hpp
      30              : 
      31              : #include <unordered_map>
      32              : 
      33              : #include "ini.hpp"
      34              : 
      35              : namespace mx
      36              : {
      37              : namespace app
      38              : {
      39              : 
      40              : /// A wrapper for the ini functions.
      41              : /** Places results of the ini parser in an unordered map, with keys of "section=name", and value
      42              :  * strings containing the value of the config item.
      43              :  *
      44              :  * \ingroup mxApp
      45              :  */
      46              : struct iniFile
      47              : {
      48              :     typedef std::unordered_map<std::string, std::string> nameMapT; ///< the unordered map type used for storing values.
      49              : 
      50              :     nameMapT names; ///< The map of section=name keys to values.
      51              : 
      52              :     /// Return a key generated from the section and name.
      53              :     /** Constructs the key as "section=name".
      54              :      *
      55              :      * \returns the created key.
      56              :      */
      57          973 :     static std::string makeKey( const std::string &section, ///< [in] The section for the key
      58              :                                 const std::string &name     ///< [in] the name for the key
      59              :     )
      60              :     {
      61          973 :         return section + "=" + name;
      62              :     }
      63              : 
      64              :     /// Parse a key into its section and name consituents.
      65              :     /** Requires that `=` be present.
      66              :      *
      67              :      * \returns 0 on success
      68              :      * \returns -1 on error, if no `=` found.
      69              :      */
      70            5 :     static int parseKey( std::string &section,  ///< [out] the section extracted from the key
      71              :                          std::string &name,     ///< [out] the name extracted from the key
      72              :                          const std::string &key ///< [in] th key to parse.
      73              :     )
      74              :     {
      75            5 :         size_t eq = key.find( '=', 0 );
      76              : 
      77            5 :         if( eq == std::string::npos )
      78            0 :             return -1;
      79              : 
      80            5 :         section = key.substr( 0, eq );
      81              : 
      82            5 :         name = key.substr( eq + 1 );
      83              : 
      84            5 :         return 0;
      85              :     }
      86              : 
      87              :     /// Calls the inih parse function with this->handler.
      88              :     /** This returns the result of the ini_parse function.
      89              :      *
      90              :      * \returns 0 on success
      91              :      * \returns >0 is the line number of the first parsing error
      92              :      * \returns -1 on file open error
      93              :      * \return -2 on memory allocation error
      94              :      */
      95           37 :     int parse( const std::string &fname /**< [in] the full path of the file*/ )
      96              :     {
      97           37 :         return ini_parse( fname.c_str(), handler, this );
      98              :     }
      99              : 
     100              :     /// Insert a config value.  Appends if the key already exists in the map.
     101              :     /** \todo need error checking.
     102              :      *
     103              :      * \returns 0 on success
     104              :      * \returns -1 on error.
     105              :      */
     106          130 :     int insert( const char *section, ///< [in] The section for the key
     107              :                 const char *name,    ///< [in] the name for the key
     108              :                 const char *value    ///< [in] the value to insert
     109              :     )
     110              :     {
     111          390 :         std::string nkey = makeKey( section, name );
     112              : 
     113          130 :         names[nkey]; // Inserts with empty value if doesn't exist, otherwise does nothing.
     114              : 
     115          130 :         names[nkey] += value; // This is just an update to the existing value.
     116              : 
     117          130 :         return 0;
     118          130 :     }
     119              : 
     120              :     /// Config entry handler for the parser.
     121              :     /** Calls insert, and returns its result.  Any non-zero return will cause ini_parse to report the current
     122              :      * line number as an error.
     123              :      *
     124              :      * \returns 1 on success
     125              :      * \returns 0 on error
     126              :      */
     127          130 :     static int handler( void *user,          ///< [in] a pointer to this.
     128              :                         const char *section, ///< [in] the section of the config entry
     129              :                         const char *name,    ///< [in] the name of the config entry
     130              :                         const char *value    ///< [in] the value of the config entry
     131              :     )
     132              :     {
     133          130 :         iniFile *iF = static_cast<iniFile *>( user );
     134          130 :         return ( iF->insert( section, name, value ) == 0 );
     135              :     }
     136              : 
     137              :     /// Get the number of entries for the given section and name.
     138              :     /** Is either 1 or 0, depending on if this cconfig key exists.
     139              :      *
     140              :      * \returns the number of entries for the section=name key.
     141              :      */
     142          607 :     size_t count( const std::string &section, ///< [in] The section for the key
     143              :                   const std::string &name     ///< [in] the name for the key
     144              :     )
     145              :     {
     146          607 :         return names.count( makeKey( section, name ) );
     147              :     }
     148              : 
     149              :     /// Erase the entry for the given section and name.
     150              :     /**
     151              :      * \returns 0 on sucess
     152              :      * \returns -1 if no section=name entry in the map.
     153              :      */
     154          115 :     int erase( const std::string &section, ///< [in] The section for the key
     155              :                const std::string &name     ///< [in] the name for the key
     156              :     )
     157              :     {
     158          115 :         if( names.erase( makeKey( section, name ) ) > 0 )
     159          115 :             return 0;
     160              :         else
     161            0 :             return -1;
     162              :     }
     163              : 
     164              :     /// Get the value associated with this section=name pair.
     165              :     /**
     166              :      * \returns the value if the section=name key exists
     167              :      * \returns and empty string if the section=name key does not exist.
     168              :      */
     169          115 :     std::string operator()( const std::string &section, ///< [in] The section for the key
     170              :                             const std::string &name     ///< [in] the name for the key
     171              :     )
     172              :     {
     173          115 :         std::string key = makeKey( section, name );
     174          115 :         if( names.count( key ) > 0 )
     175              :         {
     176          115 :             return names[key];
     177              :         }
     178              :         else
     179              :         {
     180            0 :             return std::string( "" );
     181              :         }
     182          115 :     }
     183              : 
     184              :     /// Get the value associated with this name with an empty section.
     185              :     /**
     186              :      * \returns the value if the section=name key exists, with section empty
     187              :      * \returns and empty string if the section=name key does not exist, with section empty.
     188              :      */
     189              :     std::string operator()( const std::string &name /**< [in] the name for the key*/ )
     190              :     {
     191              :         return operator()( "", name );
     192              :     }
     193              : };
     194              : 
     195              : } // namespace app
     196              : } // namespace mx
     197              : 
     198              : #endif
        

Generated by: LCOV version 2.0-1