Bytemaster's Boost Libraries
|
00001 #ifndef _BOOST_RPC_JSON_VALUE_IO_HPP_ 00002 #define _BOOST_RPC_JSON_VALUE_IO_HPP_ 00003 #include <boost/reflect/reflect.hpp> 00004 00005 #include <boost/rpc/varint.hpp> 00006 #include <boost/rpc/required.hpp> 00007 #include <boost/rpc/errors.hpp> 00008 #include <boost/cmt/log/log.hpp> 00009 #include <boost/rpc/base64.hpp> 00010 #include <sstream> 00011 #include <iostream> 00012 #include <map> 00013 #include <iomanip> 00014 00015 #include <boost/fusion/container/vector.hpp> 00016 #include <boost/fusion/algorithm.hpp> 00017 #include <boost/fusion/support/is_sequence.hpp> 00018 #include <boost/fusion/sequence/intrinsic/size.hpp> 00019 #include <boost/rpc/json/value.hpp> 00020 00021 namespace boost { namespace rpc { namespace json { 00022 00023 template<typename T> 00024 void pack( boost::rpc::json::value& jsv, const T& v ); 00025 template<typename T> 00026 void unpack( const boost::rpc::json::value& jsv, T& v ); 00027 00028 inline void pack( boost::rpc::json::value& jsv, const bool& v ) { jsv = v; } 00029 inline void pack( boost::rpc::json::value& jsv, const float& v ) { jsv = v; } 00030 inline void pack( boost::rpc::json::value& jsv, const double& v ) { jsv = v; } 00031 inline void pack( boost::rpc::json::value& jsv, const uint8_t& v ) { jsv = v; } 00032 inline void pack( boost::rpc::json::value& jsv, const uint16_t& v ) { jsv = v; } 00033 inline void pack( boost::rpc::json::value& jsv, const uint32_t& v ) { jsv = v; } 00034 inline void pack( boost::rpc::json::value& jsv, const uint64_t& v ) { jsv = v; } 00035 inline void pack( boost::rpc::json::value& jsv, const int8_t& v ) { jsv = v; } 00036 inline void pack( boost::rpc::json::value& jsv, const int16_t& v ) { jsv = v; } 00037 inline void pack( boost::rpc::json::value& jsv, const int32_t& v ) { jsv = v; } 00038 inline void pack( boost::rpc::json::value& jsv, const int64_t& v ) { jsv = v; } 00039 inline void pack( boost::rpc::json::value& jsv, const signed_int& v ) { jsv = boost::rpc::json::value((int64_t)v.value); } 00040 inline void pack( boost::rpc::json::value& jsv, const unsigned_int& v ) { jsv = boost::rpc::json::value((uint64_t)v.value); } 00041 inline void pack( boost::rpc::json::value& jsv, const std::string& v ) { jsv = v; } 00042 inline void pack( boost::rpc::json::value& jsv, const char* v ) { jsv = v; } 00043 00044 void pack( boost::rpc::json::value& jsv, const std::vector<char>& value ); 00045 template<typename T> 00046 void pack( boost::rpc::json::value& jsv, const boost::optional<T>& v ); 00047 template<typename T> 00048 void pack( boost::rpc::json::value& jsv, const required<T>& v ); 00049 template<typename T, typename Alloc, template<typename,typename> class Container> 00050 void pack( boost::rpc::json::value& jsv, const Container<T,Alloc>& value ); 00051 template<typename Key, typename Value> 00052 void pack( boost::rpc::json::value& jsv, const std::map<Key,Value>& value ); 00053 template<typename Key, typename Value> 00054 void pack( boost::rpc::json::value& jsv, const std::pair<Key,Value>& value ); 00055 template<typename Value> 00056 void pack( boost::rpc::json::value& jsv, const std::map<std::string,Value>& value ); 00057 00058 00059 template<typename T> 00060 void unpack( const boost::rpc::json::value& jsv, const T& v ); 00061 template<typename T> 00062 void unpack( const boost::rpc::json::value& jsv, T& v ); 00063 void unpack( const boost::rpc::json::value& jsv, bool& v ); 00064 void unpack( const boost::rpc::json::value& jsv, float& v ); 00065 void unpack( const boost::rpc::json::value& jsv, double& v ); 00066 void unpack( const boost::rpc::json::value& jsv, uint8_t& v ); 00067 void unpack( const boost::rpc::json::value& jsv, uint16_t& v ); 00068 void unpack( const boost::rpc::json::value& jsv, uint32_t& v ); 00069 void unpack( const boost::rpc::json::value& jsv, uint64_t& v ); 00070 void unpack( const boost::rpc::json::value& jsv, int8_t& v ); 00071 void unpack( const boost::rpc::json::value& jsv, int16_t& v ); 00072 void unpack( const boost::rpc::json::value& jsv, int32_t& v ); 00073 void unpack( const boost::rpc::json::value& jsv, int64_t& v ); 00074 void unpack( const boost::rpc::json::value& jsv, signed_int& v ); 00075 void unpack( const boost::rpc::json::value& jsv, unsigned_int& v ); 00076 void unpack( const boost::rpc::json::value& jsv, std::string& v ); 00077 void unpack( const boost::rpc::json::value& jsv, std::vector<char>& value ); 00078 template<typename T> 00079 void unpack( const boost::rpc::json::value& jsv, boost::optional<T>& v ); 00080 template<typename T> 00081 void unpack( const boost::rpc::json::value& jsv, required<T>& v ); 00082 template<typename T, typename Alloc, template<typename,typename> class Container> 00083 void unpack( const boost::rpc::json::value& jsv, Container<T,Alloc>& value ); 00084 template<typename Key, typename Value> 00085 void unpack( const boost::rpc::json::value& jsv, std::map<Key,Value>& value ); 00086 template<typename Key, typename Value> 00087 void unpack( const boost::rpc::json::value& jsv, std::pair<Key,Value>& value ); 00088 template<typename Value> 00089 void unpack( const boost::rpc::json::value& jsv, std::map<std::string,Value>& val ); 00090 00091 namespace detail { 00092 template<typename Class> 00093 struct pack_object_visitor { 00094 pack_object_visitor(const Class& _c, boost::rpc::json::object& _val) 00095 :c(_c),obj(_val){} 00096 00100 template<typename T> 00101 inline void pack_helper( const T& v, const char* name )const { 00102 boost::rpc::json::pack( obj[name], v ); 00103 } 00104 template<typename T> 00105 inline void pack_helper( const boost::optional<T>& v, const char* name )const { 00106 if( !!v ) { 00107 boost::rpc::json::pack( obj[name], *v ); 00108 } 00109 } 00110 template<typename T,typename C, T(C::*p)> 00111 inline void operator()( const char* name )const { 00112 pack_helper( c.*p, name ); 00113 } 00114 00115 private: 00116 const Class& c; 00117 boost::rpc::json::object& obj; 00118 }; 00119 00120 template<typename Class> 00121 struct unpack_object_visitor { 00122 unpack_object_visitor(Class& _c, const boost::rpc::json::object& _val) 00123 :c(_c),obj(_val){} 00124 00125 template<typename T,typename C, T(C::*p)> 00126 void operator()( const char* name )const { 00127 boost::rpc::json::unpack( obj[name], c.*p ); 00128 } 00129 Class& c; 00130 const boost::rpc::json::object& obj; 00131 }; 00132 00133 struct pack_sequence { 00134 pack_sequence( boost::rpc::json::array& _a ):a(_a){} 00135 00136 boost::rpc::json::array& a; 00137 00138 template<typename T> 00139 void operator() ( const T& v )const { 00140 a.push_back( boost::rpc::json::value()); 00141 boost::rpc::json::pack(a.back(),v); 00142 } 00143 }; 00144 struct unpack_sequence { 00145 unpack_sequence( boost::rpc::json::array::const_iterator& _a ):a(_a){} 00146 00147 boost::rpc::json::array::const_iterator& a; 00148 00149 template<typename T> 00150 void operator() ( T& v )const { 00151 if( a != boost::rpc::json::array::const_iterator() ) { 00152 boost::rpc::json::unpack(*a,v); 00153 ++a; 00154 } 00155 } 00156 }; 00157 00158 template<bool IsFusionSeq> struct if_fusion_seq { 00159 template<typename T> 00160 inline static void pack( boost::rpc::json::value& jsv, const T& v ) { 00161 jsv = boost::rpc::json::array(); 00162 pack_sequence pack_vector( jsv ); //boost::get<boost::rpc::json::array>(jsv) ); 00163 boost::fusion::for_each( v, pack_vector ); 00164 } 00165 template<typename T> 00166 inline static void unpack( const boost::rpc::json::value& jsv, T& v ) { 00167 boost::rpc::json::array::const_iterator itr = boost::get<boost::rpc::json::array>(jsv.val).begin(); 00168 unpack_sequence unpack_vector(itr); 00169 boost::fusion::for_each( v, unpack_vector ); 00170 } 00171 }; 00172 template<> struct if_fusion_seq<false> { 00173 template<typename T> 00174 inline static void pack( boost::rpc::json::value& jsv, const T& v ) { 00175 jsv = boost::rpc::json::object(); 00176 detail::pack_object_visitor<T> pov(v,jsv); 00177 boost::reflect::reflector<T>::visit(pov); 00178 } 00179 template<typename T> 00180 inline static void unpack( const boost::rpc::json::value& jsv, T& v ) { 00181 detail::unpack_object_visitor<T> pov(v,jsv ); 00182 boost::reflect::reflector<T>::visit(pov); 00183 } 00184 }; 00185 } // namesapce detail 00186 00187 00188 inline void unpack( const boost::rpc::json::value& jsv, bool& v ) { v = jsv; } 00189 inline void unpack( const boost::rpc::json::value& jsv, float& v ) { v = jsv; } 00190 inline void unpack( const boost::rpc::json::value& jsv, double& v ) { v = jsv; } 00191 inline void unpack( const boost::rpc::json::value& jsv, uint8_t& v ) { v = jsv; } 00192 inline void unpack( const boost::rpc::json::value& jsv, uint16_t& v ) { v = jsv; } 00193 inline void unpack( const boost::rpc::json::value& jsv, uint32_t& v ) { v = jsv; } 00194 inline void unpack( const boost::rpc::json::value& jsv, uint64_t& v ) { v = jsv; } 00195 inline void unpack( const boost::rpc::json::value& jsv, int8_t& v ) { v = jsv; } 00196 inline void unpack( const boost::rpc::json::value& jsv, int16_t& v ) { v = jsv; } 00197 inline void unpack( const boost::rpc::json::value& jsv, int32_t& v ) { v = jsv; } 00198 inline void unpack( const boost::rpc::json::value& jsv, int64_t& v ) { v = jsv; } 00199 inline void unpack( const boost::rpc::json::value& jsv, signed_int& v ) { v.value = jsv; } 00200 inline void unpack( const boost::rpc::json::value& jsv, unsigned_int& v ) { v.value = jsv; } 00201 inline void unpack( const boost::rpc::json::value& jsv, std::string& v ) { v = (const std::string&)jsv; } 00202 00203 template<typename T> 00204 inline void pack( boost::rpc::json::value& jsv, const T& v ) { 00205 detail::if_fusion_seq< boost::fusion::traits::is_sequence<T>::value >::pack(jsv,v); 00206 } 00207 00208 00209 template<typename T> 00210 inline void pack( boost::rpc::json::value& jsv, const boost::optional<T>& v ) { 00211 boost::rpc::json::pack( jsv, *v ); 00212 } 00213 00214 template<typename T> 00215 inline void pack( boost::rpc::json::value& jsv, const required<T>& v ) { 00216 if( !v ) BOOST_THROW_EXCEPTION( boost::rpc::required_field_not_set() ); 00217 boost::rpc::json::pack( jsv, *v ); 00218 } 00219 template<typename T> 00220 inline void unpack( const boost::rpc::json::value& jsv, required<T>& v ) { 00221 v = T(); 00222 boost::rpc::json::unpack( jsv, *v ); 00223 } 00224 template<typename T> 00225 inline void unpack( const boost::rpc::json::value& jsv, optional<T>& v ) { 00226 v = T(); 00227 boost::rpc::json::unpack( jsv, *v ); 00228 } 00229 00230 00231 template<typename T, typename Alloc, template<typename,typename> class Container> 00232 inline void pack( boost::rpc::json::value& jsv, const Container<T,Alloc>& value ) { 00233 jsv = boost::rpc::json::array(); 00234 boost::rpc::json::array& a = jsv; 00235 a.resize(value.size()); 00236 typename Container<T,Alloc>::const_iterator itr = value.begin(); 00237 typename Container<T,Alloc>::const_iterator end = value.end(); 00238 uint32_t i = 0; 00239 while( itr != end ) { 00240 boost::rpc::json::pack( a[i], *itr ); 00241 ++itr; 00242 ++i; 00243 } 00244 } 00245 00246 template<typename T, typename Alloc, template<typename,typename> class Container> 00247 inline void unpack( const boost::rpc::json::value& jsv, Container<T,Alloc>& value ) { 00248 const boost::rpc::json::array& a = jsv; 00249 value.resize( a.size() ); 00250 typename Container<T,Alloc>::iterator itr = value.begin(); 00251 typename Container<T,Alloc>::iterator end = value.end(); 00252 uint32_t i = 0; 00253 while( itr != end ) { 00254 boost::rpc::json::unpack( a[i], *itr ); 00255 ++itr; 00256 ++i; 00257 } 00258 } 00259 00260 // support for pair! 00261 template<typename Key, typename Value> 00262 inline void pack( boost::rpc::json::value& jsv, const std::pair<Key,Value>& val ) { 00263 jsv = boost::rpc::json::object(); 00264 boost::rpc::json::pack( jsv[std::string("first")], val.first ); 00265 boost::rpc::json::pack( jsv[std::string("second")], val.second ); 00266 } 00267 // support for pair! 00268 template<typename Key, typename Value> 00269 void unpack( const boost::rpc::json::value& jsv, std::pair<Key,Value>& val ) { 00270 boost::rpc::json::unpack( jsv[std::string("first")], val.first ); 00271 boost::rpc::json::unpack( jsv[std::string("second")], val.second ); 00272 } 00273 00274 00275 // support arbitrary key/value containers as an array of pairs 00276 template<typename Key, typename Value> 00277 void pack( boost::rpc::json::value& jsv, const std::map<Key,Value>& value ) { 00278 jsv = boost::rpc::json::array(); 00279 boost::rpc::json::array& a = jsv; 00280 a.resize(value.size()); 00281 typename std::map<Key,Value>::const_iterator itr = value.begin(); 00282 typename std::map<Key,Value>::const_iterator end = value.end(); 00283 uint32_t i = 0; 00284 while( itr != end ) { 00285 boost::rpc::json::pack( a[i], *itr ); 00286 ++itr; 00287 ++i; 00288 } 00289 } 00290 00291 template<typename Key, typename Value> 00292 inline void unpack( const boost::rpc::json::value& jsv, std::map<Key,Value>& value ) { 00293 const boost::rpc::json::array& a = jsv; 00294 value.clear(); 00295 for( uint32_t i = 0; i < a.size(); ++i ) { 00296 std::pair<Key,Value> p; 00297 boost::rpc::json::unpack( a[i], p ); 00298 value[p.first] = p.second; 00299 } 00300 } 00301 00302 inline void pack( boost::rpc::json::value& jsv, const std::vector<char>& data ) { 00303 if( data.size() ) { pack( jsv, base64_encode((unsigned char*)&data.front(),data.size())); } 00304 } 00305 inline void unpack( const boost::rpc::json::value& jsv, std::vector<char>& data ) { 00306 data.clear(); 00307 std::string d = base64_decode(jsv); 00308 data.insert(data.begin(),d.begin(),d.end()); 00309 } 00310 00311 00312 // pack map<string,T> as a JSON Object 00313 template<typename Value> 00314 void pack( boost::rpc::json::value& jsv, const std::map<std::string,Value>& val ) { 00315 jsv = boost::rpc::json::object(); 00316 boost::rpc::json::object& o = jsv; 00317 o.reserve(val.size()); 00318 typename std::map<std::string,Value>::const_iterator itr = val.begin(); 00319 typename std::map<std::string,Value>::const_iterator end = val.end(); 00320 while( itr != end ) { 00321 boost::rpc::json::pack( o[itr->first], itr->second ); 00322 ++itr; 00323 } 00324 } 00325 template<typename Value> 00326 void unpack( const boost::rpc::json::value& jsv, std::map<std::string,Value>& val ) { 00327 const boost::rpc::json::object& o = jsv; 00328 val.clear(); 00329 for( uint32_t i = 0; i < o.keys.size(); ++i ) { 00330 boost::rpc::json::unpack( o.keys[i].val, val[o.keys[i].key] ); 00331 } 00332 } 00333 template<typename T> 00334 inline void unpack( const boost::rpc::json::value& jsv, T& v ) { 00335 detail::if_fusion_seq< boost::fusion::traits::is_sequence<T>::value >::unpack(jsv,v); 00336 } 00337 00338 template<typename T> 00339 std::ostream& to_json( std::ostream& os, const T& v ) { 00340 boost::rpc::json::value jsv; 00341 pack( jsv, v ); 00342 write(os,jsv); 00343 return os; 00344 } 00345 00346 template<typename T> 00347 struct to_json_helper { 00348 inline to_json_helper( const T& v):val(v){} 00349 operator std::string()const; 00350 const T& val; 00351 }; 00352 template<typename T> 00353 to_json_helper<T> to_json( const T& v ) { 00354 return v; 00355 } 00356 template<typename T> 00357 inline std::ostream& operator<<(std::ostream& os, const to_json_helper<T>& h ) { 00358 return to_json( os, h.val); 00359 } 00360 template<typename T> 00361 to_json_helper<T>::operator std::string()const { 00362 std::stringstream ss; ss << *this; 00363 return ss.str(); 00364 } 00365 00366 template<typename T> 00367 void from_json( const std::string& j, T& val ) { 00368 boost::rpc::json::value v; 00369 boost::rpc::json::read( j, v ); 00370 unpack( v, val ); 00371 } 00372 00373 } } } // namespace boost::rpc::json 00374 00375 #endif // BOOST_RPC_JSON_VALUE_IO_HPP