Wolframe, 0.0.3

valueParser.hpp
Go to the documentation of this file.
1 /************************************************************************
2 Copyright (C) 2011 - 2014 Project Wolframe.
3 All rights reserved.
4 
5 This file is part of Project Wolframe.
6 
7 Commercial Usage
8 Licensees holding valid Project Wolframe Commercial licenses may
9 use this file in accordance with the Project Wolframe
10 Commercial License Agreement provided with the Software or,
11 alternatively, in accordance with the terms contained
12 in a written agreement between the licensee and Project Wolframe.
13 
14 GNU General Public License Usage
15 Alternatively, you can redistribute this file and/or modify it
16 under the terms of the GNU General Public License as published by
17 the Free Software Foundation, either version 3 of the License, or
18 (at your option) any later version.
19 
20 Wolframe is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24 
25 You should have received a copy of the GNU General Public License
26 along with Wolframe. If not, see <http://www.gnu.org/licenses/>.
27 
28 If you have questions regarding the use of this file, please contact
29 Project Wolframe.
30 
31 ************************************************************************/
34 
35 #ifndef _Wolframe_CONFIG_VALUE_PARSER_HPP_INCLUDED
36 #define _Wolframe_CONFIG_VALUE_PARSER_HPP_INCLUDED
37 
38 #include "logger-v1.hpp"
39 #include "types/propertyTree.hpp"
40 #include <stdexcept>
41 #include <boost/type_traits.hpp>
42 #include <boost/lexical_cast.hpp>
43 #include <boost/algorithm/string.hpp>
44 #include <boost/utility/value_init.hpp>
45 #include <boost/type_traits/is_enum.hpp>
46 #include <boost/utility.hpp>
47 #include <boost/limits.hpp>
48 #include <string>
49 #include <ostream>
50 #include <utility>
51 
52 namespace _Wolframe {
53 namespace config {
54 
55 namespace traits {
56 template <typename T> typename boost::enable_if<boost::is_enum<T>, T>::type increment( const T& i) { return (T)((int)i + 1); }
57 template <typename T> typename boost::disable_if<boost::is_enum<T>, T>::type increment( const T& i) { T rt = i; return ++rt; }
58 }//namespace
59 
60 
63 class Parser
64 {
65 public:
66  typedef std::string string;
67 
70  //
71  // All domains have to implement a check(ValueType&,string&) and a parse(ValueType&,const string&,string&) method
72  //
74  {
77 
80  template <typename ValueType>
81  bool check( const ValueType&, string&) const
82  {
83  return true;
84  }
85 
91  template <typename ValueType>
92  bool parse( ValueType& value, const string& token, string& explanation) const
93  {
94  using boost::bad_lexical_cast;
95  try
96  {
97  value = boost::lexical_cast<ValueType>( token);
98  }
99  catch (bad_lexical_cast& e)
100  {
101  explanation = e.what();
102  return false;
103  };
104  return true;
105  }
106  };
107 
111  template <typename DomainValueType>
113  {
117  RangeDomain( const DomainValueType& min_, const DomainValueType& max_=std::numeric_limits<DomainValueType>::max()) :m_min(min_),m_max(max_){}
118 
120  string getDomainDescription() const
121  {
122  string rt( "[ ");
123  rt.append( boost::lexical_cast<string>(m_min));
124  rt.append( ", ");
125  rt.append( boost::lexical_cast<string>(m_max));
126  rt.append( " ]");
127  return rt;
128  }
129 
134  template <typename ValueType>
135  bool check( const ValueType& val, string& explanation) const
136  {
137  if (val < m_min || val > m_max)
138  {
139  explanation = "value out of range, expected value in the range of ";
140  explanation.append( getDomainDescription());
141  return false;
142  }
143  return true;
144  }
145  private:
146  DomainValueType m_min; //< minimal allowed value of the range
147  DomainValueType m_max; //< maximal allowed value of the range
148  };
149 
153  template <typename DomainValueType>
155  {
158 
163  template <typename ValueType>
164  bool check( const ValueType& val, string& explanation) const
165  {
166  ValueType empty = boost::value_initialized<ValueType>();
167  if (val == empty)
168  {
169  explanation = "value expected to be other than '";
170  explanation.append( boost::lexical_cast<std::string>( empty));
171  explanation.append( "'");
172  return false;
173  }
174  return true;
175  }
176  };
177 
180  struct EnumDomain :public BaseTypeDomain
181  {
185  EnumDomain( unsigned int nofelems, const char** elems) :m_size(nofelems),m_ar(elems){}
186 
188  string getDomainDescription() const
189  {
190  string rt( "{");
191  unsigned int ii;
192  for (ii=0; ii<m_size; ii++)
193  {
194  if (ii>0) rt.append( ", ");
195  rt.append( "'");
196  rt.append( boost::lexical_cast<string>(m_ar[ii]));
197  rt.append( "'");
198  }
199  rt.append( "}");
200  return rt;
201  }
202 
208  template <typename ValueType>
209  bool parse( ValueType& value, const string& token, string& explanation) const
210  {
211  unsigned int ii;
212  value = boost::value_initialized<ValueType>();
213 
214  for (ii=0; ii<m_size; ii++, value=traits::increment(value))
215  {
216  if (boost::algorithm::iequals( token, m_ar[ii]))
217  {
218  return true;
219  }
220  }
221  explanation = "must be one of ";
222  explanation.append( getDomainDescription());
223  return false;
224  }
225  private:
226  unsigned int m_size; //< number of elements in the enumeration
227  const char** m_ar; //< string representation of the elements in the enumeration
228  };
229 
232  struct BoolDomain :public EnumDomain
233  {
234  private:
235  enum {NofBooleanEnum=10};
236 
239  static const char** booleanEnum()
240  {
241  static const char* ar[ NofBooleanEnum ] = {"false", "true", "0", "1", "off", "on", "no", "yes", "deny", "allow"};
242  return ar;
243  }
246  static bool getBooleanValue( unsigned int booleanEnumIdx)
247  {
248  return (booleanEnumIdx & 0x01);
249  }
250 
251  public:
254 
259  bool parse( bool& value, const string& token, string& explanation) const
260  {
261  unsigned int enumval = 0;
262  bool rt = EnumDomain::parse( enumval, token, explanation);
263  value = getBooleanValue( enumval);
264  return rt;
265  }
266  };
267 
277  // If the flag is set when the method is called an error message is logged and the command fails.
279  template <typename Value, class Domain>
280  static bool getValue( const char* module, const char* name, const string& token, Value& value, const Domain& domain, bool* isDefined=0)
281  {
282  using std::bad_alloc;
283  using std::exception;
284  try
285  {
286  if (isDefined)
287  {
288  if (*isDefined)
289  {
290  LOG_ERROR << loggingScope(module) << "duplicate definition of configuration element '" << name << "'";
291  return false;
292  }
293  }
294  string errorExplanation;
295  if (domain.parse( value, token, errorExplanation) && domain.check( value, errorExplanation))
296  {
297  if (isDefined) *isDefined = true;
298  return true;
299  }
300  LOG_ERROR << loggingScope(module) << "invalid value '" << token << "' for configuration element '" << name << "' (" << errorExplanation << ")";
301  return false;
302  }
303  catch (bad_alloc&)
304  {
305  LOG_ERROR << loggingScope(module) << "out of memory when parsing configuration element '" << name << "'";
306  return false;
307  }
308  catch (exception& e)
309  {
310  LOG_ERROR << loggingScope(module) << "illegal value for configuration element '" << name << "' (" << e.what() << ")";
311  return false;
312  }
313  }
314 
322  // If the flag is set when the method is called an error message is logged and the command fails.
324  template <typename Value>
325  static bool getValue( const char* module, const char* name, const string& token, Value& value, bool* isDefined=0)
326  {
327  return getValue<Value,BaseTypeDomain>( module, name, token, value, BaseTypeDomain(), isDefined);
328  }
329 
335  // See definition of getValue(const char*,const std::pair<const std::string,const std::string>&,Value&,const Domain&,bool*).
336  // Only difference is that we convert the decl structure from a property tree element and check if it is a name value assignement.
340  // If the flag is set when the method is called an error message is logged and the command fails.
342  template <typename Value, class Domain>
343  static bool getValue( const char* module, const std::pair<const std::string, const types::PropertyTree::Node>& decl, Value& value, const Domain& domain, bool* isDefined=0)
344  {
345  try
346  {
347  if (decl.second.begin() != decl.second.end())
348  {
349  LOG_ERROR << loggingScope(module) << "atomic value expected for configuration element '" << decl.first.c_str() << "'";
350  return false;
351  }
352  return getValue( module, decl.first.c_str(), decl.second.data(), value, domain, isDefined);
353  }
354  catch (std::bad_alloc&)
355  {
356  LOG_ERROR << loggingScope(module) << "out of memory when parsing configuration element '" << decl.first.c_str() << "'";
357  return false;
358  };
359  }
360 
365  // See definition of getValue(const char*,const std::pair<const std::string,const std::string>&,Value&,bool*).
366  // Only difference is that we convert the decl structure from a property tree element and check if it is a name value assignement.
369  // If the flag is set when the method is called an error message is logged and the command fails.
371  template <typename Value>
372  static bool getValue( const char* module, const std::pair<const std::string, const types::PropertyTree::Node>& decl, Value& value, bool* isDefined=0)
373  {
374  return getValue<Value,BaseTypeDomain>( module, decl, value, BaseTypeDomain(), isDefined);
375  }
376 
377 private:
380  static const std::string loggingScope( const char* scope)
381  {
382  std::string rt;
383  if (scope && *scope)
384  {
385  rt.append( scope);
386  rt.append( ": ");
387  }
388  return rt;
389  }
390 };
391 
392 }} // namespace _Wolframe::config
393 
394 #endif // _Wolframe_CONFIG_VALUE_PARSER_HPP_INCLUDED
Top-level include file for logging (version 1)
bool check(const ValueType &val, string &explanation) const
Checks if the configuration value is in the expected domain, e.g. non empty.
Definition: valueParser.hpp:164
DomainValueType m_min
Definition: valueParser.hpp:146
static bool getValue(const char *module, const char *name, const string &token, Value &value, const Domain &domain, bool *isDefined=0)
Get the value of a configration token with a domain restriction that is checked.
Definition: valueParser.hpp:280
BaseTypeDomain()
Constructor.
Definition: valueParser.hpp:76
static bool getBooleanValue(unsigned int booleanEnumIdx)
Returns the boolean value of an accepted token.
Definition: valueParser.hpp:246
bool check(const ValueType &, string &) const
Checks if the configuration value is in the expected domain.
Definition: valueParser.hpp:81
static const std::string loggingScope(const char *scope)
Return the header of a configuration parse error message issued, specifying the definition scope of t...
Definition: valueParser.hpp:380
bool parse(bool &value, const string &token, string &explanation) const
Parses a boolean value.
Definition: valueParser.hpp:259
boost::enable_if< boost::is_enum< T >, T >::type increment(const T &i)
Definition: valueParser.hpp:56
std::string string
Definition: valueParser.hpp:66
Describes a value domain for a range of values.
Definition: valueParser.hpp:112
static bool getValue(const char *module, const std::pair< const std::string, const types::PropertyTree::Node > &decl, Value &value, const Domain &domain, bool *isDefined=0)
Get the value of a configration token with a domain restriction that is checked.
Definition: valueParser.hpp:343
bool check(const ValueType &val, string &explanation) const
Checks if the configuration value is in the expected domain.
Definition: valueParser.hpp:135
Configuration parser for parsing the tokens of the configuration.
Definition: valueParser.hpp:63
bool parse(ValueType &value, const string &token, string &explanation) const
Parses the token string and maps it to its value representation.
Definition: valueParser.hpp:92
Describes the value domain of a boolean value as enumeration of all possible values.
Definition: valueParser.hpp:232
#define LOG_ERROR
Definition: logger-v1.hpp:109
NonEmptyDomain()
constructor
Definition: valueParser.hpp:157
unsigned int m_size
Definition: valueParser.hpp:226
Definition: valueParser.hpp:154
Describes a value domain for an enumerable fixed set of values.
Definition: valueParser.hpp:180
string getDomainDescription() const
Get the description of the set of values allowed as string for the error log message.
Definition: valueParser.hpp:188
BoolDomain()
Constructor.
Definition: valueParser.hpp:253
static bool getValue(const char *module, const char *name, const string &token, Value &value, bool *isDefined=0)
Get the value of a configration token without additional domain restriction.
Definition: valueParser.hpp:325
Interface to a key value tree based on boost::property_tree::ptree with position info for better erro...
static bool getValue(const char *module, const std::pair< const std::string, const types::PropertyTree::Node > &decl, Value &value, bool *isDefined=0)
Get the value of a configration token without additional domain restriction.
Definition: valueParser.hpp:372
const char ** m_ar
Definition: valueParser.hpp:227
bool parse(ValueType &value, const string &token, string &explanation) const
Parses the token string and maps it to its value representation.
Definition: valueParser.hpp:209
static const char ** booleanEnum()
returns the accepted string representations of a boolean
Definition: valueParser.hpp:239
DomainValueType m_max
Definition: valueParser.hpp:147
string getDomainDescription() const
Get the description of the set of values allowed as string for the error log message.
Definition: valueParser.hpp:120
Describes a domain without value restriction except the one given by the C++ value type itself...
Definition: valueParser.hpp:73
EnumDomain(unsigned int nofelems, const char **elems)
Constructor.
Definition: valueParser.hpp:185
RangeDomain(const DomainValueType &min_, const DomainValueType &max_=std::numeric_limits< DomainValueType >::max())
Constructor.
Definition: valueParser.hpp:117