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