rippled
Loading...
Searching...
No Matches
BasicConfig.cpp
1#include <xrpl/basics/BasicConfig.h>
2#include <xrpl/basics/StringUtilities.h>
3
4#include <boost/regex/v5/regbase.hpp>
5#include <boost/regex/v5/regex.hpp>
6#include <boost/regex/v5/regex_fwd.hpp>
7#include <boost/regex/v5/regex_match.hpp>
8
9#include <ostream>
10#include <string>
11#include <tuple>
12#include <utility>
13#include <vector>
14
15namespace ripple {
16
17Section::Section(std::string const& name) : name_(name)
18{
19}
20
21void
22Section::set(std::string const& key, std::string const& value)
23{
24 lookup_.insert_or_assign(key, value);
25}
26
27void
29{
30 // <key> '=' <value>
31 static boost::regex const re1(
32 "^" // start of line
33 "(?:\\s*)" // whitespace (optional)
34 "([a-zA-Z][_a-zA-Z0-9]*)" // <key>
35 "(?:\\s*)" // whitespace (optional)
36 "(?:=)" // '='
37 "(?:\\s*)" // whitespace (optional)
38 "(.*\\S+)" // <value>
39 "(?:\\s*)" // whitespace (optional)
40 ,
41 boost::regex_constants::optimize);
42
44 for (auto line : lines)
45 {
46 auto remove_comment = [](std::string& val) -> bool {
47 bool removed_trailing = false;
48 auto comment = val.find('#');
49 while (comment != std::string::npos)
50 {
51 if (comment == 0)
52 {
53 // entire value is a comment. In most cases, this
54 // would have already been handled by the file reader
55 val = "";
56 break;
57 }
58 else if (val.at(comment - 1) == '\\')
59 {
60 // we have an escaped comment char. Erase the escape char
61 // and keep looking
62 val.erase(comment - 1, 1);
63 }
64 else
65 {
66 // this must be a real comment. Extract the value
67 // as a substring and stop looking.
68 val = trim_whitespace(val.substr(0, comment));
69 removed_trailing = true;
70 break;
71 }
72
73 comment = val.find('#', comment);
74 }
75 return removed_trailing;
76 };
77
78 if (remove_comment(line) && !line.empty())
80
81 if (line.empty())
82 continue;
83
84 boost::smatch match;
85 if (boost::regex_match(line, match, re1))
86 set(match[1], match[2]);
87 else
88 values_.push_back(line);
89
90 lines_.push_back(std::move(line));
91 }
92}
93
94bool
95Section::exists(std::string const& name) const
96{
97 return lookup_.contains(name);
98}
99
101operator<<(std::ostream& os, Section const& section)
102{
103 for (auto const& [k, v] : section.lookup_)
104 os << k << "=" << v << "\n";
105 return os;
106}
107
108//------------------------------------------------------------------------------
109
110bool
112{
113 return map_.contains(name);
114}
115
116Section&
118{
119 return map_.emplace(name, name).first->second;
120}
121
122Section const&
124{
125 static Section none("");
126 auto const iter = map_.find(name);
127 if (iter == map_.end())
128 return none;
129 return iter->second;
130}
131
132void
134 std::string const& section,
135 std::string const& key,
136 std::string const& value)
137{
138 auto const result = map_.emplace(
142 result.first->second.set(key, value);
143}
144
145void
147{
148 auto i = map_.find(section);
149 if (i != map_.end())
150 i->second = Section(section);
151}
152
153void
155{
156 map_.emplace(section, section).first->second.legacy(std::move(value));
157}
158
160BasicConfig::legacy(std::string const& sectionName) const
161{
162 return section(sectionName).legacy();
163}
164
165void
167{
168 for (auto const& entry : ifs)
169 {
170 auto const result = map_.emplace(
172 std::make_tuple(entry.first),
173 std::make_tuple(entry.first));
174 result.first->second.append(entry.second);
175 }
176}
177
180{
181 for (auto const& [k, v] : c.map_)
182 ss << "[" << k << "]\n" << v;
183 return ss;
184}
185
186} // namespace ripple
Holds unparsed configuration information.
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
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.
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:26
std::string const & name() const
Returns the name of this section.
Definition BasicConfig.h:42
void set(std::string const &key, std::string const &value)
Set a key/value pair.
std::vector< std::string > lines_
Definition BasicConfig.h:30
std::vector< std::string > const & lines() const
Returns all the lines in the section.
Definition BasicConfig.h:51
void legacy(std::string value)
Set the legacy value for this section.
Definition BasicConfig.h:69
bool exists(std::string const &name) const
Returns true if a key with the given name exists.
bool had_trailing_comments_
Definition BasicConfig.h:32
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
Section(std::string const &name="")
Create an empty section.
std::unordered_map< std::string, std::string > lookup_
Definition BasicConfig.h:29
std::vector< std::string > values_
Definition BasicConfig.h:31
T contains(T... args)
T find(T... args)
T insert_or_assign(T... args)
T make_tuple(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::string trim_whitespace(std::string str)
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:628
T piecewise_construct
T push_back(T... args)
T reserve(T... args)
T size(T... args)