Skip to content

Commit 8fe007f

Browse files
committed
feat: implement insert/update entry and dup to file
1 parent 45351d1 commit 8fe007f

File tree

1 file changed

+117
-15
lines changed

1 file changed

+117
-15
lines changed

ini/INIReader.h renamed to ini/ini.h

Lines changed: 117 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,7 @@
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+
383458
template <typename T>
384459
inline 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

Comments
 (0)