rippled
Loading...
Searching...
No Matches
BasicConfig.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_BASICS_BASICCONFIG_H_INCLUDED
21#define RIPPLE_BASICS_BASICCONFIG_H_INCLUDED
22
23#include <xrpl/basics/contract.h>
24
25#include <boost/beast/core/string.hpp>
26#include <boost/lexical_cast.hpp>
27
28#include <algorithm>
29#include <optional>
30#include <string>
31#include <unordered_map>
32#include <vector>
33
34namespace ripple {
35
38
39//------------------------------------------------------------------------------
40
45{
46private:
52
54
55public:
57 explicit Section(std::string const& name = "");
58
60 std::string const&
61 name() const
62 {
63 return name_;
64 }
65
70 lines() const
71 {
72 return lines_;
73 }
74
79 values() const
80 {
81 return values_;
82 }
83
87 void
89 {
90 if (lines_.empty())
91 lines_.emplace_back(std::move(value));
92 else
93 lines_[0] = std::move(value);
94 }
95
103 legacy() const
104 {
105 if (lines_.empty())
106 return "";
107 if (lines_.size() > 1)
108 Throw<std::runtime_error>(
109 "A legacy value must have exactly one line. Section: " + name_);
110 return lines_[0];
111 }
112
116 void
117 set(std::string const& key, std::string const& value);
118
124 void
126
128 void
129 append(std::string const& line)
130 {
132 }
133
135 bool
136 exists(std::string const& name) const;
137
138 template <class T = std::string>
140 get(std::string const& name) const
141 {
142 auto const iter = lookup_.find(name);
143 if (iter == lookup_.end())
144 return std::nullopt;
145 return boost::lexical_cast<T>(iter->second);
146 }
147
149 template <class T>
150 T
151 value_or(std::string const& name, T const& other) const
152 {
153 auto const v = get<T>(name);
154 return v.has_value() ? *v : other;
155 }
156
157 // indicates if trailing comments were seen
158 // during the appending of any lines/values
159 bool
161 {
163 }
164
165 friend std::ostream&
166 operator<<(std::ostream&, Section const& section);
167
168 // Returns `true` if there are no key/value pairs.
169 bool
170 empty() const
171 {
172 return lookup_.empty();
173 }
174
175 // Returns the number of key/value pairs.
177 size() const
178 {
179 return lookup_.size();
180 }
181
182 // For iteration of key/value pairs.
184 begin() const
185 {
186 return lookup_.cbegin();
187 }
188
189 // For iteration of key/value pairs.
191 cbegin() const
192 {
193 return lookup_.cbegin();
194 }
195
196 // For iteration of key/value pairs.
198 end() const
199 {
200 return lookup_.cend();
201 }
202
203 // For iteration of key/value pairs.
205 cend() const
206 {
207 return lookup_.cend();
208 }
209};
210
211//------------------------------------------------------------------------------
212
218{
219private:
221
222public:
224 bool
225 exists(std::string const& name) const;
226
231 Section&
232 section(std::string const& name);
233
234 Section const&
235 section(std::string const& name) const;
236
237 Section const&
238 operator[](std::string const& name) const
239 {
240 return section(name);
241 }
242
243 Section&
245 {
246 return section(name);
247 }
254 void
255 overwrite(
256 std::string const& section,
257 std::string const& key,
258 std::string const& value);
259
262 void
264
274 void
275 legacy(std::string const& section, std::string value);
276
286 legacy(std::string const& sectionName) const;
287
288 friend std::ostream&
289 operator<<(std::ostream& ss, BasicConfig const& c);
290
291 // indicates if trailing comments were seen
292 // in any loaded Sections
293 bool
295 {
296 return std::any_of(map_.cbegin(), map_.cend(), [](auto s) {
297 return s.second.had_trailing_comments();
298 });
299 }
300
301protected:
302 void
303 build(IniFileSections const& ifs);
304};
305
306//------------------------------------------------------------------------------
307
313template <class T>
314bool
315set(T& target, std::string const& name, Section const& section)
316{
317 bool found_and_valid = false;
318 try
319 {
320 auto const val = section.get<T>(name);
321 if ((found_and_valid = val.has_value()))
322 target = *val;
323 }
324 catch (boost::bad_lexical_cast&)
325 {
326 }
327 return found_and_valid;
328}
329
335template <class T>
336bool
337set(T& target,
338 T const& defaultValue,
339 std::string const& name,
340 Section const& section)
341{
342 bool found_and_valid = set<T>(target, name, section);
343 if (!found_and_valid)
344 target = defaultValue;
345 return found_and_valid;
346}
347
352// NOTE This routine might be more clumsy than the previous two
353template <class T = std::string>
354T
355get(Section const& section,
356 std::string const& name,
357 T const& defaultValue = T{})
358{
359 try
360 {
361 return section.value_or<T>(name, defaultValue);
362 }
363 catch (boost::bad_lexical_cast&)
364 {
365 }
366 return defaultValue;
367}
368
369inline std::string
370get(Section const& section, std::string const& name, char const* defaultValue)
371{
372 try
373 {
374 auto const val = section.get(name);
375 if (val.has_value())
376 return *val;
377 }
378 catch (boost::bad_lexical_cast&)
379 {
380 }
381 return defaultValue;
382}
383
384template <class T>
385bool
386get_if_exists(Section const& section, std::string const& name, T& v)
387{
388 return set<T>(v, name, section);
389}
390
391template <>
392inline bool
393get_if_exists<bool>(Section const& section, std::string const& name, bool& v)
394{
395 int intVal = 0;
396 auto stat = get_if_exists(section, name, intVal);
397 if (stat)
398 v = bool(intVal);
399 return stat;
400}
401
402} // namespace ripple
403
404#endif
T any_of(T... args)
T cbegin(T... args)
Holds unparsed configuration information.
friend std::ostream & operator<<(std::ostream &ss, BasicConfig const &c)
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
bool had_trailing_comments() const
Section const & operator[](std::string const &name) const
void deprecatedClearSection(std::string const &section)
Remove all the key/value pairs from the section.
Section & section(std::string const &name)
Returns the section with the given name.
void build(IniFileSections const &ifs)
std::unordered_map< std::string, Section > map_
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.
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.
Holds a collection of configuration values.
Definition BasicConfig.h:45
std::string const & name() const
Returns the name of this section.
Definition BasicConfig.h:61
std::size_t size() const
std::string legacy() const
Get the legacy value for this section.
std::vector< std::string > lines_
Definition BasicConfig.h:49
friend std::ostream & operator<<(std::ostream &, Section const &section)
const_iterator begin() const
decltype(lookup_)::const_iterator const_iterator
Definition BasicConfig.h:53
const_iterator cend() const
bool had_trailing_comments() const
T value_or(std::string const &name, T const &other) const
Returns a value if present, else another value.
std::vector< std::string > const & lines() const
Returns all the lines in the section.
Definition BasicConfig.h:70
void legacy(std::string value)
Set the legacy value for this section.
Definition BasicConfig.h:88
std::optional< T > get(std::string const &name) const
bool exists(std::string const &name) const
Returns true if a key with the given name exists.
void append(std::string const &line)
Append a line to this section.
const_iterator cbegin() const
bool had_trailing_comments_
Definition BasicConfig.h:51
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition BasicConfig.h:79
std::string name_
Definition BasicConfig.h:47
std::unordered_map< std::string, std::string > lookup_
Definition BasicConfig.h:48
std::vector< std::string > values_
Definition BasicConfig.h:50
const_iterator end() const
bool empty() const
T emplace_back(T... args)
T empty(T... args)
T end(T... args)
T find(T... args)
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
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,...
bool get_if_exists(Section const &section, std::string const &name, T &v)
bool get_if_exists< bool >(Section const &section, std::string const &name, bool &v)
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
T size(T... args)