JSON Spirit library from http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx,...
[novacoin.git] / json / json_spirit_value.h
1 #ifndef JSON_SPIRIT_VALUE\r
2 #define JSON_SPIRIT_VALUE\r
3 \r
4 //          Copyright John W. Wilkinson 2007 - 2009.\r
5 // Distributed under the MIT License, see accompanying file LICENSE.txt\r
6 \r
7 // json spirit version 4.03\r
8 \r
9 #if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
10 # pragma once\r
11 #endif\r
12 \r
13 #include <vector>\r
14 #include <map>\r
15 #include <string>\r
16 #include <cassert>\r
17 #include <sstream>\r
18 #include <stdexcept>\r
19 #include <boost/config.hpp> \r
20 #include <boost/cstdint.hpp> \r
21 #include <boost/shared_ptr.hpp> \r
22 #include <boost/variant.hpp> \r
23 \r
24 namespace json_spirit\r
25 {\r
26     enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };\r
27 \r
28     template< class Config >    // Config determines whether the value uses std::string or std::wstring and\r
29                                 // whether JSON Objects are represented as vectors or maps\r
30     class Value_impl\r
31     {\r
32     public:\r
33 \r
34         typedef Config Config_type;\r
35         typedef typename Config::String_type String_type;\r
36         typedef typename Config::Object_type Object;\r
37         typedef typename Config::Array_type Array;\r
38         typedef typename String_type::const_pointer Const_str_ptr;  // eg const char*\r
39 \r
40         Value_impl();  // creates null value\r
41         Value_impl( Const_str_ptr      value ); \r
42         Value_impl( const String_type& value );\r
43         Value_impl( const Object&      value );\r
44         Value_impl( const Array&       value );\r
45         Value_impl( bool               value );\r
46         Value_impl( int                value );\r
47         Value_impl( boost::int64_t     value );\r
48         Value_impl( boost::uint64_t    value );\r
49         Value_impl( double             value );\r
50 \r
51         Value_impl( const Value_impl& other );\r
52 \r
53         bool operator==( const Value_impl& lhs ) const;\r
54 \r
55         Value_impl& operator=( const Value_impl& lhs );\r
56 \r
57         Value_type type() const;\r
58 \r
59         bool is_uint64() const;\r
60         bool is_null() const;\r
61 \r
62         const String_type& get_str()    const;\r
63         const Object&      get_obj()    const;\r
64         const Array&       get_array()  const;\r
65         bool               get_bool()   const;\r
66         int                get_int()    const;\r
67         boost::int64_t     get_int64()  const;\r
68         boost::uint64_t    get_uint64() const;\r
69         double             get_real()   const;\r
70 \r
71         Object& get_obj();\r
72         Array&  get_array();\r
73 \r
74         template< typename T > T get_value() const;  // example usage: int    i = value.get_value< int >();\r
75                                                      // or             double d = value.get_value< double >();\r
76 \r
77         static const Value_impl null;\r
78 \r
79     private:\r
80 \r
81         void check_type( const Value_type vtype ) const;\r
82 \r
83         typedef boost::variant< String_type, \r
84                                 boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, \r
85                                 bool, boost::int64_t, double > Variant;\r
86 \r
87         Value_type type_;\r
88         Variant v_;\r
89         bool is_uint64_;\r
90     };\r
91 \r
92     // vector objects\r
93 \r
94     template< class Config >\r
95     struct Pair_impl\r
96     {\r
97         typedef typename Config::String_type String_type;\r
98         typedef typename Config::Value_type Value_type;\r
99 \r
100         Pair_impl( const String_type& name, const Value_type& value );\r
101 \r
102         bool operator==( const Pair_impl& lhs ) const;\r
103 \r
104         String_type name_;\r
105         Value_type value_;\r
106     };\r
107 \r
108     template< class String >\r
109     struct Config_vector\r
110     {\r
111         typedef String String_type;\r
112         typedef Value_impl< Config_vector > Value_type;\r
113         typedef Pair_impl < Config_vector > Pair_type;\r
114         typedef std::vector< Value_type > Array_type;\r
115         typedef std::vector< Pair_type > Object_type;\r
116 \r
117         static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )\r
118         {\r
119             obj.push_back( Pair_type( name , value ) );\r
120 \r
121             return obj.back().value_;\r
122         }\r
123                 \r
124         static String_type get_name( const Pair_type& pair )\r
125         {\r
126             return pair.name_;\r
127         }\r
128                 \r
129         static Value_type get_value( const Pair_type& pair )\r
130         {\r
131             return pair.value_;\r
132         }\r
133     };\r
134 \r
135     // typedefs for ASCII\r
136 \r
137     typedef Config_vector< std::string > Config;\r
138 \r
139     typedef Config::Value_type  Value;\r
140     typedef Config::Pair_type   Pair;\r
141     typedef Config::Object_type Object;\r
142     typedef Config::Array_type  Array;\r
143 \r
144     // typedefs for Unicode\r
145 \r
146 #ifndef BOOST_NO_STD_WSTRING\r
147 \r
148     typedef Config_vector< std::wstring > wConfig;\r
149 \r
150     typedef wConfig::Value_type  wValue;\r
151     typedef wConfig::Pair_type   wPair;\r
152     typedef wConfig::Object_type wObject;\r
153     typedef wConfig::Array_type  wArray;\r
154 #endif\r
155 \r
156     // map objects\r
157 \r
158     template< class String >\r
159     struct Config_map\r
160     {\r
161         typedef String String_type;\r
162         typedef Value_impl< Config_map > Value_type;\r
163         typedef std::vector< Value_type > Array_type;\r
164         typedef std::map< String_type, Value_type > Object_type;\r
165         typedef typename Object_type::value_type Pair_type;\r
166 \r
167         static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )\r
168         {\r
169             return obj[ name ] = value;\r
170         }\r
171                 \r
172         static String_type get_name( const Pair_type& pair )\r
173         {\r
174             return pair.first;\r
175         }\r
176                 \r
177         static Value_type get_value( const Pair_type& pair )\r
178         {\r
179             return pair.second;\r
180         }\r
181     };\r
182 \r
183     // typedefs for ASCII\r
184 \r
185     typedef Config_map< std::string > mConfig;\r
186 \r
187     typedef mConfig::Value_type  mValue;\r
188     typedef mConfig::Object_type mObject;\r
189     typedef mConfig::Array_type  mArray;\r
190 \r
191     // typedefs for Unicode\r
192 \r
193 #ifndef BOOST_NO_STD_WSTRING\r
194 \r
195     typedef Config_map< std::wstring > wmConfig;\r
196 \r
197     typedef wmConfig::Value_type  wmValue;\r
198     typedef wmConfig::Object_type wmObject;\r
199     typedef wmConfig::Array_type  wmArray;\r
200 \r
201 #endif\r
202 \r
203     ///////////////////////////////////////////////////////////////////////////////////////////////\r
204     //\r
205     // implementation\r
206 \r
207     template< class Config >\r
208     const Value_impl< Config > Value_impl< Config >::null;\r
209 \r
210     template< class Config >\r
211     Value_impl< Config >::Value_impl()\r
212     :   type_( null_type )\r
213     ,   is_uint64_( false )\r
214     {\r
215     }\r
216 \r
217     template< class Config >\r
218     Value_impl< Config >::Value_impl( const Const_str_ptr value )\r
219     :   type_( str_type )\r
220     ,   v_( String_type( value ) )\r
221     ,   is_uint64_( false )\r
222     {\r
223     }\r
224 \r
225     template< class Config >\r
226     Value_impl< Config >::Value_impl( const String_type& value )\r
227     :   type_( str_type )\r
228     ,   v_( value )\r
229     ,   is_uint64_( false )\r
230     {\r
231     }\r
232 \r
233     template< class Config >\r
234     Value_impl< Config >::Value_impl( const Object& value )\r
235     :   type_( obj_type )\r
236     ,   v_( value )\r
237     ,   is_uint64_( false )\r
238     {\r
239     }\r
240 \r
241     template< class Config >\r
242     Value_impl< Config >::Value_impl( const Array& value )\r
243     :   type_( array_type )\r
244     ,   v_( value )\r
245     ,   is_uint64_( false )\r
246     {\r
247     }\r
248 \r
249     template< class Config >\r
250     Value_impl< Config >::Value_impl( bool value )\r
251     :   type_( bool_type )\r
252     ,   v_( value )\r
253     ,   is_uint64_( false )\r
254     {\r
255     }\r
256 \r
257     template< class Config >\r
258     Value_impl< Config >::Value_impl( int value )\r
259     :   type_( int_type )\r
260     ,   v_( static_cast< boost::int64_t >( value ) )\r
261     ,   is_uint64_( false )\r
262     {\r
263     }\r
264 \r
265     template< class Config >\r
266     Value_impl< Config >::Value_impl( boost::int64_t value )\r
267     :   type_( int_type )\r
268     ,   v_( value )\r
269     ,   is_uint64_( false )\r
270     {\r
271     }\r
272 \r
273     template< class Config >\r
274     Value_impl< Config >::Value_impl( boost::uint64_t value )\r
275     :   type_( int_type )\r
276     ,   v_( static_cast< boost::int64_t >( value ) )\r
277     ,   is_uint64_( true )\r
278     {\r
279     }\r
280 \r
281     template< class Config >\r
282     Value_impl< Config >::Value_impl( double value )\r
283     :   type_( real_type )\r
284     ,   v_( value )\r
285     ,   is_uint64_( false )\r
286     {\r
287     }\r
288 \r
289     template< class Config >\r
290     Value_impl< Config >::Value_impl( const Value_impl< Config >& other )\r
291     :   type_( other.type() )\r
292     ,   v_( other.v_ )\r
293     ,   is_uint64_( other.is_uint64_ )\r
294     {\r
295     }\r
296 \r
297     template< class Config >\r
298     Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs )\r
299     {\r
300         Value_impl tmp( lhs );\r
301 \r
302         std::swap( type_, tmp.type_ );\r
303         std::swap( v_, tmp.v_ );\r
304         std::swap( is_uint64_, tmp.is_uint64_ );\r
305 \r
306         return *this;\r
307     }\r
308 \r
309     template< class Config >\r
310     bool Value_impl< Config >::operator==( const Value_impl& lhs ) const\r
311     {\r
312         if( this == &lhs ) return true;\r
313 \r
314         if( type() != lhs.type() ) return false;\r
315 \r
316         return v_ == lhs.v_; \r
317     }\r
318 \r
319     template< class Config >\r
320     Value_type Value_impl< Config >::type() const\r
321     {\r
322         return type_;\r
323     }\r
324 \r
325     template< class Config >\r
326     bool Value_impl< Config >::is_uint64() const\r
327     {\r
328         return is_uint64_;\r
329     }\r
330 \r
331     template< class Config >\r
332     bool Value_impl< Config >::is_null() const\r
333     {\r
334         return type() == null_type;\r
335     }\r
336 \r
337     template< class Config >\r
338     void Value_impl< Config >::check_type( const Value_type vtype ) const\r
339     {\r
340         if( type() != vtype ) \r
341         {\r
342             std::ostringstream os;\r
343 \r
344             os << "value type is " << type() << " not " << vtype;\r
345 \r
346             throw std::runtime_error( os.str() );\r
347         }\r
348     }\r
349 \r
350     template< class Config >\r
351     const typename Config::String_type& Value_impl< Config >::get_str() const\r
352     {\r
353         check_type(  str_type );\r
354 \r
355         return *boost::get< String_type >( &v_ );\r
356     }\r
357 \r
358     template< class Config >\r
359     const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const\r
360     {\r
361         check_type( obj_type );\r
362 \r
363         return *boost::get< Object >( &v_ );\r
364     }\r
365      \r
366     template< class Config >\r
367     const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const\r
368     {\r
369         check_type(  array_type );\r
370 \r
371         return *boost::get< Array >( &v_ );\r
372     }\r
373      \r
374     template< class Config >\r
375     bool Value_impl< Config >::get_bool() const\r
376     {\r
377         check_type(  bool_type );\r
378 \r
379         return boost::get< bool >( v_ );\r
380     }\r
381      \r
382     template< class Config >\r
383     int Value_impl< Config >::get_int() const\r
384     {\r
385         check_type(  int_type );\r
386 \r
387         return static_cast< int >( get_int64() );\r
388     }\r
389     \r
390     template< class Config >\r
391     boost::int64_t Value_impl< Config >::get_int64() const\r
392     {\r
393         check_type(  int_type );\r
394 \r
395         return boost::get< boost::int64_t >( v_ );\r
396     }\r
397     \r
398     template< class Config >\r
399     boost::uint64_t Value_impl< Config >::get_uint64() const\r
400     {\r
401         check_type(  int_type );\r
402 \r
403         return static_cast< boost::uint64_t >( get_int64() );\r
404     }\r
405 \r
406     template< class Config >\r
407     double Value_impl< Config >::get_real() const\r
408     {\r
409         if( type() == int_type )\r
410         {\r
411             return is_uint64() ? static_cast< double >( get_uint64() )\r
412                                : static_cast< double >( get_int64() );\r
413         }\r
414 \r
415         check_type(  real_type );\r
416 \r
417         return boost::get< double >( v_ );\r
418     }\r
419 \r
420     template< class Config >\r
421     typename Value_impl< Config >::Object& Value_impl< Config >::get_obj()\r
422     {\r
423         check_type(  obj_type );\r
424 \r
425         return *boost::get< Object >( &v_ );\r
426     }\r
427 \r
428     template< class Config >\r
429     typename Value_impl< Config >::Array& Value_impl< Config >::get_array()\r
430     {\r
431         check_type(  array_type );\r
432 \r
433         return *boost::get< Array >( &v_ );\r
434     }\r
435 \r
436     template< class Config >\r
437     Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value )\r
438     :   name_( name )\r
439     ,   value_( value )\r
440     {\r
441     }\r
442 \r
443     template< class Config >\r
444     bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const\r
445     {\r
446         if( this == &lhs ) return true;\r
447 \r
448         return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ );\r
449     }\r
450 \r
451     // converts a C string, ie. 8 bit char array, to a string object\r
452     //\r
453     template < class String_type >\r
454     String_type to_str( const char* c_str )\r
455     {\r
456         String_type result;\r
457 \r
458         for( const char* p = c_str; *p != 0; ++p )\r
459         {\r
460             result += *p;\r
461         }\r
462 \r
463         return result;\r
464     }\r
465 \r
466     //\r
467 \r
468     namespace internal_\r
469     {\r
470         template< typename T >\r
471         struct Type_to_type\r
472         {\r
473         };\r
474 \r
475         template< class Value > \r
476         int get_value( const Value& value, Type_to_type< int > )\r
477         {\r
478             return value.get_int();\r
479         }\r
480        \r
481         template< class Value > \r
482         boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > )\r
483         {\r
484             return value.get_int64();\r
485         }\r
486        \r
487         template< class Value > \r
488         boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > )\r
489         {\r
490             return value.get_uint64();\r
491         }\r
492        \r
493         template< class Value > \r
494         double get_value( const Value& value, Type_to_type< double > )\r
495         {\r
496             return value.get_real();\r
497         }\r
498        \r
499         template< class Value > \r
500         typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > )\r
501         {\r
502             return value.get_str();\r
503         }\r
504        \r
505         template< class Value > \r
506         typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > )\r
507         {\r
508             return value.get_array();\r
509         }\r
510        \r
511         template< class Value > \r
512         typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > )\r
513         {\r
514             return value.get_obj();\r
515         }\r
516        \r
517         template< class Value > \r
518         bool get_value( const Value& value, Type_to_type< bool > )\r
519         {\r
520             return value.get_bool();\r
521         }\r
522     }\r
523 \r
524     template< class Config >\r
525     template< typename T > \r
526     T Value_impl< Config >::get_value() const\r
527     {\r
528         return internal_::get_value( *this, internal_::Type_to_type< T >() );\r
529     }\r
530 }\r
531 \r
532 #endif\r