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 <algorithm>
27 #include <map>
28 #include <optional>
29 #include <ostream>
30 #include <string>
31 #include <vector>
32 
33 namespace ripple {
34 
36 
37 //------------------------------------------------------------------------------
38 
42 class Section
43 {
44 private:
49  bool had_trailing_comments_ = false;
50 
52 
53 public:
55  explicit Section(std::string const& name = "");
56 
58  std::string const&
59  name() const
60  {
61  return name_;
62  }
63 
68  lines() const
69  {
70  return lines_;
71  }
72 
77  values() const
78  {
79  return values_;
80  }
81 
85  void
87  {
88  if (lines_.empty())
89  lines_.emplace_back(std::move(value));
90  else
91  lines_[0] = std::move(value);
92  }
93 
101  legacy() const
102  {
103  if (lines_.empty())
104  return "";
105  if (lines_.size() > 1)
106  Throw<std::runtime_error>(
107  "A legacy value must have exactly one line. Section: " + name_);
108  return lines_[0];
109  }
110 
114  void
115  set(std::string const& key, std::string const& value);
116 
122  void
124 
126  void
127  append(std::string const& line)
128  {
130  }
131 
133  bool
134  exists(std::string const& name) const;
135 
136  template <class T = std::string>
138  get(std::string const& name) const
139  {
140  auto const iter = lookup_.find(name);
141  if (iter == lookup_.end())
142  return std::nullopt;
143  return boost::lexical_cast<T>(iter->second);
144  }
145 
147  template <class T>
148  T
149  value_or(std::string const& name, T const& other) const
150  {
151  auto const v = get<T>(name);
152  return v.has_value() ? *v : other;
153  }
154 
155  // indicates if trailing comments were seen
156  // during the appending of any lines/values
157  bool
159  {
160  return had_trailing_comments_;
161  }
162 
163  friend std::ostream&
164  operator<<(std::ostream&, Section const& section);
165 
166  // Returns `true` if there are no key/value pairs.
167  bool
168  empty() const
169  {
170  return lookup_.empty();
171  }
172 
173  // Returns the number of key/value pairs.
175  size() const
176  {
177  return lookup_.size();
178  }
179 
180  // For iteration of key/value pairs.
182  begin() const
183  {
184  return lookup_.cbegin();
185  }
186 
187  // For iteration of key/value pairs.
189  cbegin() const
190  {
191  return lookup_.cbegin();
192  }
193 
194  // For iteration of key/value pairs.
196  end() const
197  {
198  return lookup_.cend();
199  }
200 
201  // For iteration of key/value pairs.
203  cend() const
204  {
205  return lookup_.cend();
206  }
207 };
208 
209 //------------------------------------------------------------------------------
210 
216 {
217 private:
219 
220 public:
222  bool
223  exists(std::string const& name) const;
224 
229  Section&
230  section(std::string const& name);
231 
232  Section const&
233  section(std::string const& name) const;
234 
235  Section const&
236  operator[](std::string const& name) const
237  {
238  return section(name);
239  }
240 
241  Section&
242  operator[](std::string const& name)
243  {
244  return section(name);
245  }
252  void
253  overwrite(
254  std::string const& section,
255  std::string const& key,
256  std::string const& value);
257 
260  void
262 
272  void
273  legacy(std::string const& section, std::string value);
274 
284  legacy(std::string const& sectionName) const;
285 
286  friend std::ostream&
287  operator<<(std::ostream& ss, BasicConfig const& c);
288 
289  // indicates if trailing comments were seen
290  // in any loaded Sections
291  bool
293  {
294  return std::any_of(map_.cbegin(), map_.cend(), [](auto s) {
295  return s.second.had_trailing_comments();
296  });
297  }
298 
299 protected:
300  void
301  build(IniFileSections const& ifs);
302 };
303 
304 //------------------------------------------------------------------------------
305 
311 template <class T>
312 bool
313 set(T& target, std::string const& name, Section const& section)
314 {
315  bool found_and_valid = false;
316  try
317  {
318  auto const val = section.get<T>(name);
319  if ((found_and_valid = val.has_value()))
320  target = *val;
321  }
322  catch (boost::bad_lexical_cast&)
323  {
324  }
325  return found_and_valid;
326 }
327 
333 template <class T>
334 bool
335 set(T& target,
336  T const& defaultValue,
337  std::string const& name,
338  Section const& section)
339 {
340  bool found_and_valid = set<T>(target, name, section);
341  if (!found_and_valid)
342  target = defaultValue;
343  return found_and_valid;
344 }
345 
350 // NOTE This routine might be more clumsy than the previous two
351 template <class T = std::string>
352 T
353 get(Section const& section,
354  std::string const& name,
355  T const& defaultValue = T{})
356 {
357  try
358  {
359  return section.value_or<T>(name, defaultValue);
360  }
361  catch (boost::bad_lexical_cast&)
362  {
363  }
364  return defaultValue;
365 }
366 
367 inline std::string
368 get(Section const& section, std::string const& name, const char* defaultValue)
369 {
370  try
371  {
372  auto const val = section.get(name);
373  if (val.has_value())
374  return *val;
375  }
376  catch (boost::bad_lexical_cast&)
377  {
378  }
379  return defaultValue;
380 }
381 
382 template <class T>
383 bool
384 get_if_exists(Section const& section, std::string const& name, T& v)
385 {
386  return set<T>(v, name, section);
387 }
388 
389 template <>
390 inline bool
391 get_if_exists<bool>(Section const& section, std::string const& name, bool& v)
392 {
393  int intVal = 0;
394  auto stat = get_if_exists(section, name, intVal);
395  if (stat)
396  v = bool(intVal);
397  return stat;
398 }
399 
400 } // namespace ripple
401 
402 #endif
ripple::Section::const_iterator
decltype(lookup_)::const_iterator const_iterator
Definition: BasicConfig.h:51
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
ripple::BasicConfig::had_trailing_comments
bool had_trailing_comments() const
Definition: BasicConfig.h:292
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
ripple::Dir::const_iterator
Definition: Directory.h:49
std::string
STL class.
ripple::BasicConfig::operator[]
Section const & operator[](std::string const &name) const
Definition: BasicConfig.h:236
vector
std::map::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::cend
const_iterator cend() const
Definition: BasicConfig.h:203
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:149
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::Section::had_trailing_comments
bool had_trailing_comments() const
Definition: BasicConfig.h:158
std::any_of
T any_of(T... args)
algorithm
ripple::Section::begin
const_iterator begin() const
Definition: BasicConfig.h:182
ripple::Section::values
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition: BasicConfig.h:77
ripple::get_if_exists
bool get_if_exists(Section const &section, std::string const &name, T &v)
Definition: BasicConfig.h:384
ripple::Section::append
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
Definition: BasicConfig.cpp:38
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:59
ripple::Section::end
const_iterator end() const
Definition: BasicConfig.h:196
ripple::Section::size
std::size_t size() const
Definition: BasicConfig.h:175
ripple::BasicConfig::deprecatedClearSection
void deprecatedClearSection(std::string const &section)
Remove all the key/value pairs from the section.
Definition: BasicConfig.cpp:156
ripple::Section::empty
bool empty() const
Definition: BasicConfig.h:168
ripple::BasicConfig::operator<<
friend std::ostream & operator<<(std::ostream &ss, BasicConfig const &c)
Definition: BasicConfig.cpp:189
std::ostream
STL class.
ripple::BasicConfig::build
void build(IniFileSections const &ifs)
Definition: BasicConfig.cpp:176
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:313
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
ripple::Section::cbegin
const_iterator cbegin() const
Definition: BasicConfig.h:189
map
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::BasicConfig::operator[]
Section & operator[](std::string const &name)
Definition: BasicConfig.h:242
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::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:111
std::map::cbegin
T cbegin(T... args)
ripple::Section::name_
std::string name_
Definition: BasicConfig.h:45
ripple::Section::legacy
std::string legacy() const
Get the legacy value for this section.
Definition: BasicConfig.h:101
ripple::Section::get
std::optional< T > get(std::string const &name) const
Definition: BasicConfig.h:138
std::vector::empty
T empty(T... args)
optional
std::size_t
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
ostream
ripple::get_if_exists< bool >
bool get_if_exists< bool >(Section const &section, std::string const &name, bool &v)
Definition: BasicConfig.h:391
ripple::BasicConfig
Holds unparsed configuration information.
Definition: BasicConfig.h:215
ripple::Section::append
void append(std::string const &line)
Append a line to this section.
Definition: BasicConfig.h:127
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::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:118
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:127
string