1//
2// IniFileConfiguration.cpp
3//
4// Library: Util
5// Package: Configuration
6// Module: IniFileConfiguration
7//
8// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Util/IniFileConfiguration.h"
16
17
18#ifndef POCO_UTIL_NO_INIFILECONFIGURATION
19
20
21#include "Poco/Exception.h"
22#include "Poco/String.h"
23#include "Poco/Path.h"
24#include "Poco/FileStream.h"
25#include "Poco/Ascii.h"
26#include <set>
27
28
29using Poco::icompare;
30using Poco::trim;
31using Poco::Path;
32
33
34namespace Poco {
35namespace Util {
36
37
38IniFileConfiguration::IniFileConfiguration()
39{
40}
41
42
43IniFileConfiguration::IniFileConfiguration(std::istream& istr)
44{
45 load(istr);
46}
47
48
49IniFileConfiguration::IniFileConfiguration(const std::string& path)
50{
51 load(path);
52}
53
54
55IniFileConfiguration::~IniFileConfiguration()
56{
57}
58
59
60void IniFileConfiguration::load(std::istream& istr)
61{
62 _map.clear();
63 _sectionKey.clear();
64 while (!istr.eof())
65 {
66 parseLine(istr);
67 }
68}
69
70
71void IniFileConfiguration::load(const std::string& path)
72{
73 Poco::FileInputStream istr(path);
74 if (istr.good())
75 load(istr);
76 else
77 throw Poco::OpenFileException(path);
78}
79
80
81bool IniFileConfiguration::getRaw(const std::string& key, std::string& value) const
82{
83 IStringMap::const_iterator it = _map.find(key);
84 if (it != _map.end())
85 {
86 value = it->second;
87 return true;
88 }
89 else return false;
90}
91
92
93void IniFileConfiguration::setRaw(const std::string& key, const std::string& value)
94{
95 _map[key] = value;
96}
97
98
99void IniFileConfiguration::enumerate(const std::string& key, Keys& range) const
100{
101 std::set<std::string> keySet;
102 std::string prefix = key;
103 if (!prefix.empty()) prefix += '.';
104 std::string::size_type psize = prefix.size();
105 for (IStringMap::const_iterator it = _map.begin(); it != _map.end(); ++it)
106 {
107 if (icompare(it->first, psize, prefix) == 0)
108 {
109 std::string subKey;
110 std::string::size_type end = it->first.find('.', psize);
111 if (end == std::string::npos)
112 subKey = it->first.substr(psize);
113 else
114 subKey = it->first.substr(psize, end - psize);
115 if (keySet.find(subKey) == keySet.end())
116 {
117 range.push_back(subKey);
118 keySet.insert(subKey);
119 }
120 }
121 }
122}
123
124
125void IniFileConfiguration::removeRaw(const std::string& key)
126{
127 std::string prefix = key;
128 if (!prefix.empty()) prefix += '.';
129 std::string::size_type psize = prefix.size();
130 IStringMap::iterator it = _map.begin();
131 IStringMap::iterator itCur;
132 while (it != _map.end())
133 {
134 itCur = it++;
135 if ((icompare(itCur->first, key) == 0) || (icompare(itCur->first, psize, prefix) == 0))
136 {
137 _map.erase(itCur);
138 }
139 }
140}
141
142
143bool IniFileConfiguration::ICompare::operator () (const std::string& s1, const std::string& s2) const
144{
145 return icompare(s1, s2) < 0;
146}
147
148
149void IniFileConfiguration::parseLine(std::istream& istr)
150{
151 static const int eof = std::char_traits<char>::eof();
152
153 int c = istr.get();
154 while (c != eof && Poco::Ascii::isSpace(c)) c = istr.get();
155 if (c != eof)
156 {
157 if (c == ';')
158 {
159 while (c != eof && c != '\n') c = istr.get();
160 }
161 else if (c == '[')
162 {
163 std::string key;
164 c = istr.get();
165 while (c != eof && c != ']' && c != '\n') { key += (char) c; c = istr.get(); }
166 _sectionKey = trim(key);
167 }
168 else
169 {
170 std::string key;
171 while (c != eof && c != '=' && c != '\n') { key += (char) c; c = istr.get(); }
172 std::string value;
173 if (c == '=')
174 {
175 c = istr.get();
176 while (c != eof && c != '\n') { value += (char) c; c = istr.get(); }
177 }
178 std::string fullKey = _sectionKey;
179 if (!fullKey.empty()) fullKey += '.';
180 fullKey.append(trim(key));
181 _map[fullKey] = trim(value);
182 }
183 }
184}
185
186
187} } // namespace Poco::Util
188
189
190#endif // POCO_UTIL_NO_INIFILECONFIGURATION
191