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