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 <beast/unit_test/detail/const_container.hpp>
25 #include <boost/beast/core/string.hpp>
26 #include <boost/lexical_cast.hpp>
27 #include <boost/optional.hpp>
28 #include <algorithm>
29 #include <map>
30 #include <ostream>
31 #include <string>
32 #include <vector>
33 
34 namespace ripple {
35 
37 
38 //------------------------------------------------------------------------------
39 
43 class Section
44  : public beast::unit_test::detail::const_container <
45  std::map <std::string, std::string, boost::beast::iless>>
46 {
47 private:
51  bool had_trailing_comments_ = false;
52 
53 public:
55  explicit
56  Section (std::string const& name = "");
57 
59  std::string const&
60  name() const
61  {
62  return name_;
63  }
64 
69  lines() const
70  {
71  return lines_;
72  }
73 
78  values() const
79  {
80  return values_;
81  }
82 
86  void
88  {
89  if (lines_.empty ())
90  lines_.emplace_back (std::move (value));
91  else
92  lines_[0] = std::move (value);
93  }
94 
102  legacy () const
103  {
104  if (lines_.empty ())
105  return "";
106  if (lines_.size () > 1)
107  Throw<std::runtime_error> (
108  "A legacy value must have exactly one line. Section: " + name_);
109  return lines_[0];
110  }
111 
115  void
116  set (std::string const& key, std::string const& value);
117 
123  void
125 
127  void
128  append (std::string const& line)
129  {
131  }
132 
134  bool
135  exists (std::string const& name) const;
136 
141  find (std::string const& name) const;
142 
143  template <class T>
144  boost::optional<T>
145  get (std::string const& name) const
146  {
147  auto const iter = cont().find(name);
148  if (iter == cont().end())
149  return boost::none;
150  return boost::lexical_cast<T>(iter->second);
151  }
152 
154  template<class T>
155  T
156  value_or(std::string const& name, T const& other) const
157  {
158  auto const v = get<T>(name);
159  return v.is_initialized() ? *v : other;
160  }
161 
162  // indicates if trailing comments were seen
163  // during the appending of any lines/values
165 
166  friend
167  std::ostream&
168  operator<< (std::ostream&, Section const& section);
169 };
170 
171 //------------------------------------------------------------------------------
172 
178 {
179 private:
181 
182 public:
184  bool
185  exists (std::string const& name) const;
186 
191  Section&
192  section (std::string const& name);
193 
194  Section const&
195  section (std::string const& name) const;
196 
197  Section const&
198  operator[] (std::string const& name) const
199  {
200  return section(name);
201  }
202 
203  Section&
205  {
206  return section(name);
207  }
214  void
215  overwrite (std::string const& section, std::string const& key,
216  std::string const& value);
217 
220  void
222 
232  void
233  legacy(std::string const& section, std::string value);
234 
244  legacy(std::string const& sectionName) const;
245 
246  friend
247  std::ostream&
248  operator<< (std::ostream& ss, BasicConfig const& c);
249 
250  // indicates if trailing comments were seen
251  // in any loaded Sections
252  bool had_trailing_comments() const {
253  return std::any_of(map_.cbegin(), map_.cend(),
254  [](auto s){ return s.second.had_trailing_comments(); });
255  }
256 
257 protected:
258  void
259  build (IniFileSections const& ifs);
260 };
261 
262 //------------------------------------------------------------------------------
263 
269 template <class T>
270 bool
271 set (T& target, std::string const& name, Section const& section)
272 {
273  bool found_and_valid = false;
274  try
275  {
276  auto const val = section.get<T> (name);
277  if ((found_and_valid = val.is_initialized()))
278  target = *val;
279  }
280  catch (boost::bad_lexical_cast&)
281  {
282  }
283  return found_and_valid;
284 }
285 
291 template <class T>
292 bool
293 set (T& target, T const& defaultValue,
294  std::string const& name, Section const& section)
295 {
296  bool found_and_valid = set<T>(target, name, section);
297  if (!found_and_valid)
298  target = defaultValue;
299  return found_and_valid;
300 }
301 
306 // NOTE This routine might be more clumsy than the previous two
307 template <class T>
308 T
309 get (Section const& section,
310  std::string const& name, T const& defaultValue = T{})
311 {
312  try
313  {
314  return section.value_or<T> (name, defaultValue);
315  }
316  catch (boost::bad_lexical_cast&)
317  {
318  }
319  return defaultValue;
320 }
321 
322 inline
324 get (Section const& section,
325  std::string const& name, const char* defaultValue)
326 {
327  bool found_and_valid = false;
328  try
329  {
330  auto const val = section.get<std::string> (name);
331  if ((found_and_valid = val.is_initialized()))
332  return *val;
333  }
334  catch (boost::bad_lexical_cast&)
335  {
336  }
337  return defaultValue;
338 }
339 
340 template <class T>
341 bool
342 get_if_exists (Section const& section,
343  std::string const& name, T& v)
344 {
345  return set<T>(v, name, section);
346 }
347 
348 template <>
349 inline
350 bool
351 get_if_exists<bool> (Section const& section,
352  std::string const& name, bool& v)
353 {
354  int intVal = 0;
355  auto stat = get_if_exists(section, name, intVal);
356  if (stat)
357  v = bool (intVal);
358  return stat;
359 }
360 
361 } // ripple
362 
363 #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:252
ripple::Section::values_
std::vector< std::string > values_
Definition: BasicConfig.h:50
ripple::Section::legacy
void legacy(std::string value)
Set the legacy value for this section.
Definition: BasicConfig.h:87
std::string
STL class.
std::pair
ripple::BasicConfig::operator[]
Section const & operator[](std::string const &name) const
Definition: BasicConfig.h:198
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:156
ripple::Section::exists
bool exists(std::string const &name) const
Returns true if a key with the given name exists.
Definition: BasicConfig.cpp:109
ripple::Section::had_trailing_comments
bool had_trailing_comments() const
Definition: BasicConfig.h:164
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:78
ripple::get_if_exists
bool get_if_exists(Section const &section, std::string const &name, T &v)
Definition: BasicConfig.h:342
ripple::Section::append
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
Definition: BasicConfig.cpp:41
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:60
ripple::BasicConfig::deprecatedClearSection
void deprecatedClearSection(std::string const &section)
Remove all the key/value pairs from the section.
Definition: BasicConfig.cpp:165
ripple::BasicConfig::operator<<
friend std::ostream & operator<<(std::ostream &ss, BasicConfig const &c)
Definition: BasicConfig.cpp:196
std::ostream
STL class.
ripple::BasicConfig::build
void build(IniFileSections const &ifs)
Definition: BasicConfig.cpp:185
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:271
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:173
ripple::Section::lines
std::vector< std::string > const & lines() const
Returns all the lines in the section.
Definition: BasicConfig.h:69
map
ripple::Section::had_trailing_comments_
bool had_trailing_comments_
Definition: BasicConfig.h:51
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:156
ripple::Section::find
std::pair< std::string, bool > find(std::string const &name) const
Retrieve a key/value pair.
Definition: BasicConfig.cpp:115
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:145
ripple::Section::set
void set(std::string const &key, std::string const &value)
Set a key/value pair.
Definition: BasicConfig.cpp:33
ripple::Section::operator<<
friend std::ostream & operator<<(std::ostream &, Section const &section)
Definition: BasicConfig.cpp:124
ripple::Section::name_
std::string name_
Definition: BasicConfig.h:48
ripple::Section::legacy
std::string legacy() const
Get the legacy value for this section.
Definition: BasicConfig.h:102
std::vector::empty
T empty(T... args)
ripple::Section::lines_
std::vector< std::string > lines_
Definition: BasicConfig.h:49
ripple::BasicConfig::map_
std::map< std::string, Section, boost::beast::iless > map_
Definition: BasicConfig.h:180
ostream
ripple::get_if_exists< bool >
bool get_if_exists< bool >(Section const &section, std::string const &name, bool &v)
Definition: BasicConfig.h:351
ripple::BasicConfig
Holds unparsed configuration information.
Definition: BasicConfig.h:177
ripple::Section::append
void append(std::string const &line)
Append a line to this section.
Definition: BasicConfig.h:128
ripple::BasicConfig::exists
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Definition: BasicConfig.cpp:134
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:124
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:140
string