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 <optional>
10#include <string>
11#include <unordered_map>
12#include <vector>
13
14namespace xrpl {
15
17
18//------------------------------------------------------------------------------
19
24{
25private:
31
33
34public:
36 explicit Section(std::string name = "");
37
39 [[nodiscard]] std::string const&
40 name() const
41 {
42 return name_;
43 }
44
48 [[nodiscard]] std::vector<std::string> const&
49 lines() const
50 {
51 return lines_;
52 }
53
57 [[nodiscard]] std::vector<std::string> const&
58 values() const
59 {
60 return values_;
61 }
62
66 void
68 {
69 if (lines_.empty())
70 {
71 lines_.emplace_back(std::move(value));
72 }
73 else
74 {
75 lines_[0] = std::move(value);
76 }
77 }
78
85 [[nodiscard]] std::string
86 legacy() const
87 {
88 if (lines_.empty())
89 return "";
90 if (lines_.size() > 1)
91 {
93 "A legacy value must have exactly one line. Section: " + name_);
94 }
95 return lines_[0];
96 }
97
101 void
102 set(std::string const& key, std::string const& value);
103
109 void
111
113 void
114 append(std::string const& line)
115 {
117 }
118
120 [[nodiscard]] bool
121 exists(std::string const& name) const;
122
123 template <class T = std::string>
124 [[nodiscard]] std::optional<T>
125 get(std::string const& name) const
126 {
127 auto const iter = lookup_.find(name);
128 if (iter == lookup_.end())
129 return std::nullopt;
130 return boost::lexical_cast<T>(iter->second);
131 }
132
134 template <class T>
135 [[nodiscard]] T
136 valueOr(std::string const& name, T const& other) const
137 {
138 auto const v = get<T>(name);
139 return v.has_value() ? *v : other;
140 }
141
142 // indicates if trailing comments were seen
143 // during the appending of any lines/values
144 [[nodiscard]] bool
146 {
148 }
149
150 friend std::ostream&
151 operator<<(std::ostream&, Section const& section);
152
153 // Returns `true` if there are no key/value pairs.
154 [[nodiscard]] bool
155 empty() const
156 {
157 return lookup_.empty();
158 }
159
160 // Returns the number of key/value pairs.
161 [[nodiscard]] std::size_t
162 size() const
163 {
164 return lookup_.size();
165 }
166
167 // For iteration of key/value pairs.
168 [[nodiscard]] const_iterator
169 begin() const
170 {
171 return lookup_.cbegin();
172 }
173
174 // For iteration of key/value pairs.
175 [[nodiscard]] const_iterator
176 cbegin() const
177 {
178 return lookup_.cbegin();
179 }
180
181 // For iteration of key/value pairs.
182 [[nodiscard]] const_iterator
183 end() const
184 {
185 return lookup_.cend();
186 }
187
188 // For iteration of key/value pairs.
189 [[nodiscard]] const_iterator
190 cend() const
191 {
192 return lookup_.cend();
193 }
194};
195
196//------------------------------------------------------------------------------
197
203{
204private:
206
207public:
209 [[nodiscard]] bool
210 exists(std::string const& name) const;
211
216 Section&
217 section(std::string const& name);
218
219 [[nodiscard]] Section const&
220 section(std::string const& name) const;
221
222 Section const&
223 operator[](std::string const& name) const
224 {
225 return section(name);
226 }
227
228 Section&
230 {
231 return section(name);
232 }
233
234
239 void
240 overwrite(std::string const& section, std::string const& key, std::string const& value);
241
244 void
246
256 void
257 legacy(std::string const& section, std::string value);
258
267 [[nodiscard]] std::string
268 legacy(std::string const& sectionName) const;
269
270 friend std::ostream&
271 operator<<(std::ostream& ss, BasicConfig const& c);
272
273 // indicates if trailing comments were seen
274 // in any loaded Sections
275 [[nodiscard]] bool
277 {
278 return std::ranges::any_of(map_, [](auto s) { return s.second.hadTrailingComments(); });
279 }
280
281protected:
282 void
283 build(IniFileSections const& ifs);
284};
285
286//------------------------------------------------------------------------------
287
293template <class T>
294bool
295set(T& target, std::string const& name, Section const& section)
296{
297 bool foundAndValid = false;
298 try
299 {
300 auto const val = section.get<T>(name);
301 foundAndValid = val.has_value();
302 if (foundAndValid)
303 target = *val;
304 }
305 catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
306 {
307 }
308 return foundAndValid;
309}
310
316template <class T>
317bool
318set(T& target, T const& defaultValue, std::string const& name, Section const& section)
319{
320 bool const foundAndValid = set<T>(target, name, section);
321 if (!foundAndValid)
322 target = defaultValue;
323 return foundAndValid;
324}
325
330// NOTE This routine might be more clumsy than the previous two
331template <class T = std::string>
332T
333get(Section const& section, std::string const& name, T const& defaultValue = T{})
334{
335 try
336 {
337 return section.valueOr<T>(name, defaultValue);
338 }
339 catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
340 {
341 }
342 return defaultValue;
343}
344
345inline std::string
346get(Section const& section, std::string const& name, char const* defaultValue)
347{
348 try
349 {
350 auto const val = section.get(name);
351 if (val.has_value())
352 return *val;
353 }
354 catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
355 {
356 }
357 return defaultValue;
358}
359
360template <class T>
361bool
362getIfExists(Section const& section, std::string const& name, T& v)
363{
364 return set<T>(v, name, section);
365}
366
367template <>
368inline bool
369getIfExists<bool>(Section const& section, std::string const& name, bool& v)
370{
371 int intVal = 0;
372 auto stat = getIfExists(section, name, intVal);
373 if (stat)
374 v = bool(intVal);
375 return stat;
376}
377
378} // 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:24
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:32
const_iterator cbegin() const
bool hadTrailingComments_
Definition BasicConfig.h:30
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:27
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition BasicConfig.h:58
std::string const & name() const
Returns the name of this section.
Definition BasicConfig.h:40
std::vector< std::string > values_
Definition BasicConfig.h:29
std::vector< std::string > const & lines() const
Returns all the lines in the section.
Definition BasicConfig.h:49
std::string name_
Definition BasicConfig.h:26
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:86
void legacy(std::string value)
Set the legacy value for this section.
Definition BasicConfig.h:67
std::vector< std::string > lines_
Definition BasicConfig.h:28
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:16
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49