PIDUINO
Loading...
Searching...
No Matches
configfile.h
1/* Copyright © 2018-2025 Pascal JEAN, All rights reserved.
2 This file is part of the Piduino Library.
3
4 The Piduino Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 The Piduino Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with the Piduino Library; if not, see <http://www.gnu.org/licenses/>.
16*/
17#pragma once
18
19#include <iostream>
20#include <string>
21#include <sstream>
22#include <map>
23#include <fstream>
24#include <stdexcept>
25#include <typeinfo>
26#include <type_traits>
27
35namespace Piduino {
36
37 class Convert {
38
39 public:
40 // -----------------------------------------------------------------------
41 template <typename T>
42 static std::string T_to_string (T const &val) {
43 std::ostringstream ostr;
44
45 ostr << val;
46 return ostr.str();
47 }
48
49 // -----------------------------------------------------------------------
50 template <typename T>
51 static T string_to_T (std::string const &val) {
52 std::istringstream istr (val);
53 T returnVal;
54
55 if (! (istr >> returnVal)) {
56
57 throw std::invalid_argument ("Not a valid " +
58 (std::string) typeid (T).name() + " received !");
59 }
60 return returnVal;
61 }
62 };
63
64 class ConfigFile {
65 public:
66
67 // -----------------------------------------------------------------------
68 ConfigFile (const std::string &filename, char keysep = '=', char remsep = '#') :
69 _keysep (keysep), _remsep (remsep) {
70
71 extractKeys (filename);
72 }
73
74 // -----------------------------------------------------------------------
75 bool
76 keyExists (const std::string &key) const {
77
78 return _contents.find (key) != _contents.end();
79 }
80
81 // -----------------------------------------------------------------------
82 template<typename ValueType> ValueType value (const std::string &key,
83 ValueType const &defaultValue = ValueType()) const {
84
85 if (!keyExists (key)) {
86
87 return defaultValue;
88 }
89
90 return Convert::string_to_T<ValueType> (_contents.find (key)->second);
91 }
92
93 // -----------------------------------------------------------------------
94 std::string value (const std::string &key,
95 std::string const &defaultValue = std::string()) const {
96 if (!keyExists (key)) {
97
98 return defaultValue;
99 }
100
101 return _contents.find (key)->second;
102 }
103
104 private:
105 std::map<std::string, std::string> _contents;
108
109 // -----------------------------------------------------------------------
110 void
111 removeComment (std::string &line) const {
112 size_t pos = line.find (_remsep);
113 if (pos != line.npos) {
114 line.erase (pos, line.npos);
115 }
116 }
117
118 // -----------------------------------------------------------------------
119 bool
120 onlyWhitespace (const std::string &line) const {
121
122 return (line.find_first_not_of (' ') == line.npos);
123 }
124
125 // -----------------------------------------------------------------------
126 bool
127 validLine (const std::string &line) const {
128 std::string temp = line;
129
130 temp.erase (0, temp.find_first_not_of ("\t "));
131
132 if (temp[0] == _keysep) {
133
134 return false;
135 }
136
137 // for (size_t i = temp.find (_keysep) + 1; i < temp.length(); i++)
138
139 // if (temp[i] != ' ') {
140
141 // return true;
142 // }
143
144 // return false;
145 return true;
146 }
147
148 // -----------------------------------------------------------------------
149 static void trim (std::string &str) {
150
151 str.erase (0, str.find_first_not_of ("\t \""));
152 str.erase (str.find_last_not_of ("\t \"") + 1);
153 }
154
155 // -----------------------------------------------------------------------
156 void
157 extractKey (std::string &key, size_t const &sepPos,
158 const std::string &line) const {
159
160 key = line.substr (0, sepPos);
161 trim (key);
162 }
163
164 // -----------------------------------------------------------------------
165 void
166 extractValue (std::string &value, size_t const &sepPos,
167 const std::string &line) const {
168
169 if (sepPos < line.npos) {
170
171 value = line.substr (sepPos + 1);
172 trim (value);
173 }
174 else {
175
176 value.clear();
177 }
178 }
179
180 // -----------------------------------------------------------------------
181 void
182 extractContents (const std::string &line) {
183 std::string temp = line;
184
185 temp.erase (0, temp.find_first_not_of ("\t "));
186 size_t sepPos = temp.find (_keysep);
187
188 std::string key, value;
189 extractKey (key, sepPos, temp);
190 extractValue (value, sepPos, temp);
191
192 if (keyExists (key)) { // last replace previous key
193
194 _contents.erase (key);
195 }
196 _contents.insert (std::pair<std::string, std::string> (key, value));
197 }
198
199 // -----------------------------------------------------------------------
200 void
201 parseLine (const std::string &line, size_t const lineNo) {
202
203 if (line.find (_keysep) != line.npos) {
204
205 if (validLine (line)) {
206
207 extractContents (line);
208 }
209 }
210 }
211
212 // -----------------------------------------------------------------------
213 void
214 extractKeys (const std::string &filename) {
215 std::ifstream file;
216 file.open (filename.c_str());
217 if (!file) {
218
219 throw std::invalid_argument ("File " + filename + " couldn't be found!");
220 }
221
222 std::string line;
223 size_t lineNo = 0;
224 while (std::getline (file, line)) {
225 lineNo++;
226 std::string temp = line;
227
228 if (temp.empty()) {
229 continue;
230 }
231
232 removeComment (temp);
233 if (onlyWhitespace (temp)) {
234 continue;
235 }
236
237 parseLine (temp, lineNo);
238 }
239
240 file.close();
241 }
242
243 };
244 #if 0
245 // -----------------------------------------------------------------------
246 std::string ConfigFile::value (const std::string &key, std::string const &defaultValue) const {
247
248 if (!keyExists (key)) {
249
250 return std::string();
251 }
252 return _contents.find (key)->second;
253 }
254 #endif
255}
260/* ========================================================================== */
void extractValue(std::string &value, size_t const &sepPos, const std::string &line) const
Definition configfile.h:166
std::string value(const std::string &key, std::string const &defaultValue=std::string()) const
Definition configfile.h:94
void removeComment(std::string &line) const
Definition configfile.h:111
bool onlyWhitespace(const std::string &line) const
Definition configfile.h:120
bool validLine(const std::string &line) const
Definition configfile.h:127
void extractKey(std::string &key, size_t const &sepPos, const std::string &line) const
Definition configfile.h:157
ValueType value(const std::string &key, ValueType const &defaultValue=ValueType()) const
Definition configfile.h:82
static void trim(std::string &str)
Definition configfile.h:149
void parseLine(const std::string &line, size_t const lineNo)
Definition configfile.h:201
ConfigFile(const std::string &filename, char keysep='=', char remsep='#')
Definition configfile.h:68
bool keyExists(const std::string &key) const
Definition configfile.h:76
std::map< std::string, std::string > _contents
Definition configfile.h:105
void extractContents(const std::string &line)
Definition configfile.h:182
void extractKeys(const std::string &filename)
Definition configfile.h:214
static T string_to_T(std::string const &val)
Definition configfile.h:51
static std::string T_to_string(T const &val)
Definition configfile.h:42
Global namespace for Piduino.
Definition board.h:28