Virtual Testbed
Ship dynamics simulator for extreme conditions
ini.hh
1 #ifndef VTESTBED_INI_INI_HH
2 #define VTESTBED_INI_INI_HH
3 
4 #include <locale>
5 #include <map>
6 #include <sstream>
7 #include <vector>
8 
9 #include <vtestbed/ini/types.hh>
10 
11 namespace vtb {
12 
13  namespace ini {
14 
15  class Ini {
16 
17  private:
18 
21 
22  enum Read_State {
23  READ_STATE_NONE,
24  READ_STATE_CATEGORY,
25  READ_STATE_POST_CATEGORY,
26  READ_STATE_COMMENT,
27  READ_STATE_PRE_KEY,
28  READ_STATE_KEY,
29  READ_STATE_VALUE,
30  };
31 
32  private:
33  map_2d _categories;
34  bool _has_changes = false;
35 
36  public:
37 
38  int load(const string_type& filename, bool keep_existing = false);
39  bool save(const string_type& filename);
40  inline bool HasChanges() const { return this->_has_changes; }
41  inline const map_2d& sections() const { return this->_categories; }
42  bool HasCategory(const string_type& category) const;
43 
44  template <class T>
45  T find(const char* category, const char* key) const {
46  auto r1 = this->_categories.find(category);
47  if (r1 == this->_categories.end()) {
48  throw std::invalid_argument(key);
49  }
50  auto r2 = r1->second.find(key);
51  if (r2 == r1->second.end()) {
52  throw std::invalid_argument(key);
53  }
54  T value{};
55  std::istringstream in(r2->second);
56  in.imbue(std::locale::classic());
57  if (!(in >> value)) {
58  throw std::invalid_argument(key);
59  }
60  return value;
61  }
62 
63  template <class T>
64  T get(
65  const string_type& category,
66  const string_type& key,
67  T def_value
68  ) const {
69  auto r1 = this->_categories.find(category);
70  if (r1 == this->_categories.end()) { return def_value; }
71  auto r2 = r1->second.find(key);
72  if (r2 == r1->second.end()) { return def_value; }
73  T value{};
74  std::istringstream in(r2->second);
75  in.imbue(std::locale::classic());
76  if (in >> value) { return value; }
77  return def_value;
78  }
79 
80  inline string_type
81  get(
82  const char* category,
83  const char* key,
84  const char* def_value = ""
85  ) const {
86  return this->get<string_type>(category, key, def_value);
87  }
88 
89  template <class T>
90  void set(const char* category, const char* key, T value) {
92  out.imbue(std::locale::classic());
93  out << value;
94  this->_categories[category][key] = out.str();
95  this->_has_changes = true;
96  }
97 
98  inline void
99  set(const char* category, const char* key, const char* value) {
100  this->_categories[category][key] = value;
101  this->_has_changes = true;
102  }
103 
104  inline void
105  set(const char* category, const char* key, const string_type& value) {
106  this->_categories[category][key] = value;
107  this->_has_changes = true;
108  }
109 
110  };
111  }
112 }
113 
114 #endif // vim:filetype=cpp
T classic(T... args)
Main namespace.
Definition: convert.hh:9