Bytemaster's Boost Libraries
/Users/dlarimer/dev/libs/rpc/include/boost/rpc/raw.hpp
00001 #ifndef _BOOST_RPC_RAW_HPP_
00002 #define _BOOST_RPC_RAW_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 
00020 namespace boost { namespace rpc { namespace raw {
00021 
00022     template<typename Stream, typename T>
00023     inline void pack( Stream& s, const T& v );
00024     template<typename Stream, typename T>
00025     inline void unpack( Stream& s, T& v );
00026     template<typename Stream, typename T, typename Alloc, template<typename,typename> class Container>
00027     inline void pack( Stream& s, const Container<T,Alloc>& value );
00028     template<typename Stream, typename T, typename Alloc, template<typename,typename> class Container>
00029     inline void unpack( Stream& s, Container<T,Alloc>& value );
00030     template<typename Stream, typename Key, typename Value>
00031     void pack( Stream& s, const std::map<Key,Value>& value );
00032     template<typename Stream, typename Key, typename Value>
00033     void unpack( Stream& s, std::map<Key,Value>& value );
00034 
00035     template<typename Stream> inline void pack( Stream& s, const signed_int& v ) {
00036       uint32_t val = (v.value<<1) ^ (v.value>>31);
00037       do {
00038         uint8_t b = uint8_t(val) & 0x7f;
00039         val >>= 7;
00040         b |= ((val > 0) << 7);
00041         s.put(b);
00042       } while( val );
00043     }
00044     template<typename Stream> inline void pack( Stream& s, const unsigned_int& v ) {
00045       uint64_t val = v.value;
00046       do {
00047         uint8_t b = uint8_t(val) & 0x7f;
00048         val >>= 7;
00049         b |= ((val > 0) << 7);
00050         s.put(b);
00051       }while( val );
00052     }
00053 
00054 
00055     template<typename Stream> inline void pack( Stream& s, const bool& v ) { pack( s, uint8_t(v) );     }
00056     template<typename Stream> inline void pack( Stream& s, const char* v ) { pack( s, std::string(v) ); }
00057 
00058     template<typename Stream, typename T> 
00059     inline void pack( Stream& s, const required<T>& v ) { pack( s, *v); }
00060 
00061     template<typename Stream, typename T> 
00062     inline void pack( Stream& s, const boost::optional<T>& v ) {
00063       pack( s, bool(v) );
00064       if( v ) 
00065         pack( s, *v );
00066     }
00067     template<typename Stream> inline void pack( Stream& s, const std::vector<char>& value ) { 
00068       pack( s, unsigned_int(value.size()) );
00069       if( value.size() )
00070         s.write( &value.front(), value.size() );
00071     }
00072     template<typename Stream> inline void pack( Stream& s, const std::string& v )  {
00073       pack( s, unsigned_int(v.size()) );     
00074       if( v.size() )
00075         s.write( v.c_str(), v.size() );
00076     }
00077 
00078     template<typename Stream> inline void unpack( Stream& s, signed_int& vi ) {
00079       uint32_t v = 0; char b = 0; int by = 0;
00080       do {
00081         s.get(b);
00082         v |= uint32_t(uint8_t(b) & 0x7f) << by;
00083         by += 7;
00084       } while( uint8_t(b) & 0x80 );
00085       vi.value = ((v>>1) ^ (v>>31)) + (v&0x01);
00086       vi.value = v&0x01 ? vi.value : -vi.value;
00087       vi.value = -vi.value;
00088     }
00089     template<typename Stream> inline void unpack( Stream& s, unsigned_int& vi ) {
00090       uint64_t v = 0; char b = 0; uint8_t by = 0;
00091       do {
00092           s.get(b);
00093           v |= uint32_t(uint8_t(b) & 0x7f) << by;
00094           by += 7;
00095       } while( uint8_t(b) & 0x80 );
00096       vi.value = v;
00097     }
00098     template<typename Stream> inline void unpack( Stream& s, bool& v ) {
00099       uint8_t b; 
00100       unpack( s, b ); 
00101       v=b;    
00102     }
00103     template<typename Stream> inline void unpack( Stream& s, std::vector<char>& value ) { 
00104       unsigned_int size; unpack( s, size );
00105       value.resize(size.value);
00106       if( value.size() )
00107         s.read( &value.front(), value.size() );
00108     }
00109     template<typename Stream> inline void unpack( Stream& s, std::string& v )  {
00110       std::vector<char> tmp; unpack(s,tmp);
00111       v = std::string(tmp.begin(),tmp.end());
00112     }
00113 
00114     template<typename Stream, typename T>
00115     void unpack( const Stream& s, boost::optional<T>& v ) {
00116       bool b; unpack( s, b ); 
00117       if( b ) { v = T(); unpack( s, *v ); }
00118     }
00119     template<typename Stream, typename T>
00120     void unpack( const Stream& s, required<T>& v ) {
00121       v = T(); unpack( s, *v );
00122     }
00123     template<typename Stream, typename T, typename Alloc, template<typename,typename> class Container>
00124     void unpack( const Stream& s, Container<T,Alloc>& value );
00125     template<typename Stream, typename Key, typename Value>
00126     void unpack( const Stream& s, std::map<Key,Value>& value );
00127     template<typename Stream, typename Key, typename Value>
00128     void unpack( const Stream& s, std::pair<Key,Value>& value );
00129     template<typename Stream, typename Value>
00130     void unpack( const Stream& s, std::map<std::string,Value>& val );
00131 
00132     namespace detail {
00133     
00134       template<typename Stream, typename Class>
00135       struct pack_object_visitor {
00136         pack_object_visitor(const Class& _c, Stream& _s)
00137         :c(_c),s(_s){}
00138 
00143         template<typename T>
00144         inline void pack_helper( const T& v, const char* name )const {
00145           boost::rpc::raw::pack( s, v ); 
00146         }
00147         template<typename T>
00148         inline void pack_helper( const boost::optional<T>& v, const char* name )const {
00149           if( !!v ) boost::rpc::raw::pack( s, *v ); 
00150         }
00151         template<typename T, typename C, T(C::*p)>
00152         inline void operator()( const char* name )const {
00153           pack_helper( c.*p, name );
00154         }
00155         private:            
00156           const Class& c;
00157           Stream&      s;
00158       };
00159 
00160       template<typename Stream, typename Class>
00161       struct unpack_object_visitor {
00162         unpack_object_visitor(Class& _c, Stream& _s)
00163         :c(_c),s(_s){}
00164 
00165         template<typename T, typename C, T(C::*p)>
00166         inline void operator()( const char* name )const {
00167           boost::rpc::raw::unpack( s, c.*p );
00168         }
00169         private:            
00170           Class&  c;
00171           Stream& s;
00172       };
00173 
00174       template<typename Stream>
00175       struct pack_sequence {
00176          pack_sequence( Stream& _s ):s(_s){}
00177          template<typename T>
00178          void operator() ( const T& v )const { boost::rpc::raw::pack(s,v); }
00179          Stream&    s;
00180       };
00181 
00182       template<typename Stream>
00183       struct unpack_sequence {
00184          unpack_sequence( Stream& _s ):s(_s){}
00185          template<typename T>
00186          void operator() ( T& v )const { boost::rpc::raw::unpack(s,v); }
00187          Stream&  s;
00188       };
00189 
00190 
00191       template<typename IsReflected=boost::false_type>
00192       struct if_reflected {
00193         template<typename Stream, typename T>
00194         static inline void pack( Stream& s, const T& v ) { 
00195           BOOST_STATIC_ASSERT( boost::is_pod<T>::value );
00196           s.write( (char*)&v, sizeof(v) );   
00197         }
00198         template<typename Stream, typename T>
00199         static inline void unpack( Stream& s, T& v ) { 
00200           BOOST_STATIC_ASSERT( boost::is_pod<T>::value );
00201           s.read( (char*)&v, sizeof(v) );   
00202         }
00203       };
00204       template<>
00205       struct if_reflected<boost::true_type> {
00206         template<typename Stream, typename T>
00207         static inline void pack( Stream& s, const T& v ) { 
00208           boost::reflect::reflector<T>::visit( pack_object_visitor<Stream,T>( v, s ) );
00209         }
00210         template<typename Stream, typename T>
00211         static inline void unpack( Stream& s, T& v ) { 
00212           boost::reflect::reflector<T>::visit( unpack_object_visitor<Stream,T>( v, s ) );
00213         }
00214       };
00215 
00216       template<typename IsFusionSeq> 
00217       struct if_fusion_seq {
00218         template<typename Stream, typename T> 
00219         inline static void pack( Stream& s, const T& v ) {
00220           pack_sequence<Stream> pack_vector( s );
00221           boost::fusion::for_each( v, pack_vector );
00222         }
00223         template<typename Stream, typename T> 
00224         inline static void unpack( Stream& s, T& v ) {
00225           unpack_sequence<Stream> unpack_vector(s);
00226           boost::fusion::for_each( v, unpack_vector );
00227         }
00228       };
00229 
00230       template<> 
00231       struct if_fusion_seq<boost::mpl::false_> {
00232         template<typename Stream, typename T> 
00233         inline static void pack( Stream& s, const T& v ) {
00234           if_reflected<typename boost::reflect::reflector<T>::is_defined>::pack(s,v);
00235         }
00236         template<typename Stream, typename T> 
00237         inline static void unpack( Stream& s, T& v ) {
00238           if_reflected<typename boost::reflect::reflector<T>::is_defined>::unpack(s,v);
00239         }
00240       };
00241     } // namesapce detail
00242 
00243     
00244 
00245     template<typename Stream, typename T, typename Alloc, template<typename,typename> class Container>
00246     inline void pack( Stream& s, const Container<T,Alloc>& value ) {
00247       pack( s, unsigned_int(value.size()) );
00248       typename Container<T,Alloc>::const_iterator itr = value.begin();
00249       typename Container<T,Alloc>::const_iterator end = value.end();
00250       while( itr != end ) {
00251         boost::rpc::raw::pack( s, *itr );
00252         ++itr;
00253       }
00254     }
00255 
00256     template<typename Stream, typename T, typename Alloc, template<typename,typename> class Container>
00257     inline void unpack( Stream& s, Container<T,Alloc>& value ) {
00258       unsigned_int size; unpack( s, size );
00259       value.resize(size.value);
00260       typename Container<T,Alloc>::iterator itr = value.begin();
00261       typename Container<T,Alloc>::iterator end = value.end();
00262       while( itr != end ) {
00263         boost::rpc::raw::unpack( s, *itr );
00264         ++itr;
00265       }
00266     }
00267 
00268     // support for pair!
00269     template<typename Stream, typename Key, typename Value>
00270     inline void pack( Stream& s, const std::pair<Key,Value>& val ) {
00271       boost::rpc::raw::pack( s, val.first );
00272       boost::rpc::raw::pack( s, val.second );
00273     }
00274     // support for pair!
00275     template<typename Stream, typename Key, typename Value>
00276     void unpack( Stream& s, std::pair<Key,Value>& val ) {
00277       boost::rpc::raw::unpack( s, val.first );
00278       boost::rpc::raw::unpack( s, val.second );
00279     }
00280 
00281 
00282     // support arbitrary key/value containers as an array of pairs
00283     template<typename Stream, typename Key, typename Value>
00284     void pack( Stream& s, const std::map<Key,Value>& value ) {
00285       pack( s, unsigned_int(value.size()) );
00286       typename std::map<Key,Value>::const_iterator itr = value.begin();
00287       typename std::map<Key,Value>::const_iterator end = value.end();
00288       while( itr != end ) {
00289         boost::rpc::raw::pack( s, *itr );
00290         ++itr;
00291       }
00292     }
00293 
00294     template<typename Stream, typename Key, typename Value>
00295     inline void unpack( Stream& s, std::map<Key,Value>& value ) {
00296       unsigned_int size; unpack( s, size );
00297       value.clear();
00298       for( uint32_t i = 0; i < size.value; ++i ) {
00299         Key k; 
00300         boost::rpc::raw::unpack(s,k);
00301         boost::rpc::raw::unpack(s,value[k]);
00302       }
00303     }
00304     template<typename Stream, typename T> 
00305     inline void pack( Stream& s, const T& v ) {
00306       detail::if_fusion_seq< typename boost::fusion::traits::is_sequence<T>::type >::pack(s,v);
00307     }
00308     template<typename Stream, typename T> 
00309     inline void unpack( Stream& s, T& v ) {
00310       detail::if_fusion_seq< typename boost::fusion::traits::is_sequence<T>::type >::unpack(s,v);
00311     }
00312     
00313 } } } // namespace boost::rpc::raw
00314 
00315 #endif // BOOST_RPC_RAW_HPP
 All Classes Namespaces Files Functions Variables Typedefs Defines