3434#include < cstdlib>
3535#include < cstring>
3636#include < istream>
37+ #include < charconv>
3738#include < ini.h>
3839#include " lcf/inireader.h"
3940
4041namespace lcf {
4142
42- INIReader::INIReader (const std::string& filename)
43+ INIReader::INIReader (std::string filename)
4344{
4445 _error = ini_parse (filename.c_str (), ValueHandler, this );
4546}
@@ -100,41 +101,50 @@ int INIReader::ParseError() const
100101 return _error;
101102}
102103
103- std::string INIReader::Get (const std::string& section, const std::string& name, const std::string& default_value) const
104+ std::string_view INIReader::Get (std::string_view section, std::string_view name, std::string_view default_value) const
104105{
105106 std::string key = MakeKey (section, name);
106- // Use _values.find() here instead of _values.at() to support pre C++11 compilers
107- return _values.count (key) ? _values.find (key)->second : default_value;
107+
108+ auto it = _values.find (key);
109+ if (it == _values.end ()) {
110+ return default_value;
111+ }
112+ return it->second ;
108113}
109114
110- std::string INIReader::GetString (const std::string& section, const std::string& name, const std::string& default_value) const
115+ std::string_view INIReader::GetString (std::string_view section, std::string_view name, std::string_view default_value) const
111116{
112- const std::string str = Get (section, name, " " );
117+ auto str = Get (section, name, " " );
113118 return str.empty () ? default_value : str;
114119}
115120
116- long INIReader::GetInteger (const std::string& section, const std::string& name, long default_value) const
121+ long INIReader::GetInteger (std::string_view section, std::string_view name, long default_value) const
117122{
118- std::string valstr = Get (section, name, " " );
119- const char * value = valstr.c_str ();
120- char * end;
121- // This parses "1234" (decimal) and also "0x4D2" (hex)
122- long n = strtol (value, &end, 0 );
123- return end > value ? n : default_value;
123+ std::string_view valstr = Get (section, name, " " );
124+ long n;
125+ auto ec = std::from_chars (valstr.data (), valstr.data () + valstr.size (), n).ec ;
126+ return ec == std::errc () ? n : default_value;
124127}
125128
126- double INIReader::GetReal (const std::string& section, const std::string& name, double default_value) const
129+ double INIReader::GetReal (std::string_view section, std::string_view name, double default_value) const
127130{
128- std::string valstr = Get (section, name, " " );
131+ std::string valstr = std::string ( Get (section, name, " " ) );
129132 const char * value = valstr.c_str ();
130133 char * end;
131134 double n = strtod (value, &end);
132135 return end > value ? n : default_value;
136+ /*
137+ // FIXME: std::from_chars<double> not supported by clang and old g++ versions
138+ std::string_view valstr = Get(section, name, "");
139+ double n;
140+ auto ec = std::from_chars(valstr.data(), valstr.data() + valstr.size(), n).ec;
141+ return ec == std::errc() ? n : default_value;
142+ */
133143}
134144
135- bool INIReader::GetBoolean (const std::string& section, const std::string& name, bool default_value) const
145+ bool INIReader::GetBoolean (std::string_view section, std::string_view name, bool default_value) const
136146{
137- std::string valstr = Get (section, name, " " );
147+ auto valstr = std::string ( Get (section, name, " " ) );
138148 // Convert to lower case to make string comparisons case-insensitive
139149 std::transform (valstr.begin (), valstr.end (), valstr.begin (), ::tolower);
140150 if (valstr == " true" || valstr == " yes" || valstr == " on" || valstr == " 1" )
@@ -145,15 +155,15 @@ bool INIReader::GetBoolean(const std::string& section, const std::string& name,
145155 return default_value;
146156}
147157
148- bool INIReader::HasValue (const std::string& section, const std::string& name) const
158+ bool INIReader::HasValue (std::string_view section, std::string_view name) const
149159{
150160 std::string key = MakeKey (section, name);
151- return _values.count (key);
161+ return _values.find (key) != _values. end ( );
152162}
153163
154- std::string INIReader::MakeKey (const std::string& section, const std::string& name)
164+ std::string INIReader::MakeKey (std::string_view section, std::string_view name)
155165{
156- std::string key = section + " =" + name;
166+ std::string key = std::string ( section) + " =" + std::string ( name) ;
157167 // Convert to lower case to make section/name lookups case-insensitive
158168 std::transform (key.begin (), key.end (), key.begin (), ::tolower);
159169 return key;
@@ -164,9 +174,15 @@ int INIReader::ValueHandler(void* user, const char* section, const char* name,
164174{
165175 INIReader* reader = static_cast <INIReader*>(user);
166176 std::string key = MakeKey (section, name);
167- if (reader->_values [key].size () > 0 )
168- reader->_values [key] += " \n " ;
169- reader->_values [key] += value;
177+
178+ auto [it, inserted] = reader->_values .try_emplace (key, value);
179+
180+ if (!inserted) {
181+ // Key is duplicated
182+ it->second += " \n " ;
183+ it->second += value;
184+ }
185+
170186 return 1 ;
171187}
172188
0 commit comments