rippled
BasicConfig.cpp
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 #include <ripple/basics/BasicConfig.h>
21 #include <ripple/basics/StringUtilities.h>
22 #include <boost/regex.hpp>
23 #include <algorithm>
24 
25 namespace ripple {
26 
27 Section::Section(std::string const& name) : name_(name)
28 {
29 }
30 
31 void
32 Section::set(std::string const& key, std::string const& value)
33 {
34  lookup_.insert_or_assign(key, value);
35 }
36 
37 void
39 {
40  // <key> '=' <value>
41  static boost::regex const re1(
42  "^" // start of line
43  "(?:\\s*)" // whitespace (optonal)
44  "([a-zA-Z][_a-zA-Z0-9]*)" // <key>
45  "(?:\\s*)" // whitespace (optional)
46  "(?:=)" // '='
47  "(?:\\s*)" // whitespace (optional)
48  "(.*\\S+)" // <value>
49  "(?:\\s*)" // whitespace (optional)
50  ,
51  boost::regex_constants::optimize);
52 
54  for (auto line : lines)
55  {
56  auto remove_comment = [](std::string& val) -> bool {
57  bool removed_trailing = false;
58  auto comment = val.find('#');
59  while (comment != std::string::npos)
60  {
61  if (comment == 0)
62  {
63  // entire value is a comment. In most cases, this
64  // would have already been handled by the file reader
65  val = "";
66  break;
67  }
68  else if (val.at(comment - 1) == '\\')
69  {
70  // we have an escaped comment char. Erase the escape char
71  // and keep looking
72  val.erase(comment - 1, 1);
73  }
74  else
75  {
76  // this must be a real comment. Extract the value
77  // as a substring and stop looking.
78  val = trim_whitespace(val.substr(0, comment));
79  removed_trailing = true;
80  break;
81  }
82 
83  comment = val.find('#', comment);
84  }
85  return removed_trailing;
86  };
87 
88  if (remove_comment(line) && !line.empty())
90 
91  if (line.empty())
92  continue;
93 
94  boost::smatch match;
95  if (boost::regex_match(line, match, re1))
96  set(match[1], match[2]);
97  else
98  values_.push_back(line);
99 
100  lines_.push_back(std::move(line));
101  }
102 }
103 
104 bool
105 Section::exists(std::string const& name) const
106 {
107  return lookup_.find(name) != lookup_.end();
108 }
109 
111 operator<<(std::ostream& os, Section const& section)
112 {
113  for (auto const& [k, v] : section.lookup_)
114  os << k << "=" << v << "\n";
115  return os;
116 }
117 
118 //------------------------------------------------------------------------------
119 
120 bool
122 {
123  return map_.find(name) != map_.end();
124 }
125 
126 Section&
128 {
129  return map_[name];
130 }
131 
132 Section const&
134 {
135  static Section none("");
136  auto const iter = map_.find(name);
137  if (iter == map_.end())
138  return none;
139  return iter->second;
140 }
141 
142 void
144  std::string const& section,
145  std::string const& key,
146  std::string const& value)
147 {
148  auto const result = map_.emplace(
149  std::piecewise_construct,
152  result.first->second.set(key, value);
153 }
154 
155 void
157 {
158  auto i = map_.find(section);
159  if (i != map_.end())
160  i->second = Section(section);
161 }
162 
163 void
165 {
166  map_[section].legacy(std::move(value));
167 }
168 
170 BasicConfig::legacy(std::string const& sectionName) const
171 {
172  return section(sectionName).legacy();
173 }
174 
175 void
177 {
178  for (auto const& entry : ifs)
179  {
180  auto const result = map_.emplace(
181  std::piecewise_construct,
182  std::make_tuple(entry.first),
183  std::make_tuple(entry.first));
184  result.first->second.append(entry.second);
185  }
186 }
187 
190 {
191  for (auto const& [k, v] : c.map_)
192  ss << "[" << k << "]\n" << v;
193  return ss;
194 }
195 
196 } // namespace ripple
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
ripple::Section::values_
std::vector< std::string > values_
Definition: BasicConfig.h:48
ripple::Section::legacy
void legacy(std::string value)
Set the legacy value for this section.
Definition: BasicConfig.h:86
std::make_tuple
T make_tuple(T... args)
std::string
STL class.
std::vector::reserve
T reserve(T... args)
std::vector< std::string >
std::string::find
T find(T... args)
std::vector::size
T size(T... args)
ripple::Section::Section
Section(std::string const &name="")
Create an empty section.
Definition: BasicConfig.cpp:27
ripple::Section::exists
bool exists(std::string const &name) const
Returns true if a key with the given name exists.
Definition: BasicConfig.cpp:105
ripple::trim_whitespace
std::string trim_whitespace(std::string str)
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:242
algorithm
ripple::Section::append
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
Definition: BasicConfig.cpp:38
std::vector::push_back
T push_back(T... args)
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:59
std::map::insert_or_assign
T insert_or_assign(T... args)
ripple::BasicConfig::deprecatedClearSection
void deprecatedClearSection(std::string const &section)
Remove all the key/value pairs from the section.
Definition: BasicConfig.cpp:156
std::ostream
STL class.
ripple::JsonOptions::none
@ none
ripple::BasicConfig::build
void build(IniFileSections const &ifs)
Definition: BasicConfig.cpp:176
ripple::BasicConfig::legacy
void legacy(std::string const &section, std::string value)
Set a value that is not a key/value pair.
Definition: BasicConfig.cpp:164
ripple::Section::lines
std::vector< std::string > const & lines() const
Returns all the lines in the section.
Definition: BasicConfig.h:68
std::map
STL class.
ripple::Section::had_trailing_comments_
bool had_trailing_comments_
Definition: BasicConfig.h:49
ripple::BasicConfig::overwrite
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.
Definition: BasicConfig.cpp:143
ripple::Section::lookup_
std::map< std::string, std::string > lookup_
Definition: BasicConfig.h:46
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Section::set
void set(std::string const &key, std::string const &value)
Set a key/value pair.
Definition: BasicConfig.cpp:32
ripple::Section::lines_
std::vector< std::string > lines_
Definition: BasicConfig.h:47
std::map::end
T end(T... args)
ripple::BasicConfig::map_
std::map< std::string, Section, boost::beast::iless > map_
Definition: BasicConfig.h:218
ripple::BasicConfig
Holds unparsed configuration information.
Definition: BasicConfig.h:215
ripple::BasicConfig::exists
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Definition: BasicConfig.cpp:121
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:127