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 xrpl {
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 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 {
87 set(match[1], match[2]);
88 }
89 else
90 {
91 values_.push_back(line);
92 }
93
94 lines_.push_back(std::move(line));
95 }
96}
97
98bool
99Section::exists(std::string const& name) const
100{
101 return lookup_.contains(name);
102}
103
105operator<<(std::ostream& os, Section const& section)
106{
107 for (auto const& [k, v] : section.lookup_)
108 os << k << "=" << v << "\n";
109 return os;
110}
111
112//------------------------------------------------------------------------------
113
114bool
116{
117 return map_.contains(name);
118}
119
120Section&
122{
123 return map_.emplace(name, name).first->second;
124}
125
126Section const&
128{
129 static Section const none("");
130 auto const iter = map_.find(name);
131 if (iter == map_.end())
132 return none;
133 return iter->second;
134}
135
136void
137BasicConfig::overwrite(std::string const& section, std::string const& key, std::string const& value)
138{
139 auto const result =
141 result.first->second.set(key, value);
142}
143
144void
146{
147 auto i = map_.find(section);
148 if (i != map_.end())
149 i->second = Section(section);
150}
151
152void
154{
155 map_.emplace(section, section).first->second.legacy(std::move(value));
156}
157
159BasicConfig::legacy(std::string const& sectionName) const
160{
161 return section(sectionName).legacy();
162}
163
164void
166{
167 for (auto const& entry : ifs)
168 {
169 auto const result = map_.emplace(
170 std::piecewise_construct, std::make_tuple(entry.first), std::make_tuple(entry.first));
171 result.first->second.append(entry.second);
172 }
173}
174
177{
178 for (auto const& [k, v] : c.map_)
179 ss << "[" << k << "]\n" << v;
180 return ss;
181}
182
183} // namespace xrpl
Holds unparsed configuration information.
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.
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
std::unordered_map< std::string, std::string > lookup_
Definition BasicConfig.h:27
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
Section(std::string const &name="")
Create an empty section.
void set(std::string const &key, std::string const &value)
Set a key/value pair.
void legacy(std::string value)
Set the legacy value for this section.
Definition BasicConfig.h:67
bool had_trailing_comments_
Definition BasicConfig.h:30
std::vector< std::string > lines_
Definition BasicConfig.h:28
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.
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:5
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:617
std::string trim_whitespace(std::string str)
T piecewise_construct
T push_back(T... args)
T reserve(T... args)
T size(T... args)