Bytemaster's Boost Libraries
/Users/dlarimer/dev/libs/rpc/include/boost/rpc/json/value_io.hpp
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
 All Classes Namespaces Files Functions Variables Typedefs Defines