xrpld
Loading...
Searching...
No Matches
BasicConfig.h
1#pragma once
2
3#include <xrpl/basics/contract.h>
4
5#include <boost/beast/core/string.hpp>
6#include <boost/lexical_cast.hpp>
7
8#include <algorithm>
9#include <cstddef>
10#include <optional>
11#include <ostream>
12#include <stdexcept>
13#include <string>
14#include <unordered_map>
15#include <utility>
16#include <vector>
17
18namespace xrpl {
19
21
22//------------------------------------------------------------------------------
23
29{
30private:
36
38
39public:
43 explicit Section(std::string name = "");
44
48 [[nodiscard]] std::string const&
49 name() const
50 {
51 return name_;
52 }
53
58 [[nodiscard]] std::vector<std::string> const&
59 lines() const
60 {
61 return lines_;
62 }
63
68 [[nodiscard]] std::vector<std::string> const&
69 values() const
70 {
71 return values_;
72 }
73
77 void
79 {
80 if (lines_.empty())
81 {
82 lines_.emplace_back(std::move(value));
83 }
84 else
85 {
86 lines_[0] = std::move(value);
87 }
88 }
89
96 [[nodiscard]] std::string
97 legacy() const
98 {
99 if (lines_.empty())
100 return "";
101 if (lines_.size() > 1)
102 {
104 "A legacy value must have exactly one line. Section: " + name_);
105 }
106 return lines_[0];
107 }
108
113 void
114 set(std::string const& key, std::string const& value);
115
122 void
124
128 void
129 append(std::string const& line)
130 {
132 }
133
137 [[nodiscard]] bool
138 exists(std::string const& name) const;
139
140 template <class T = std::string>
141 [[nodiscard]] std::optional<T>
142 get(std::string const& name) const
143 {
144 auto const iter = lookup_.find(name);
145 if (iter == lookup_.end())
146 return std::nullopt;
147 return boost::lexical_cast<T>(iter->second);
148 }
149
153 template <class T>
154 [[nodiscard]] T
155 valueOr(std::string const& name, T const& other) const
156 {
157 auto const v = get<T>(name);
158 return v.has_value() ? *v : other;
159 }
160
161 // indicates if trailing comments were seen
162 // during the appending of any lines/values
163 [[nodiscard]] bool
165 {
167 }
168
169 friend std::ostream&
170 operator<<(std::ostream&, Section const& section);
171
172 // Returns `true` if there are no key/value pairs.
173 [[nodiscard]] bool
174 empty() const
175 {
176 return lookup_.empty();
177 }
178
179 // Returns the number of key/value pairs.
180 [[nodiscard]] std::size_t
181 size() const
182 {
183 return lookup_.size();
184 }
185
186 // For iteration of key/value pairs.
187 [[nodiscard]] const_iterator
188 begin() const
189 {
190 return lookup_.cbegin();
191 }
192
193 // For iteration of key/value pairs.
194 [[nodiscard]] const_iterator
195 cbegin() const
196 {
197 return lookup_.cbegin();
198 }
199
200 // For iteration of key/value pairs.
201 [[nodiscard]] const_iterator
202 end() const
203 {
204 return lookup_.cend();
205 }
206
207 // For iteration of key/value pairs.
208 [[nodiscard]] const_iterator
209 cend() const
210 {
211 return lookup_.cend();
212 }
213};
214
215//------------------------------------------------------------------------------
216
223{
224private:
226
227public:
231 [[nodiscard]] bool
232 exists(std::string const& name) const;
233
239 Section&
240 section(std::string const& name);
241
242 [[nodiscard]] Section const&
243 section(std::string const& name) const;
244
245 Section const&
246 operator[](std::string const& name) const
247 {
248 return section(name);
249 }
250
251 Section&
253 {
254 return section(name);
255 }
256
257
263 void
264 overwrite(std::string const& section, std::string const& key, std::string const& value);
265
269 void
271
281 void
282 legacy(std::string const& section, std::string value);
283
292 [[nodiscard]] std::string
293 legacy(std::string const& sectionName) const;
294
295 friend std::ostream&
296 operator<<(std::ostream& ss, BasicConfig const& c);
297
298 // indicates if trailing comments were seen
299 // in any loaded Sections
300 [[nodiscard]] bool
302 {
303 return std::ranges::any_of(map_, [](auto s) { return s.second.hadTrailingComments(); });
304 }
305
306protected:
307 void
308 build(IniFileSections const& ifs);
309};
310
311//------------------------------------------------------------------------------
312
319template <class T>
320bool
321set(T& target, std::string const& name, Section const& section)
322{
323 bool foundAndValid = false;
324 try
325 {
326 auto const val = section.get<T>(name);
327 foundAndValid = val.has_value();
328 if (foundAndValid)
329 target = *val;
330 }
331 catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
332 {
333 }
334 return foundAndValid;
335}
336
343template <class T>
344bool
345set(T& target, T const& defaultValue, std::string const& name, Section const& section)
346{
347 bool const foundAndValid = set<T>(target, name, section);
348 if (!foundAndValid)
349 target = defaultValue;
350 return foundAndValid;
351}
352
358// NOTE This routine might be more clumsy than the previous two
359template <class T = std::string>
360T
361get(Section const& section, std::string const& name, T const& defaultValue = T{})
362{
363 try
364 {
365 return section.valueOr<T>(name, defaultValue);
366 }
367 catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
368 {
369 }
370 return defaultValue;
371}
372
373inline std::string
374get(Section const& section, std::string const& name, char const* defaultValue)
375{
376 try
377 {
378 auto const val = section.get(name);
379 if (val.has_value())
380 return *val;
381 }
382 catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
383 {
384 }
385 return defaultValue;
386}
387
388template <class T>
389bool
390getIfExists(Section const& section, std::string const& name, T& v)
391{
392 return set<T>(v, name, section);
393}
394
395template <>
396inline bool
397getIfExists<bool>(Section const& section, std::string const& name, bool& v)
398{
399 int intVal = 0;
400 auto stat = getIfExists(section, name, intVal);
401 if (stat)
402 v = bool(intVal);
403 return stat;
404}
405
406} // namespace xrpl
T any_of(T... args)
Holds unparsed configuration information.
friend std::ostream & operator<<(std::ostream &ss, BasicConfig const &c)
Section const & operator[](std::string const &name) const
bool hadTrailingComments() const
void deprecatedClearSection(std::string const &section)
Remove all the key/value pairs from the section.
void build(IniFileSections const &ifs)
void overwrite(std::string const &section, std::string const &key, std::string const &value)
Overwrite a key/value pair with a command line argument If the section does not exist it is created.
std::unordered_map< std::string, Section > map_
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Section & operator[](std::string const &name)
void legacy(std::string const &section, std::string value)
Set a value that is not a key/value pair.
Section & section(std::string const &name)
Returns the section with the given name.
Holds a collection of configuration values.
Definition BasicConfig.h:29
Section(std::string name="")
Create an empty section.
const_iterator end() const
std::optional< T > get(std::string const &name) const
decltype(lookup_)::const_iterator const_iterator
Definition BasicConfig.h:37
const_iterator cbegin() const
bool hadTrailingComments_
Definition BasicConfig.h:35
bool empty() const
void append(std::string const &line)
Append a line to this section.
std::unordered_map< std::string, std::string > lookup_
Definition BasicConfig.h:32
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition BasicConfig.h:69
std::string const & name() const
Returns the name of this section.
Definition BasicConfig.h:49
std::vector< std::string > values_
Definition BasicConfig.h:34
std::vector< std::string > const & lines() const
Returns all the lines in the section.
Definition BasicConfig.h:59
std::string name_
Definition BasicConfig.h:31
friend std::ostream & operator<<(std::ostream &, Section const &section)
void set(std::string const &key, std::string const &value)
Set a key/value pair.
const_iterator begin() const
bool hadTrailingComments() const
std::size_t size() const
T valueOr(std::string const &name, T const &other) const
Returns a value if present, else another value.
std::string legacy() const
Get the legacy value for this section.
Definition BasicConfig.h:97
void legacy(std::string value)
Set the legacy value for this section.
Definition BasicConfig.h:78
std::vector< std::string > lines_
Definition BasicConfig.h:33
const_iterator cend() const
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
bool exists(std::string const &name) const
Returns true if a key with the given name exists.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
bool getIfExists< bool >(Section const &section, std::string const &name, bool &v)
bool getIfExists(Section const &section, std::string const &name, T &v)
Dir::ConstIterator const_iterator
Definition Dir.cpp:16
std::unordered_map< std::string, std::vector< std::string > > IniFileSections
Definition BasicConfig.h:20
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52