9 #ifndef JSON_PACK_BASE_H
10 #define JSON_PACK_BASE_H
11 #include "classdesc.h"
12 #include <json_spirit.h>
20 class json_pack_error :
public exception
22 static const int maxchars=200;
23 char errstring[maxchars];
25 json_pack_error(
const char *fmt,...)
29 vsnprintf(errstring,maxchars,fmt,args);
32 virtual ~json_pack_error() throw() {}
33 virtual const char* what()
const throw() {
return errstring;}
37 class json_pack_t:
public json_spirit::mValue
41 json_pack_t(): json_spirit::mValue(json_spirit::mObject()),
43 json_pack_t(
const json_spirit::mValue& x): json_spirit::mValue(x),
48 typedef json_pack_t json_unpack_t;
51 template <
class T>
void json_pack(json_pack_t& o,
const string& d, T& a);
53 template <
class T>
void json_pack(json_pack_t& o,
const string& d,
const T& a)
56 template <
class T>
void json_unpack(json_unpack_t& o,
const string& d, T& a);
58 template <
class T> json_pack_t& operator<<(json_pack_t& j,
const T& a)
61 template <
class T>
const json_unpack_t& operator>>(
const json_unpack_t& j, T& a)
62 {json_unpack(const_cast<json_unpack_t&>(j),
"",a);
return j;}
65 inline json_spirit::mValue&
66 json_find(json_spirit::mValue& x, std::string name)
68 if (name.size()==0)
return x;
69 if (name[0]==
'.') name.erase(0,1);
70 std::string::size_type p=name.find(
'.');
71 if (x.type()==json_spirit::obj_type)
73 json_spirit::mObject& xo=x.get_obj();
74 json_spirit::mObject::iterator i=xo.find(name.substr(0,p));
76 throw json_pack_error(
"json object %s not found", name.substr(0,p).c_str());
77 else if (p==std::string::npos)
80 return json_find(i->second,name.substr(p,std::string::npos));
83 throw json_pack_error(
"%s is not a json object",name.c_str());
87 template <
class T> json_spirit::mValue valueof(T a)
88 {
return json_spirit::mValue(a);}
89 template <
class T> T getValue(
const json_spirit::mValue& x)
90 {
return x.get_value<T>();}
92 inline json_spirit::mValue valueof(
unsigned char a)
93 {
return json_spirit::mValue(
int(a));}
94 template <>
inline unsigned char getValue(
const json_spirit::mValue& x)
95 {
return x.get_value<
int>();}
97 inline json_spirit::mValue valueof(
signed char a)
98 {
return json_spirit::mValue(
int(a));}
99 template <>
inline signed char getValue(
const json_spirit::mValue& x)
100 {
return x.get_value<
int>();}
102 inline json_spirit::mValue valueof(
char a)
103 {
return json_spirit::mValue(
int(a));}
104 template <>
inline char getValue(
const json_spirit::mValue& x)
105 {
return x.get_value<
int>();}
107 inline json_spirit::mValue valueof(
unsigned short a)
108 {
return json_spirit::mValue(
int(a));}
109 template <>
inline unsigned short getValue(
const json_spirit::mValue& x)
110 {
return x.get_value<
int>();}
112 inline json_spirit::mValue valueof(
signed short a)
113 {
return json_spirit::mValue(
int(a));}
114 template <>
inline signed short getValue(
const json_spirit::mValue& x)
115 {
return x.get_value<
int>();}
117 inline json_spirit::mValue valueof(
unsigned int a)
118 {
return json_spirit::mValue(boost::uint64_t(a));}
119 template <>
inline unsigned getValue(
const json_spirit::mValue& x)
120 {
return x.get_value<boost::uint64_t>();}
122 inline json_spirit::mValue valueof(
unsigned long a)
123 {
return json_spirit::mValue(boost::uint64_t(a));}
124 template <>
inline unsigned long getValue(
const json_spirit::mValue& x)
125 {
return x.get_value<boost::uint64_t>();}
127 inline json_spirit::mValue valueof(
long a)
128 {
return json_spirit::mValue(boost::int64_t(a));}
129 template <>
inline long getValue(
const json_spirit::mValue& x)
130 {
return x.get_value<boost::int64_t>();}
133 inline json_spirit::mValue valueof(
unsigned long long a)
134 {
return json_spirit::mValue(boost::uint64_t(a));}
135 template <>
inline unsigned long long getValue(
const json_spirit::mValue& x)
136 {
return x.get_value<boost::uint64_t>();}
138 inline json_spirit::mValue valueof(
long long a)
139 {
return json_spirit::mValue(boost::int64_t(a));}
140 template <>
inline long long getValue(
const json_spirit::mValue& x)
141 {
return x.get_value<boost::int64_t>();}
144 inline json_spirit::mValue valueof(
float a)
145 {
return json_spirit::mValue(
double(a));}
146 template <>
inline float getValue(
const json_spirit::mValue& x)
147 {
return x.get_value<
double>();}
150 template <
class T>
typename
151 enable_if<Or<is_fundamental<T>,is_string<T> >,
void>::T
152 json_packp(json_unpack_t& o,
const string& d,
const T& a, dummy<0> dum=0)
154 using namespace json_spirit;
161 json_spirit::mValue& parent=
json_find(o,head(d));
162 if (parent.type()==obj_type)
163 parent.get_obj()[tail(d)]=valueof(a);
165 throw json_pack_error(
"cannot add to a basic type");
167 catch (json_pack_error&)
170 if (o.throw_on_error)
throw;
176 template <
class T>
typename
177 enable_if<Or<is_fundamental<T>,is_string<T> >,
void>::T
178 json_unpackp(json_unpack_t& o,
string d, T& a, dummy<0> dum=0)
184 catch (
const json_pack_error&)
187 if (o.throw_on_error)
throw;
191 template <
class T>
void json_pack_isarray
192 (json_spirit::mValue& jval,
const T& val, std::vector<size_t> dims)
202 size_t s=dims.back();
203 jval=json_spirit::mArray(s);
206 for (
size_t i=0; i<dims.size(); ++i) stride*=dims[i];
207 for (
size_t i=0; i<s; ++i)
208 json_pack_isarray(jval.get_array()[i],(&val)[i*stride], dims);
214 void json_pack(json_pack_t& o,
const string& d, is_array ia,
const T& a,
215 int ndims,
size_t ncopies,...)
218 va_start(ap,ncopies);
219 std::vector<size_t> dims(ndims);
220 dims[ndims-1]=ncopies;
221 for (
int i=ndims-2; i>=0; --i) dims[i]=va_arg(ap,
size_t);
225 json_spirit::mValue& parent=
json_find(o,head(d));
226 if (parent.type()!=json_spirit::obj_type)
227 throw json_pack_error(
"attempt to pack an array member into a non-object");
229 json_pack_isarray(parent.get_obj()[tail(d)],a,dims);
231 catch (json_pack_error&)
234 if (o.throw_on_error)
throw;
238 template <
class T>
void json_unpack_isarray
239 (
const json_spirit::mValue& jval, T& val, std::vector<size_t> dims)
243 json_unpack_t j(jval);
244 json_unpack(j,
"",val);
248 size_t s=dims.back();
251 for (
size_t i=0; i<dims.size(); ++i) stride*=dims[i];
252 for (
size_t i=0; i<s; ++i)
253 json_unpack_isarray(jval.get_array()[i],(&val)[i*stride], dims);
258 void json_unpack(json_unpack_t& o,
const string& d, is_array ia, T& a,
259 int ndims,
size_t ncopies,...)
262 va_start(ap,ncopies);
263 std::vector<size_t> dims(ndims);
264 dims[ndims-1]=ncopies;
265 for (
int i=ndims-2; i>=0; --i) dims[i]=va_arg(ap,
size_t);
269 const json_spirit::mValue& v=
json_find(o,d);
270 if (v.type()!=json_spirit::array_type)
271 throw json_pack_error
272 (
"attempt to unpack an array member from a non-object");
274 json_unpack_isarray(v,a,dims);
276 catch (json_pack_error&)
279 if (o.throw_on_error)
throw;
289 template <
class T>
void json_pack(json_pack_t& x,
const string& d,
292 string tmp(static_cast<string>(arg));
297 template <
class T>
void json_unpack(json_unpack_t& x,
const string& d,
301 json_unpack(x,d,tmp);
303 int (*isspace)(int)=std::isspace;
304 std::string::iterator end=std::remove_if(tmp.begin(),tmp.end(),isspace);
305 arg=tmp.substr(0,end-tmp.begin());
309 template <
class T>
typename
310 enable_if<is_sequence<T>,
void>::T
311 json_unpackp(json_unpack_t& o,
const string& d, T& a, dummy<1> dum=0)
315 const json_spirit::mValue& val=
json_find(o,d);
316 if (val.type()!=json_spirit::array_type)
317 throw json_pack_error(
"%s is not an array",d.c_str());
320 const json_spirit::mArray& arr=val.get_array();
321 for (
size_t i=0; i<arr.size(); ++i)
323 typename T::value_type v;
324 json_unpack_t j(arr[i]);
330 catch (json_pack_error&)
332 if (o.throw_on_error)
throw;
336 template <
class T1,
class T2>
337 void json_pack(json_pack_t& o,
const string& d, std::pair<T1,T2>& a)
343 template <
class T1,
class T2>
344 void json_unpackp(json_unpack_t& o,
const string& d, std::pair<T1,T2>& a)
346 json_unpack(o,d+
".first",a.first);
347 json_unpack(o,d+
".second",a.second);
350 template <
class T>
typename
351 enable_if<Or<is_sequence<T>,is_associative_container<T> >,
void>::T
352 json_packp(json_pack_t& o,
const string& d,
const T& a, dummy<1> dum=0)
356 json_spirit::mValue& parent=
json_find(o,head(d));
357 if (parent.type()!=json_spirit::obj_type)
358 throw json_pack_error(
"attempt to pack an array member into a non-object");
361 json_spirit::mValue* v;
365 v=&parent.get_obj()[tail(d)];
367 json_spirit::mArray& arr=
368 (*v=json_spirit::mArray(a.size())).get_array();
369 typename T::const_iterator i=a.begin();
370 for (
size_t k=0; i!=a.end(); ++i, ++k)
378 catch (json_pack_error&)
380 if (o.throw_on_error)
throw;
384 template <
class T>
typename
385 enable_if<is_associative_container<T>,
void>::T
386 json_unpackp(json_unpack_t& o,
const string& d, T& a, dummy<2> dum=0)
390 const json_spirit::mValue& val=
json_find(o,d);
391 if (val.type()!=json_spirit::array_type)
392 throw json_pack_error(
"%s is not an array",d.c_str());
395 const json_spirit::mArray& arr=val.get_array();
396 for (
size_t i=0; i<arr.size(); ++i)
398 typename NonConstKeyValueType<typename T::value_type>::T v;
399 json_unpack_t j(arr[i]);
405 catch (json_pack_error&)
407 if (o.throw_on_error)
throw;
414 template <
class C,
class T>
415 void json_pack(json_pack_t& targ,
const string& desc, C& c, T arg) {}
417 template <
class C,
class T>
418 void json_unpack(json_unpack_t& targ,
const string& desc, C& c, T arg) {}
424 void json_pack(json_pack_t& targ,
const string& desc, is_const_static i, T arg)
428 void json_unpack(json_unpack_t& targ,
const string& desc, is_const_static i, T arg)
432 template <
class T,
class U>
433 void json_pack(json_pack_t&,
const string&, is_const_static,
const T&, U) {}
436 template <
class T,
class U>
437 void json_unpack(json_unpack_t&,
const string&, is_const_static,
const T&, U) {}
440 void json_unpack(json_unpack_t& targ,
const string& desc,
const T& arg) {}
443 void json_pack(json_pack_t& targ,
const string& desc, Exclude<T>& arg) {}
446 void json_unpack(json_unpack_t& targ,
const string& desc, Exclude<T>& arg) {}
449 template <
class T>
string json(
const T& x)
455 template <
class T>
void json(
const T& x,
const string& s)
463 void json_pack_onbase(json_pack_t& x,
const string& d,T& a)
467 void json_unpack_onbase(json_unpack_t& x,
const string& d,T& a)
468 {json_unpack(x,d+basename<T>(),a);}
473 namespace classdesc_access
475 template <
class T>
struct access_json_pack;
476 template <
class T>
struct access_json_unpack;
479 using classdesc::json_pack_onbase;
480 using classdesc::json_unpack_onbase;
483 using classdesc::json_unpack;
bool throw_on_error
enable exceptions on error conditions
Definition: json_pack_base.h:40
string json(const T &x)
produce json string equivalent of object x
Definition: json_pack_base.h:449
void json_pack(json_pack_t &o, const string &d, T &a)
forward declare generic json operations
Definition: json_pack_epilogue.h:53
json_spirit::mValue & json_find(json_spirit::mValue &x, std::string name)
find an object named by name within the json object x
Definition: json_pack_base.h:66