1- // Read an INI file into easy-to-access name/value pairs.
2-
3- // inih and INIReader are released under the New BSD license (see LICENSE.txt).
4- // Go to the project home page for more info:
5- //
6- // https://github.com/benhoyt/inih
7- /* inih -- simple .INI file parser
8-
9- inih is released under the New BSD license (see LICENSE.txt). Go to the project
10- home page for more info:
11-
12- https://github.com/benhoyt/inih
13-
14- */
1+ /* *
2+ * Yet another .ini parser for modern c++ (made for cpp17), inspired and extend
3+ * from @benhoyt's inih. See project page: https://github.com/SSARCandy/ini-cpp
4+ */
155
166#ifndef __INI_H__
177#define __INI_H__
@@ -20,9 +10,11 @@ home page for more info:
2010#include < stdio.h>
2111#include < string.h>
2212
13+ #include < sys/stat.h>
2314#include < algorithm>
2415#include < cctype>
2516#include < cstdlib>
17+ #include < fstream>
2618#include < iostream>
2719#include < iterator>
2820#include < map>
@@ -247,6 +239,22 @@ class INIReader {
247239 const std::string& name,
248240 const std::vector<T>& default_v) const ;
249241
242+ template <typename T = std::string>
243+ void InsertEntry (const std::string& section, const std::string& name,
244+ const T& v);
245+
246+ template <typename T = std::string>
247+ void InsertEntry (const std::string& section, const std::string& name,
248+ const std::vector<T>& vs);
249+
250+ template <typename T = std::string>
251+ void UpdateEntry (const std::string& section, const std::string& name,
252+ const T& v);
253+
254+ template <typename T = std::string>
255+ void UpdateEntry (const std::string& section, const std::string& name,
256+ const std::vector<T>& vs);
257+
250258 protected:
251259 int _error;
252260 std::unordered_map<std::string,
@@ -259,6 +267,12 @@ class INIReader {
259267 T Converter (const std::string& s) const ;
260268
261269 const bool BoolConverter (std::string s) const ;
270+
271+ template <typename T>
272+ std::string V2String (const T& v) const ;
273+
274+ template <typename T>
275+ std::string Vec2String (const std::vector<T>& v) const ;
262276};
263277
264278#endif // __INIREADER_H__
@@ -380,6 +394,67 @@ inline std::vector<T> INIReader::GetVector(
380394 };
381395}
382396
397+ template <typename T>
398+ inline void INIReader::InsertEntry (const std::string& section,
399+ const std::string& name, const T& v) {
400+ if (_values[section][name].size () > 0 ) {
401+ throw std::runtime_error (" duplicate key '" + std::string (name) +
402+ " ' in section '" + section + " '." );
403+ }
404+ _values[section][name] = V2String (v);
405+ }
406+
407+ template <typename T>
408+ inline void INIReader::InsertEntry (const std::string& section,
409+ const std::string& name,
410+ const std::vector<T>& vs) {
411+ if (_values[section][name].size () > 0 ) {
412+ throw std::runtime_error (" duplicate key '" + std::string (name) +
413+ " ' in section '" + section + " '." );
414+ }
415+ _values[section][name] = Vec2String (vs);
416+ }
417+
418+ template <typename T>
419+ inline void INIReader::UpdateEntry (const std::string& section,
420+ const std::string& name, const T& v) {
421+ if (!_values[section][name].size ()) {
422+ throw std::runtime_error (" key '" + std::string (name) +
423+ " ' not exist in section '" + section + " '." );
424+ }
425+ _values[section][name] = V2String (v);
426+ }
427+
428+ template <typename T>
429+ inline void INIReader::UpdateEntry (const std::string& section,
430+ const std::string& name,
431+ const std::vector<T>& vs) {
432+ if (!_values[section][name].size ()) {
433+ throw std::runtime_error (" key '" + std::string (name) +
434+ " ' not exist in section '" + section + " '." );
435+ }
436+ _values[section][name] = Vec2String (vs);
437+ }
438+
439+ template <typename T>
440+ inline std::string INIReader::V2String (const T& v) const {
441+ std::stringstream ss;
442+ ss << v;
443+ return ss.str ();
444+ }
445+
446+ template <typename T>
447+ inline std::string INIReader::Vec2String (const std::vector<T>& v) const {
448+ if (v.empty ()) {
449+ return " " ;
450+ }
451+ std::ostringstream oss;
452+ std::copy (v.begin (), v.end () - 1 , std::ostream_iterator<T>(oss, " " ));
453+ oss << v.back ();
454+
455+ return oss.str ();
456+ }
457+
383458template <typename T>
384459inline T INIReader::Converter (const std::string& s) const {
385460 try {
@@ -416,5 +491,32 @@ inline int INIReader::ValueHandler(void* user, const char* section,
416491 reader->_values [section][name] = value;
417492 return 1 ;
418493}
419- }
420494#endif // __INIREADER__
495+
496+ #ifndef __INIWRITER_H__
497+ #define __INIWRITER_H__
498+
499+ class INIWriter {
500+ public:
501+ INIWriter (){};
502+ inline static void write (const std::string& filepath,
503+ const INIReader& reader) {
504+ if (struct stat buf; stat (filepath.c_str (), &buf) == 0 ) {
505+ throw std::runtime_error (" file: " + filepath + " already exist." );
506+ }
507+ std::ofstream out;
508+ out.open (filepath);
509+ if (!out.is_open ()) {
510+ throw std::runtime_error (" cannot open output file: " + filepath);
511+ }
512+ for (const auto & section : reader.Sections ()) {
513+ out << " [" << section << " ]\n " ;
514+ for (const auto & key : reader.Keys (section)) {
515+ out << key << " =" << reader.Get (section, key) << " \n " ;
516+ }
517+ }
518+ out.close ();
519+ }
520+ };
521+ }
522+ #endif /* __INIWRITER_H__ */
0 commit comments