ALPSCore reference
params_impl.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 
13 #include <boost/lexical_cast.hpp>
14 #include <boost/optional.hpp>
15 #include <locale> // FIXME: needed only for boolean conversions
16 
17 namespace alps {
18  namespace params_ns {
19 
20  namespace detail {
21 
22  // FIXME: move this to a *.cpp file
23  template <typename T>
24  struct parse_string {
25  static boost::optional<T> apply(const std::string& in) {
26  T conv_result;
27  boost::optional<T> result;
28  if (boost::conversion::try_lexical_convert(in, conv_result)) {
29  result=conv_result;
30  }
31  return result;
32  }
33  };
34 
35  template <>
36  struct parse_string<std::string> {
37  static boost::optional<std::string> apply(const std::string& in) {
38  return in;
39  }
40  };
41 
42  template <>
43  struct parse_string<bool> {
44  static boost::optional<bool> apply(std::string in) {
45  std::locale c_locale("C");
46  for(char& c: in) {
47  c=tolower(c, c_locale);
48  }
49  boost::optional<bool> result;
50  if (in=="true" || in=="on" || in=="yes" || in=="1") result=true;
51  if (in=="false" || in=="off" || in=="no" || in=="0") result=false;
52  return result;
53  }
54  };
55 
56  template <typename T>
57  struct parse_string< std::vector<T> > {
58  static boost::optional< std::vector<T> > apply(const std::string& in) {
59  typedef std::vector<T> value_type;
60  typedef boost::optional<value_type> result_type;
61  typedef boost::optional<T> optional_el_type;
62  typedef std::string::const_iterator sit_type;
63  value_type result_vec;
64  result_type result;
65  sit_type it1=in.begin();
66  while (it1!=in.end()) {
67  sit_type it2=find(it1, in.end(), ',');
68  optional_el_type elem=parse_string<T>::apply(std::string(it1,it2));
69  if (!elem) return result;
70  result_vec.push_back(*elem);
71  if (it2!=in.end()) ++it2;
72  it1=it2;
73  }
74  result=result_vec;
75  return result;
76  }
77  };
78 
79  } // ::detail
80 
81  template <typename T>
82  bool params::assign_to_name_(const std::string& name, const std::string& strval)
83  {
84  boost::optional<T> result=detail::parse_string<T>::apply(strval);
85  if (result) {
86  (*this)[name]=*result;
87  return true;
88  } else {
89  return false;
90  }
91  }
92 
93  template <typename T>
94  bool params::define_(const std::string& name, const std::string& descr)
95  {
96  if (this->exists(name) && !this->exists<T>(name))
97  throw exception::type_mismatch(name, "Parameter already in dictionary with a different type");
98 
99  td_map_type::iterator td_it=td_map_.find(name); // FIXME: use lower-bound instead
100  if (td_it!=td_map_.end()) {
101  if (td_it->second.typestr() != detail::make_typestr::apply<T>()) throw exception::type_mismatch(name, "Parameter already defined with a different type");
102  td_it->second.descr()=descr;
103  return true;
104  }
105  td_map_.insert(std::make_pair(name, detail::td_type::make_pair<T>(descr, td_map_.size())));
106 
107  strmap::const_iterator it=raw_kv_content_.find(name);
108  if (it==raw_kv_content_.end()) {
109  if (this->exists(name)) return true;
110  return false; // caller needs to decide whether the default is available
111  }
112  if (!assign_to_name_<T>(name, it->second)) {
113  err_status_.push_back("Cannot parse parameter '"+name+"' as the requested type");
114  (*this)[name].clear();
115  }
116  return true;
117  }
118 
119  template <typename T>
120  params& params::define(const std::string& name, const std::string& descr)
121  {
122  if (!define_<T>(name, descr)) {
123  if (!this->exists<T>(name)) err_status_.push_back("Required parameter '"+name+"' is missing");
124  }
125  return *this;
126  }
127 
128  template <typename T>
129  params& params::define(const std::string& name, const T& defval, const std::string& descr)
130  {
131  if (!define_<T>(name, descr)) {
132  (*this)[name]=defval;
133  }
134  return *this;
135  }
136 
137  inline bool params::supplied(const std::string &name) const
138  {
139  return raw_kv_content_.count(name);
140  }
141 
142  inline bool params::defaulted(const std::string& name) const
143  {
144  return exists(name) && !supplied(name);
145  }
146 
147  inline bool params::defined(const std::string& name) const
148  {
149  return td_map_.count(name)!=0 || exists(name);
150  }
151 
152  inline void swap(params& p1, params& p2)
153  {
154  using std::swap;
155  swap(static_cast<dictionary&>(p1), static_cast<dictionary&>(p2));
156  swap(p1.raw_kv_content_, p2.raw_kv_content_);
157  swap(p1.td_map_, p2.td_map_);
158  swap(p1.err_status_, p2.err_status_);
159  swap(p1.origins_.data(), p2.origins_.data());
160  }
161 
162  inline std::string params::get_origin_name() const
163  {
164  return origin_name(*this);
165  }
166 
167  } // params_ns::
169  using params_ns::swap;
170 
171 } // alps::
Parse sectioned INI file or HDF5 or command line, provide the results as dictionary.
Definition: params.hpp:84
bool defined(const std::string &name) const
Check whether a parameter was ever defined.
params & define(const std::string &name, const std::string &descr)
Defines a parameter; returns false on error, and records the error in the object. ...
STL namespace.
void swap(params &p1, params &p2)
std::string origin_name(const params &p)
Convenience function to obtain the "origin" filename associated with the parameters object...
Definition: params.cpp:505
bool supplied(const std::string &name) const
True if the parameter is supplied via file or cmdline.
traits< Acc >::result_type result(const Acc &acc)
Definition: util.hpp:53
bool defaulted(const std::string &name) const
True if the parameter acquired its value by default.
std::string get_origin_name() const ALPS_DEPRECATED
Convenience method: returns the "origin name".