liblcf
Loading...
Searching...
No Matches
inireader.cpp
Go to the documentation of this file.
1// Read an INI file into easy-to-access name/value pairs.
2
3// inih and INIReader are released under the New BSD license:
4//
5// Copyright (c) 2009, Ben Hoyt
6// All rights reserved.
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are met:
10// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above copyright
13// notice, this list of conditions and the following disclaimer in the
14// documentation and/or other materials provided with the distribution.
15// * Neither the name of Ben Hoyt nor the names of its contributors
16// may be used to endorse or promote products derived from this software
17// without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY BEN HOYT ''AS IS'' AND ANY
20// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22// DISCLAIMED. IN NO EVENT SHALL BEN HOYT BE LIABLE FOR ANY
23// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Go to the project home page for more info: https://github.com/benhoyt/inih
31
32#include <algorithm>
33#include <cctype>
34#include <cstdlib>
35#include <cstring>
36#include <istream>
37#include <ini.h>
38#include "lcf/inireader.h"
39
40namespace lcf {
41
42INIReader::INIReader(const std::string& filename)
43{
44 _error = ini_parse(filename.c_str(), ValueHandler, this);
45}
46
47INIReader::INIReader(std::istream& filestream)
48{
49 _error = ini_parse_stream([](char* str, int num, void* stream) {
50 std::istream* is = reinterpret_cast<std::istream*>(stream);
51 if (num > 0) {
52 // via https://stackoverflow.com/questions/6089231/
53 std::string out;
54
55 std::istream::sentry se(*is, true);
56 std::streambuf* sb = is->rdbuf();
57
58 bool loop = true;
59
60 do {
61 int c = sb->sbumpc();
62 switch (c) {
63 case '\n':
64 loop = false;
65 break;
66 case '\r':
67 if (sb->sgetc() == '\n') {
68 sb->sbumpc();
69 }
70 loop = false;
71 break;
72 case EOF:
73 // Also handle the case when the last line has no line ending
74 if (out.empty()) {
75 is->setstate(std::ios::eofbit);
76 }
77 loop = false;
78 break;
79 default:
80 out += (char)c;
81 }
82 } while (loop);
83
84 if (out.empty() && (is->fail() || is->eof())) {
85 return (char*)nullptr;
86 }
87
88 strncpy(str, out.c_str(), num);
89 str[num - 1] = '\0';
90
91 return str;
92 }
93
94 return (char*)nullptr;
95 }, &filestream, ValueHandler, this);
96}
97
98int INIReader::ParseError() const
99{
100 return _error;
101}
102
103std::string INIReader::Get(const std::string& section, const std::string& name, const std::string& default_value) const
104{
105 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;
108}
109
110std::string INIReader::GetString(const std::string& section, const std::string& name, const std::string& default_value) const
111{
112 const std::string str = Get(section, name, "");
113 return str.empty() ? default_value : str;
114}
115
116long INIReader::GetInteger(const std::string& section, const std::string& name, long default_value) const
117{
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;
124}
125
126double INIReader::GetReal(const std::string& section, const std::string& name, double default_value) const
127{
128 std::string valstr = Get(section, name, "");
129 const char* value = valstr.c_str();
130 char* end;
131 double n = strtod(value, &end);
132 return end > value ? n : default_value;
133}
134
135bool INIReader::GetBoolean(const std::string& section, const std::string& name, bool default_value) const
136{
137 std::string valstr = Get(section, name, "");
138 // Convert to lower case to make string comparisons case-insensitive
139 std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);
140 if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1")
141 return true;
142 else if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0")
143 return false;
144 else
145 return default_value;
146}
147
148bool INIReader::HasValue(const std::string& section, const std::string& name) const
149{
150 std::string key = MakeKey(section, name);
151 return _values.count(key);
152}
153
154std::string INIReader::MakeKey(const std::string& section, const std::string& name)
155{
156 std::string key = section + "=" + name;
157 // Convert to lower case to make section/name lookups case-insensitive
158 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
159 return key;
160}
161
162int INIReader::ValueHandler(void* user, const char* section, const char* name,
163 const char* value)
164{
165 INIReader* reader = static_cast<INIReader*>(user);
166 std::string key = MakeKey(section, name);
167 if (reader->_values[key].size() > 0)
168 reader->_values[key] += "\n";
169 reader->_values[key] += value;
170 return 1;
171}
172
173} //namespace lcf
Definition: dbarray.cpp:13