rippled
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 <ripple/basics/contract.h>
24 #include <boost/beast/core/string.hpp>
25 #include <boost/lexical_cast.hpp>
26 #include <boost/optional.hpp>
27 #include <algorithm>
28 #include <beast/unit_test/detail/const_container.hpp>
29 #include <map>
30 #include <ostream>
31 #include <string>
32 #include <vector>
33 
34 namespace ripple {
35 
37 
38 //------------------------------------------------------------------------------
39 
43 class Section : public beast::unit_test::detail::const_container<
44  std::map<std::string, std::string, boost::beast::iless>>
45 {
46 private:
50  bool had_trailing_comments_ = false;
51 
52 public:
54  explicit Section(std::string const& name = "");
55 
57  std::string const&
58  name() const
59  {
60  return name_;
61  }
62 
67  lines() const
68  {
69  return lines_;
70  }
71 
76  values() const
77  {
78  return values_;
79  }
80 
84  void
86  {
87  if (lines_.empty())
88  lines_.emplace_back(std::move(value));
89  else
90  lines_[0] = std::move(value);
91  }
92 
100  legacy() const
101  {
102  if (lines_.empty())
103  return "";
104  if (lines_.size() > 1)
105  Throw<std::runtime_error>(
106  "A legacy value must have exactly one line. Section: " + name_);
107  return lines_[0];
108  }
109 
113  void
114  set(std::string const& key, std::string const& value);
115 
121  void
123 
125  void
126  append(std::string const& line)
127  {
129  }
130 
132  bool
133  exists(std::string const& name) const;
134 
139  find(std::string const& name) const;
140 
141  template <class T>
142  boost::optional<T>
143  get(std::string const& name) const
144  {
145  auto const iter = cont().find(name);
146  if (iter == cont().end())
147  return boost::none;
148  return boost::lexical_cast<T>(iter->second);
149  }
150 
152  template <class T>
153  T
154  value_or(std::string const& name, T const& other) const
155  {
156  auto const v = get<T>(name);
157  return v.is_initialized() ? *v : other;
158  }
159 
160  // indicates if trailing comments were seen
161  // during the appending of any lines/values
162  bool
164  {
165  return had_trailing_comments_;
166  }
167 
168  friend std::ostream&
169  operator<<(std::ostream&, Section const& section);
170 };
171 
172 //------------------------------------------------------------------------------
173 
179 {
180 private:
182 
183 public:
185  bool
186  exists(std::string const& name) const;
187 
192  Section&
193  section(std::string const& name);
194 
195  Section const&
196  section(std::string const& name) const;
197 
198  Section const&
199  operator[](std::string const& name) const
200  {
201  return section(name);
202  }
203 
204  Section&
205  operator[](std::string const& name)
206  {
207  return section(name);
208  }
215  void
216  overwrite(
217  std::string const& section,
218  std::string const& key,
219  std::string const& value);
220 
223  void
225 
235  void
236  legacy(std::string const& section, std::string value);
237 
247  legacy(std::string const& sectionName) const;
248 
249  friend std::ostream&
250  operator<<(std::ostream& ss, BasicConfig const& c);
251 
252  // indicates if trailing comments were seen
253  // in any loaded Sections
254  bool
256  {
257  return std::any_of(map_.cbegin(), map_.cend(), [](auto s) {
258  return s.second.had_trailing_comments();
259  });
260  }
261 
262 protected:
263  void
264  build(IniFileSections const& ifs);
265 };
266 
267 //------------------------------------------------------------------------------
268 
274 template <class T>
275 bool
276 set(T& target, std::string const& name, Section const& section)
277 {
278  bool found_and_valid = false;
279  try
280  {
281  auto const val = section.get<T>(name);
282  if ((found_and_valid = val.is_initialized()))
283  target = *val;
284  }
285  catch (boost::bad_lexical_cast&)
286  {
287  }
288  return found_and_valid;
289 }
290 
296 template <class T>
297 bool
298 set(T& target,
299  T const& defaultValue,
300  std::string const& name,
301  Section const& section)
302 {
303  bool found_and_valid = set<T>(target, name, section);
304  if (!found_and_valid)
305  target = defaultValue;
306  return found_and_valid;
307 }
308 
313 // NOTE This routine might be more clumsy than the previous two
314 template <class T>
315 T
316 get(Section const& section,
317  std::string const& name,
318  T const& defaultValue = T{})
319 {
320  try
321  {
322  return section.value_or<T>(name, defaultValue);
323  }
324  catch (boost::bad_lexical_cast&)
325  {
326  }
327  return defaultValue;
328 }
329 
330 inline std::string
331 get(Section const& section, std::string const& name, const char* defaultValue)
332 {
333  try
334  {
335  auto const val = section.get<std::string>(name);
336  if (val.is_initialized())
337  return *val;
338  }
339  catch (boost::bad_lexical_cast&)
340  {
341  }
342  return defaultValue;
343 }
344 
345 template <class T>
346 bool
347 get_if_exists(Section const& section, std::string const& name, T& v)
348 {
349  return set<T>(v, name, section);
350 }
351 
352 template <>
353 inline bool
354 get_if_exists<bool>(Section const& section, std::string const& name, bool& v)
355 {
356  int intVal = 0;
357  auto stat = get_if_exists(section, name, intVal);
358  if (stat)
359  v = bool(intVal);
360  return stat;
361 }
362 
363 } // namespace ripple
364 
365 #endif
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:43
ripple::BasicConfig::had_trailing_comments
bool had_trailing_comments() const
Definition: BasicConfig.h:255
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::string
STL class.
std::pair
ripple::BasicConfig::operator[]
Section const & operator[](std::string const &name) const
Definition: BasicConfig.h:199
vector
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::value_or
T value_or(std::string const &name, T const &other) const
Returns a value if present, else another value.
Definition: BasicConfig.h:154
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::Section::had_trailing_comments
bool had_trailing_comments() const
Definition: BasicConfig.h:163
std::any_of
T any_of(T... args)
algorithm
ripple::Section::values
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition: BasicConfig.h:76
ripple::get_if_exists
bool get_if_exists(Section const &section, std::string const &name, T &v)
Definition: BasicConfig.h:347
ripple::Section::append
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
Definition: BasicConfig.cpp:40
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
ripple::BasicConfig::operator<<
friend std::ostream & operator<<(std::ostream &ss, BasicConfig const &c)
Definition: BasicConfig.cpp:200
std::ostream
STL class.
ripple::BasicConfig::build
void build(IniFileSections const &ifs)
Definition: BasicConfig.cpp:187
ripple::set
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,...
Definition: BasicConfig.h:276
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
map
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::BasicConfig::operator[]
Section & operator[](std::string const &name)
Definition: BasicConfig.h:205
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Section::get
boost::optional< T > get(std::string const &name) const
Definition: BasicConfig.h:143
ripple::Section::set
void set(std::string const &key, std::string const &value)
Set a key/value pair.
Definition: BasicConfig.cpp:32
ripple::Section::operator<<
friend std::ostream & operator<<(std::ostream &, Section const &section)
Definition: BasicConfig.cpp:122
ripple::Section::name_
std::string name_
Definition: BasicConfig.h:47
ripple::Section::legacy
std::string legacy() const
Get the legacy value for this section.
Definition: BasicConfig.h:100
std::vector::empty
T empty(T... args)
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
ostream
ripple::get_if_exists< bool >
bool get_if_exists< bool >(Section const &section, std::string const &name, bool &v)
Definition: BasicConfig.h:354
ripple::BasicConfig
Holds unparsed configuration information.
Definition: BasicConfig.h:178
ripple::Section::append
void append(std::string const &line)
Append a line to this section.
Definition: BasicConfig.h:126
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::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:116
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:138
string