Skip to content

Commit 44ec495

Browse files
author
David Chu
committed
refactor: restructure _values
Changed `_values`'s structure to unordered_map to store the config as {"section1": {"key1": "value1", ...}, ...}. Also created a get section method and modified the way of checking if a key exists. Previously, methods with a default value checks key existence twice. Now all methods check and access a key only once.
1 parent b96184f commit 44ec495

File tree

1 file changed

+43
-36
lines changed

1 file changed

+43
-36
lines changed

ini/INIReader.h

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,9 @@ class INIReader
247247
int ParseError() const;
248248

249249
// Return the list of sections found in ini file
250-
const std::set<std::string>& Sections() const;
250+
const std::set<std::string> Sections() const;
251+
252+
const std::unordered_map<std::string, std::string> Get(std::string section) const;
251253

252254
template<typename T = std::string>
253255
T Get(std::string section, std::string name) const;
@@ -263,9 +265,7 @@ class INIReader
263265

264266
protected:
265267
int _error;
266-
std::map<std::string, std::string> _values;
267-
std::set<std::string> _sections;
268-
static std::string MakeKey(std::string section, std::string name);
268+
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> _values;
269269
static int ValueHandler(void* user, const char* section, const char* name, const char* value);
270270

271271
template<typename T>
@@ -310,20 +310,36 @@ inline int INIReader::ParseError() const
310310
return _error;
311311
}
312312

313-
inline const std::set<std::string>& INIReader::Sections() const
313+
inline const std::set<std::string> INIReader::Sections() const
314314
{
315-
return _sections;
315+
std::set<std::string> retval;
316+
for (auto const& element : _values) {
317+
retval.insert(element.first);
318+
}
319+
return retval;
320+
}
321+
322+
inline const std::unordered_map<std::string, std::string> INIReader::Get(std::string section) const {
323+
auto const _section = _values.find(section);
324+
if (_section == _values.end()) {
325+
throw std::runtime_error("section '" + section + "' not found.");
326+
}
327+
return _section->second;
316328
}
317329

318-
template<typename T = std::string>
330+
template<typename T>
319331
inline T INIReader::Get(std::string section, std::string name) const {
320-
std::string key = MakeKey(section, name);
321-
if (!_values.count(key)) {
322-
throw std::runtime_error("key " + key + " not found.");
332+
auto const _section = Get(section);
333+
auto const _value = _section.find(name);
334+
335+
if (_value == _section.end()) {
336+
throw std::runtime_error("key '" + name + "' not found in section '" + section + "'.");
323337
}
324-
338+
339+
std::string value = _value->second;
340+
325341
if constexpr (std::is_same<T, std::string>()) {
326-
return _values.at(key);
342+
return value;
327343
} else if constexpr (std::is_same<T, bool>()) {
328344
std::string s{_values.at(key)};
329345
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
@@ -344,23 +360,20 @@ inline T INIReader::Get(std::string section, std::string name) const {
344360

345361
template<typename T>
346362
inline T INIReader::Get(std::string section, std::string name, T&& default_v) const {
347-
std::string key = MakeKey(section, name);
348-
if (!_values.count(key)) {
363+
try {
364+
return Get<T>(section, name);
365+
} catch(std::runtime_error &e) {
349366
return default_v;
350367
}
351-
return Get<T>(section, name);
352368
}
353369

354-
template<typename T = std::string>
370+
template<typename T>
355371
inline std::vector<T> INIReader::GetVector(std::string section, std::string name) const {
356-
std::string key = MakeKey(section, name);
357-
if (!_values.count(key)) {
358-
throw std::runtime_error("key " + key + " not found.");
359-
}
372+
std::string value = Get(section, name);
360373

361-
std::istringstream out{_values.at(key)};
374+
std::istringstream out{value};
362375
const std::vector<std::string> strs{
363-
std::istream_iterator<std::string>{out},
376+
std::istream_iterator<std::string>{out},
364377
std::istream_iterator<std::string>()
365378
};
366379
try {
@@ -370,17 +383,17 @@ inline std::vector<T> INIReader::GetVector(std::string section, std::string name
370383
}
371384
return vs;
372385
} catch (std::exception& e) {
373-
throw std::runtime_error("cannot parse value in " + key + " to vector<T>.");
386+
throw std::runtime_error("cannot parse value " + value + " to vector<T>.");
374387
}
375388
}
376389

377390
template<typename T>
378391
inline std::vector<T> INIReader::GetVector(std::string section, std::string name, std::vector<T> default_v) const {
379-
std::string key = MakeKey(section, name);
380-
if (!_values.count(key)) {
392+
try {
393+
return GetVector<T>(section, name);
394+
} catch(std::runtime_error &e) {
381395
return default_v;
382-
}
383-
return GetVector<T>(section, name);
396+
};
384397
}
385398

386399

@@ -398,20 +411,14 @@ inline T INIReader::Converter(std::string s) const {
398411
return v;
399412
}
400413

401-
inline std::string INIReader::MakeKey(const std::string section, const std::string name)
402-
{
403-
std::string key = section + "=" + name;
404-
return key;
405414
}
406415

407416
inline int INIReader::ValueHandler(void* user, const char* section, const char* name, const char* value)
408417
{
409418
INIReader* reader = (INIReader*)user;
410-
std::string key = MakeKey(section, name);
411-
if (reader->_values[key].size() > 0)
412-
reader->_values[key] += "\n";
413-
reader->_values[key] += value;
414-
reader->_sections.insert(section);
419+
if (reader->_values[section][name].size() > 0)
420+
reader->_values[section][name] += "\n";
421+
reader->_values[section][name] += value;
415422
return 1;
416423
}
417424
}

0 commit comments

Comments
 (0)