Wolframe, 0.0.3

parseValue.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 #ifndef _Wolframe_SERIALIZE_STRUCT_PARSE_VALUE_HPP_INCLUDED
35 #define _Wolframe_SERIALIZE_STRUCT_PARSE_VALUE_HPP_INCLUDED
36 #include "types/conversions.hpp"
37 #include "types/datetime.hpp"
38 #include "types/bignumber.hpp"
39 #include "types/customDataType.hpp"
40 #include "types/integer.hpp"
41 #include <boost/lexical_cast.hpp>
42 #include <boost/numeric/conversion/cast.hpp>
43 #include <boost/utility/enable_if.hpp>
44 #include <boost/type_traits.hpp>
45 #include <string>
46 
47 namespace {
48 
51 struct ParseValueType
52 {
53  struct String {};
54  struct Bool {};
55  struct Arithmetic {};
56  struct DateTime {};
57  struct BigNumber {};
58 
61  template <typename T>
62  static typename boost::enable_if_c<
63  boost::is_same<T,std::string>::value
64  ,const String&>::type get( const T&) { static String rt; return rt;}
65 
68  template <typename T>
69  static typename boost::enable_if_c<
70  boost::is_same<T,bool>::value
71  ,const Bool&>::type get( const T&) { static Bool rt; return rt;}
72 
75  template <typename T>
76  static typename boost::enable_if_c<
77  (boost::is_arithmetic<T>::value && !boost::is_same<T,bool>::value && !boost::is_same<T,std::string>::value)
78  ,const Arithmetic&>::type get( const T&) { static Arithmetic rt; return rt;}
79 
82  template <typename T>
83  static typename boost::enable_if_c<
84  boost::is_same<T,_Wolframe::types::DateTime>::value
85  ,const DateTime&>::type get( const T&) { static DateTime rt; return rt;}
86 
89  template <typename T>
90  static typename boost::enable_if_c<
91  boost::is_same<T,_Wolframe::types::BigNumber>::value
92  ,const BigNumber&>::type get( const T&) { static BigNumber rt; return rt;}
93 };
94 
95 struct ValueParser
96 {
97  static bool getBool( bool& val, int boolnum)
98  {
99  if (boolnum == 0)
100  {
101  val = false;
102  return true;
103  }
104  else if (boolnum == 1)
105  {
106  val = true;
107  return true;
108  }
109  return false;
110  }
111 
112  template <typename ValueType>
113  static bool parseValue( ValueType& val, const ParseValueType::String&, const _Wolframe::types::VariantConst& element)
114  {
115  using namespace _Wolframe;
116 
117  try
118  {
119  val = element.tostring();
120  return true;
121  }
122  catch (const boost::bad_lexical_cast&){}
123  catch (const std::runtime_error&){}
124  return false;
125  }
126 
127  template <typename ValueType>
128  static bool parseValue( ValueType& val, const ParseValueType::Bool&, const _Wolframe::types::VariantConst& element)
129  {
130  using namespace _Wolframe;
131 
132  try
133  {
134  switch (element.type())
135  {
136  case types::Variant::Null:
137  return false;
138 
139  case types::Variant::Bool:
140  val = element.tobool();
141  return true;
142 
143  case types::Variant::Double:
144  return getBool( val, boost::numeric_cast<int>( element.todouble()));
145 
146  case types::Variant::Int:
147  return getBool( val, boost::numeric_cast<ValueType>( element.toint()));
148 
149  case types::Variant::UInt:
150  return getBool( val, boost::numeric_cast<ValueType>( element.touint()));
151 
152  case types::Variant::String:
153  {
154  const char* cc = element.charptr();
155  std::size_t ccsize = element.charsize();
156 
157  if (ccsize == 4 && boost::algorithm::iequals( cc, "true"))
158  {
159  val = true;
160  return true;
161  }
162  if (ccsize == 5 && boost::algorithm::iequals( cc, "false"))
163  {
164  val = false;
165  return true;
166  }
167  if (ccsize == 3 && boost::algorithm::iequals( cc, "yes"))
168  {
169  val = true;
170  return true;
171  }
172  if (ccsize == 2 && boost::algorithm::iequals( cc, "no"))
173  {
174  val = false;
175  return true;
176  }
177  if (ccsize == 1)
178  {
179  if ((cc[0]|32) == 't' || (cc[0]|32) == 'y')
180  {
181  val = true;
182  return true;
183  }
184  if ((cc[0]|32) == 'f' || (cc[0]|32) == 'n')
185  {
186  val = false;
187  return true;
188  }
189  }
190  return false;
191  }
192  case types::Variant::BigNumber:
193  throw std::runtime_error( "cannot convert big number type to boolean value");
195  throw std::runtime_error( "cannot convert timestamp type to boolean value");
196  case types::Variant::Custom:
197  {
198  types::Variant baseval;
199  try
200  {
201  if (element.customref()->getBaseTypeValue( baseval)
202  && baseval.type() != types::Variant::Custom)
203  {
204  return ValueParser::parseValue( val, ParseValueType::Bool(), baseval);
205  }
206  }
207  catch (const std::runtime_error& e)
208  {
209  throw std::runtime_error( std::string("cannot convert custom data type to boolean value: ") + e.what());
210  }
211  throw std::runtime_error( "cannot convert custom data type to boolean value");
212  }
213  }
214  }
215  catch (const boost::bad_lexical_cast&){}
216  return false;
217  }
218 
219  template <typename ValueType>
220  static bool parseValue( ValueType& val, const ParseValueType::Arithmetic&, const _Wolframe::types::VariantConst& element)
221  {
222  using namespace _Wolframe;
223 
224  try
225  {
226  switch (element.type())
227  {
228  case types::Variant::Null:
229  return false;
230 
231  case types::Variant::Bool:
232  val = boost::numeric_cast<ValueType>( element.tobool());
233  return true;
234 
235  case types::Variant::Double:
236  val = boost::numeric_cast<ValueType>( element.todouble());
237  return true;
238 
239  case types::Variant::Int:
240  val = boost::numeric_cast<ValueType>( element.toint());
241  return true;
242 
243  case types::Variant::UInt:
244  val = boost::numeric_cast<ValueType>( element.touint());
245  return true;
246 
248  throw std::runtime_error( "cannot convert timestamp to arithmetic type");
249 
250  case types::Variant::BigNumber:
251  val = boost::lexical_cast<ValueType>( element.tostring());
252  return true;
253 
254  case types::Variant::String:
255  val = boost::lexical_cast<ValueType>( element.tostring());
256  return true;
257 
258  case types::Variant::Custom:
259  {
260  types::Variant baseval;
261  try
262  {
263  if (element.customref()->getBaseTypeValue( baseval)
264  && baseval.type() != types::Variant::Custom)
265  {
266  return ValueParser::parseValue( val, ParseValueType::Arithmetic(), baseval);
267  }
268  val = boost::lexical_cast<ValueType>( element.tostring());
269  return true;
270  }
271  catch (const std::runtime_error& e)
272  {
273  throw std::runtime_error( std::string("cannot convert custom data type to arithmetic value: ") + e.what());
274  }
275  }
276  }
277  }
278  catch (const boost::bad_lexical_cast&){}
279  catch (const boost::bad_numeric_cast&){}
280  return false;
281  }
282 
283  template <typename ValueType>
284  static bool parseValue( ValueType& val, const ParseValueType::BigNumber&, const _Wolframe::types::VariantConst& element)
285  {
286  using namespace _Wolframe;
287 
288  try
289  {
290  switch (element.type())
291  {
292  case types::Variant::Null:
293  return false;
294 
295  case types::Variant::Bool:
296  val = types::BigNumber( (_WOLFRAME_UINTEGER)(element.tobool()?1:0));
297  return true;
298 
299  case types::Variant::Double:
300  val = types::BigNumber( element.todouble());
301  return true;
302 
303  case types::Variant::Int:
304  val = types::BigNumber( element.toint());
305  return true;
306 
307  case types::Variant::UInt:
308  val = types::BigNumber( element.touint());
309  return true;
310 
312  throw std::runtime_error( "cannot convert timestamp to big number");
313 
314  case types::Variant::BigNumber:
315  val = *element.bignumref();
316  return true;
317 
318  case types::Variant::String:
319  val = types::BigNumber( element.charptr(), element.charsize());
320  return true;
321 
322  case types::Variant::Custom:
323  {
324  types::Variant baseval;
325  try
326  {
327  if (element.customref()->getBaseTypeValue( baseval)
328  && baseval.type() != types::Variant::Custom)
329  {
330  return ValueParser::parseValue( val, ParseValueType::BigNumber(), baseval);
331  }
332  val = types::BigNumber( element.tostring());
333  return true;
334  }
335  catch (const std::runtime_error& e)
336  {
337  throw std::runtime_error( std::string("cannot convert custom data type to bignumber value: ") + e.what());
338  }
339  }
340  }
341  }
342  catch (const boost::bad_lexical_cast&){}
343  catch (const boost::bad_numeric_cast&){}
344  return false;
345  }
346 
347  template <typename ValueType>
348  static bool parseValue( ValueType& val, const ParseValueType::DateTime&, const _Wolframe::types::VariantConst& element)
349  {
350  using namespace _Wolframe;
351 
352  try
353  {
354  switch (element.type())
355  {
356  case types::Variant::Null:
357  case types::Variant::Bool:
358  case types::Variant::Double:
359  case types::Variant::Int:
360  case types::Variant::UInt:
361  return false;
362 
364  val = element.totimestamp();
365  return true;
366 
367  case types::Variant::BigNumber:
368  return false;
369 
370  case types::Variant::String:
371  val = types::DateTime( element.charptr(), element.charsize());
372  return true;
373 
374  case types::Variant::Custom:
375  {
376  types::Variant baseval;
377  try
378  {
379  if (element.customref()->getBaseTypeValue( baseval)
380  && baseval.type() != types::Variant::Custom)
381  {
382  return ValueParser::parseValue( val, ParseValueType::DateTime(), baseval);
383  }
384  val = types::DateTime( element.tostring());
385  return true;
386  }
387  catch (const std::runtime_error& e)
388  {
389  throw std::runtime_error( std::string("cannot convert custom data type to datetime value: ") + e.what());
390  }
391  }
392  }
393  }
394  catch (const boost::bad_lexical_cast&){}
395  catch (const boost::bad_numeric_cast&){}
396  return false;
397  }
398 };
399 } //anonymous namespace
400 
401 namespace _Wolframe {
402 namespace serialize {
403 
404 template <typename ValueType>
405 bool parseValue( ValueType& val, const types::VariantConst& element)
406 {
407  return ValueParser::parseValue( val, ParseValueType::get(val), element);
408 }
409 
410 }}//namespace
411 #endif
412 
413 
boost::uint64_t Timestamp
Timestamp equivalent to a date time value for variant type.
Definition: datetime.hpp:47
Application wide definitions of integer number value types.
Type for representing arbitrary precision fixed point numbers and big integers as binary coded decima...
virtual bool getBaseTypeValue(Variant &) const
Definition: customDataType.hpp:81
Custom data type interface for variant.
Type for representing big numbers as binary coded decimal (BCD) numbers.
Definition: bignumber.hpp:49
Data::UInt touint() const
Data type for normalized date time (absolute time without time zone info)
Definition: datetime.hpp:55
#define _WOLFRAME_UINTEGER
Definition: integer.hpp:42
Forward declaration.
Definition: variant.hpp:65
Variant value type that represents a variant copy without content ownership.
Definition: variant.hpp:286
Conversions of atomic types.
Type type() const
Get the type of this.
Definition: variant.hpp:191
double todouble() const
std::string tostring() const
Getter with value conversion.
const CustomDataValue * customref() const
Get the pointer to the custom data object (throws for non custom data type)
Definition: variant.hpp:201
Date and datetime value type.
Data::Timestamp totimestamp() const
char * charptr() const
Get the pointer to the C representation of a string (throws for non string)
Definition: variant.hpp:197
Data::Int toint() const
std::size_t charsize() const
Get the size of a string (throws for non string)
Definition: variant.hpp:199
bool parseValue(ValueType &val, const types::VariantConst &element)
Definition: parseValue.hpp:405
const types::BigNumber * bignumref() const
Get the pointer to the big number object (throws for non big number data type)
Definition: variant.hpp:205