mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
iniFile.hpp
Go to the documentation of this file.
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  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  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  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  size_t eq = key.find('=', 0);
76 
77  if( eq == std::string::npos ) return -1;
78 
79  section = key.substr(0, eq);
80 
81  name = key.substr(eq+1);
82 
83  return 0;
84  }
85 
86  /// Calls the inih parse function with this->handler.
87  /** This returns the result of the ini_parse function.
88  *
89  * \returns 0 on success
90  * \returns >0 is the line number of the first parsing error
91  * \returns -1 on file open error
92  * \return -2 on memory allocation error
93  */
94  int parse( const std::string & fname /**< [in] the full path of the file*/ )
95  {
96  return ini_parse(fname.c_str(), handler, this);
97  }
98 
99  /// Insert a config value. Appends if the key already exists in the map.
100  /** \todo need error checking.
101  *
102  * \returns 0 on success
103  * \returns -1 on error.
104  */
105  int insert( const char *section, ///< [in] The section for the key
106  const char *name, ///< [in] the name for the key
107  const char * value ///< [in] the value to insert
108  )
109  {
110  std::string nkey = makeKey(section, name);
111 
112  names[nkey]; //Inserts with empty value if doesn't exist, otherwise does nothing.
113 
114  names[nkey] += value; //This is just an update to the existing value.
115 
116  return 0;
117  }
118 
119  /// Config entry handler for the parser.
120  /** Calls insert, and returns its result. Any non-zero return will cause ini_parse to report the current
121  * line number as an error.
122  *
123  * \returns 1 on success
124  * \returns 0 on error
125  */
126  static int handler( void* user, ///< [in] a pointer to this.
127  const char* section, ///< [in] the section of the config entry
128  const char* name, ///< [in] the name of the config entry
129  const char* value ///< [in] the value of the config entry
130  )
131  {
132  iniFile * iF = static_cast<iniFile *>(user);
133  return (iF->insert(section, name, value) == 0);
134  }
135 
136  /// Get the number of entries for the given section and name.
137  /** Is either 1 or 0, depending on if this cconfig key exists.
138  *
139  * \returns the number of entries for the section=name key.
140  */
141  size_t count( const std::string &section, ///< [in] The section for the key
142  const std::string & name ///< [in] the name for the key
143  )
144  {
145  return names.count(makeKey(section, name));
146  }
147 
148  /// Erase the entry for the given section and name.
149  /**
150  * \returns 0 on sucess
151  * \returns -1 if no section=name entry in the map.
152  */
153  int erase( const std::string & section, ///< [in] The section for the key
154  const std::string & name ///< [in] the name for the key
155  )
156  {
157  if ( names.erase(makeKey(section,name)) > 0) return 0;
158  else return -1;
159  }
160 
161  /// Get the value associated with this section=name pair.
162  /**
163  * \returns the value if the section=name key exists
164  * \returns and empty string if the section=name key does not exist.
165  */
166  std::string operator()( const std::string &section, ///< [in] The section for the key
167  const std::string & name ///< [in] the name for the key
168  )
169  {
170  std::string key = makeKey(section, name);
171  if(names.count(key) > 0)
172  {
173  return names[key];
174  }
175  else
176  {
177  return std::string("");
178  }
179  }
180 
181  /// Get the value associated with this name with an empty section.
182  /**
183  * \returns the value if the section=name key exists, with section empty
184  * \returns and empty string if the section=name key does not exist, with section empty.
185  */
186  std::string operator()( const std::string & name /**< [in] the name for the key*/ )
187  {
188  return operator()("", name);
189  }
190 
191 
192 };
193 
194 } //namespace app
195 } //namespace mx
196 
197 #endif
The inih ini-style, file parser modified for mxlib.
int ini_parse(const char *filename, int(*handler)(void *, const char *, const char *, const char *), void *user)
Parse given INI-style file.
Definition: ini.cpp:193
The mxlib c++ namespace.
Definition: mxError.hpp:107
A wrapper for the ini functions.
Definition: iniFile.hpp:47
static int handler(void *user, const char *section, const char *name, const char *value)
Config entry handler for the parser.
Definition: iniFile.hpp:126
size_t count(const std::string &section, const std::string &name)
Get the number of entries for the given section and name.
Definition: iniFile.hpp:141
int erase(const std::string &section, const std::string &name)
Erase the entry for the given section and name.
Definition: iniFile.hpp:153
static std::string makeKey(const std::string &section, const std::string &name)
Return a key generated from the section and name.
Definition: iniFile.hpp:57
nameMapT names
The map of section=name keys to values.
Definition: iniFile.hpp:50
std::unordered_map< std::string, std::string > nameMapT
the unordered map type used for storing values.
Definition: iniFile.hpp:48
int insert(const char *section, const char *name, const char *value)
Insert a config value. Appends if the key already exists in the map.
Definition: iniFile.hpp:105
std::string operator()(const std::string &section, const std::string &name)
Get the value associated with this section=name pair.
Definition: iniFile.hpp:166
static int parseKey(std::string &section, std::string &name, const std::string &key)
Parse a key into its section and name consituents.
Definition: iniFile.hpp:70
int parse(const std::string &fname)
Calls the inih parse function with this->handler.
Definition: iniFile.hpp:94
std::string operator()(const std::string &name)
Get the value associated with this name with an empty section.
Definition: iniFile.hpp:186