00001 #ifndef _BOOST_RPC_RAW_HPP_
00002 #define _BOOST_RPC_RAW_HPP_
00003 #include <boost/rpc/datastream.hpp>
00004 #include <boost/rpc/varint.hpp>
00005 #include <boost/rpc/errors.hpp>
00006 #include <boost/rpc/required.hpp>
00007 #include <boost/reflect/reflect.hpp>
00008 #include <boost/optional.hpp>
00009 #include <boost/throw_exception.hpp>
00010 #include <boost/fusion/container/vector.hpp>
00011 #include <boost/fusion/algorithm.hpp>
00012 #include <boost/fusion/support/is_sequence.hpp>
00013 #include <boost/fusion/sequence/intrinsic/size.hpp>
00014
00015 #include <iostream>
00016 #include <boost/rpc/log/log.hpp>
00017
00018 namespace boost { namespace rpc { namespace raw {
00019
00020 namespace detail {
00021
00022 template<bool IsReflected=true>
00023 struct if_reflected;
00024
00025 template<typename DataStreamType>
00026 class unpack_message_visitor : public boost::reflect::visitor< unpack_message_visitor<DataStreamType> >
00027 {
00028 public:
00029 unpack_message_visitor( boost::rpc::datastream<DataStreamType>& os )
00030 :m_os(os){}
00031
00035 template<typename T, typename Flags>
00036 inline void unpack_field( T& value, const char* name, Flags key, boost::true_type _is_fundamental ) {
00037 m_os >> value;
00038 }
00039
00044 template< typename T, typename Flags>
00045 void unpack_field( T& value, const char* name, Flags key, boost::false_type _is_not_fundamental ) {
00046 unpack( value );
00047 }
00048
00049 template<typename DST>
00050 struct visit_sequence
00051 {
00052 visit_sequence( datastream<DST>& _ds ):pmv(_ds){}
00053
00054 mutable unpack_message_visitor<DST> pmv;
00055
00056 template<typename T>
00057 void operator() ( T& v )const
00058 {
00059 pmv.unpack_field(v,0,0, typename boost::is_fundamental<T>::type());
00060 }
00061 };
00062
00063 template< typename T>
00064 void unpack( T& value, boost::false_type _is_not_fundamental, boost::mpl::true_ _is_fusion_sequence) {
00065 visit_sequence<DataStreamType> unpack_vector(m_os);
00066 boost::fusion::for_each( value, unpack_vector );
00067 }
00068
00069
00070 template< typename T>
00071 void unpack( T& value, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence) {
00072 if_reflected<boost::reflect::reflector<T>::is_defined>::unpack( m_os, value );
00073 }
00074
00075 void unpack( std::string& value, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence) {
00076 uint32_t size;
00077 m_os >> size;
00078 value.resize(size);
00079 std::vector<char> tmp(size);
00080 if( size )
00081 m_os.read( &tmp.front(), tmp.size() );
00082 value = std::string(tmp.begin(),tmp.end());
00083 }
00084
00085 template< typename T >
00086 void unpack( T& value, boost::true_type _is_fundamental, boost::mpl::false_ _is_not_fusion_sequence) {
00087 m_os >> value;
00088 }
00089 template< typename T >
00090 void unpack( T& value ) {
00091 unpack( value, typename boost::is_fundamental<T>::type(), typename boost::fusion::traits::is_sequence<T>::type() );
00092 }
00093
00094 template<typename Flags>
00095 void unpack_field( signed_int& value, const char* name, Flags key, boost::false_type _is_not_fundamental ) {
00096 m_os >> value;
00097 }
00098 template<typename Flags>
00099 void unpack_field( unsigned_int& value, const char* name, Flags key, boost::false_type _is_not_fundamental ) {
00100 m_os >> value;
00101 }
00102 template<typename Flags>
00103 void unpack_field( std::string& value, const char* name, Flags key, boost::false_type _is_not_fundamental ) {
00104 unpack( value );
00105 }
00106 template<typename T, typename Flags>
00107 void unpack_field( boost::optional<T>& value, const char* name, Flags key, boost::false_type _is_not_fundamental ) {
00108 uint8_t present;
00109 m_os >> present;
00110 if( present ) {
00111 if( !value )
00112 value = T();
00113 unpack_field( *value, name, key, typename boost::is_fundamental<T>::type() );
00114 }
00115 }
00116 template<typename T, typename Flags>
00117 void unpack_field( typename boost::rpc::required<T>& value, const char* name, Flags key, boost::false_type _is_not_fundamental ) {
00118 if( !!value )
00119 unpack_field( *value, name, key, typename boost::is_fundamental<T>::type() );
00120 else
00121 BOOST_THROW_EXCEPTION( boost::rpc::required_field_not_set() );
00122 }
00123
00124 template<typename Class, typename T, typename Flags>
00125 void accept_member( Class& c, T (Class::*p), const char* name, Flags key ) {
00126 unpack_field( c.*p, name, key, typename boost::is_fundamental<T>::type() );
00127 }
00128
00129 template<typename Field, typename Alloc, template<typename,typename> class Container>
00130 void unpack( Container<Field,Alloc>& c, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence) {
00131 uint32_t size;
00132 m_os >> size;
00133 if( size )
00134 {
00135 c.resize(size);
00136 typename Container<Field,Alloc >::iterator itr = c.begin();
00137 typename Container<Field,Alloc >::iterator end = c.end();
00138 while( itr != end )
00139 {
00140 unpack( *itr );
00141 ++itr;
00142 }
00143 }
00144 }
00145
00146 template<typename First, typename Second>
00147 void unpack( std::pair<First,Second>& c, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence) {
00148 unpack( c.first );
00149 unpack( c.second );
00150 }
00151
00152
00153 template<typename Class, typename Field, typename Alloc, template<typename,typename> class Container, typename Flags>
00154 void accept_member( Class& c, Container<Field,Alloc> (Class::*p), const char* name, Flags key ) {
00155 unpack( c.*p );
00156 }
00157 private:
00158 boost::rpc::datastream<DataStreamType>& m_os;
00159 };
00160
00161
00162 template<typename DataStreamType>
00163 class pack_message_visitor : public boost::reflect::visitor< unpack_message_visitor<DataStreamType> >
00164 {
00165 public:
00166 pack_message_visitor( boost::rpc::datastream<DataStreamType>& os )
00167 :m_os(os){}
00168
00172 template<typename T, typename Flags>
00173 inline void pack_field( const T& value, const char* name, Flags key, boost::true_type _is_fundamental )
00174 {
00175 m_os << value;
00176 }
00177
00182 template< typename T, typename Flags>
00183 void pack_field( const T& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00184 {
00185 pack( value );
00186 }
00187
00188 template<typename DST>
00189 struct visit_sequence
00190 {
00191 visit_sequence( datastream<DST>& _ds ):pmv(_ds){}
00192
00193 mutable pack_message_visitor<DST> pmv;
00194
00195 template<typename T>
00196 void operator() ( const T& v )const
00197 {
00198 pmv.pack_field(v,0,0, typename boost::is_fundamental<T>::type());
00199 }
00200 };
00201
00202 template< typename T>
00203 void pack( const T& value, boost::false_type _is_not_fundamental, boost::mpl::true_ _is_fusion_sequence)
00204 {
00205 visit_sequence<DataStreamType> pack_vector(m_os);
00206 boost::fusion::for_each( value, pack_vector );
00207 }
00208 template<typename Field, typename Alloc, template<typename,typename> class Container>
00209 void pack( const Container<Field,Alloc>& c, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence)
00210 {
00211 m_os << uint32_t( c.size() );
00212 if( c.size() )
00213 {
00214 typename Container<Field,Alloc >::const_iterator itr = c.begin();
00215 typename Container<Field,Alloc >::const_iterator end = c.end();
00216 while( itr != end )
00217 {
00218 pack( *itr );
00219 ++itr;
00220 }
00221 }
00222 }
00223
00224 template<typename First, typename Second>
00225 void pack( const std::pair<First,Second>& c, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence)
00226 {
00227 pack( c.first );
00228 pack( c.second );
00229 }
00230
00231 template< typename T>
00232 void pack( const T& value, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence)
00233 {
00234 if_reflected<boost::reflect::reflector<T>::is_defined>::pack( m_os, value );
00235
00236
00237 }
00238
00239 void pack( const std::string& value, boost::false_type _is_not_fundamental, boost::mpl::false_ _is_not_fusion_sequence)
00240 {
00241 uint32_t size = value.size();
00242 m_os << size;
00243 m_os.write( value.c_str(), size );
00244 }
00245
00246 template< typename T >
00247 void pack( const T& value, boost::true_type _is_fundamental, boost::mpl::false_ _is_not_fusion_sequence)
00248 {
00249 m_os << value;
00250 }
00251 template< typename T >
00252 void pack( const T& value )
00253 {
00254 pack( value, typename boost::is_fundamental<T>::type(), typename boost::fusion::traits::is_sequence<T>::type() );
00255 }
00256
00257 template<typename Flags>
00258 void pack_field( const signed_int& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00259 {
00260 m_os << value;
00261 }
00262 template<typename Flags>
00263 void pack_field( const unsigned_int& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00264 {
00265 m_os << value;
00266 }
00267 template<typename Flags>
00268 void pack_field( const std::string& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00269 {
00270 pack( value );
00271 }
00272 template<typename T, typename Flags>
00273 void pack_field( const boost::optional<T>& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00274 {
00275 uint8_t present = !!value;
00276 m_os << present;
00277 if( present )
00278 pack_field( *value, name, key, typename boost::is_fundamental<T>::type() );
00279 }
00280 template<typename T, typename Flags>
00281 void pack_field( const typename boost::rpc::required<T>& value, const char* name, Flags key, boost::false_type _is_not_fundamental )
00282 {
00283 if( !!value )
00284 pack_field( *value, name, key, typename boost::is_fundamental<T>::type() );
00285 else
00286 BOOST_THROW_EXCEPTION( boost::rpc::required_field_not_set() );
00287 }
00288
00289 template<typename Class, typename T, typename Flags>
00290 void accept_member( const Class& c, T (Class::*p), const char* name, Flags key )
00291 {
00292 pack_field( c.*p, name, key, typename boost::is_fundamental<T>::type() );
00293 }
00294
00295 template<typename Class, typename Field, typename Alloc, template<typename,typename> class Container, typename Flags>
00296 void accept_member( const Class& c, Container<Field,Alloc> (Class::*p), const char* name, Flags key )
00297 {
00298 pack( c.*p );
00299 }
00300 private:
00301 boost::rpc::datastream<DataStreamType>& m_os;
00302 };
00303
00304 template<bool IsReflected>
00305 struct if_reflected
00306 {
00307 template<typename DataStreamType, typename T>
00308 inline static void unpack( boost::rpc::datastream<DataStreamType>& ds, T& value )
00309 {
00310 detail::unpack_message_visitor<DataStreamType> unpack_visitor( ds );
00311 boost::reflect::reflector<T>::visit( value, unpack_visitor, -1 );
00312 }
00313 template<typename DataStreamType, typename T>
00314 inline static void pack( boost::rpc::datastream<DataStreamType>& ds, const T& value )
00315 {
00316 detail::pack_message_visitor<DataStreamType> pack_visitor( ds );
00317 boost::reflect::reflector<T>::visit( value, pack_visitor, -1 );
00318 }
00319 };
00320 template<>
00321 struct if_reflected<false>
00322 {
00323 template<typename DataStream, typename T>
00324 inline static void unpack( DataStream& ds, T& value )
00325 {
00326 ds >> value;
00327 }
00328 template<typename DataStream, typename T>
00329 inline static void pack( DataStream& ds, const T& value )
00330 {
00331 ds << value;
00332 }
00333 };
00334
00335 }
00336
00337 template<typename T>
00338 size_t packsize( const T& v )
00339 {
00340 boost::rpc::datastream<size_t> ps;
00341 detail::pack_message_visitor<size_t> size_visitor( ps );
00342 size_visitor.pack(v);
00343 return ps.tellp();
00344 }
00345 template<typename T>
00346 void pack( char* loc, size_t loc_size, const T& v )
00347 {
00348 boost::rpc::datastream<char*> ds(loc, loc_size);
00349 detail::pack_message_visitor<char*> pack_visitor( ds );
00350 pack_visitor.pack(v);
00351 }
00352 template<typename T, typename DataStreamType>
00353 void pack( boost::rpc::datastream<DataStreamType>& ds, const T& v )
00354 {
00355 detail::pack_message_visitor<DataStreamType> pack_visitor( ds );
00356 pack_visitor.pack(v);
00357 }
00358 template<typename T>
00359 void pack( std::vector<char>& msg, const T& v )
00360 {
00361 msg.resize(packsize(v));
00362 pack( &msg.front(), msg.size(), v );
00363 }
00364 template<typename T>
00365 void pack( std::string& msg, const T& v )
00366 {
00367 msg.resize(packsize(v));
00368 pack( msg.c_str(), msg.size(), v );
00369 }
00370
00371 template<typename T>
00372 void unpack( const char* msg, size_t msg_size, T& v )
00373 {
00374 boost::rpc::datastream<const char*> ds(msg,msg_size);
00375 detail::unpack_message_visitor<const char*> unpack_visitor( ds );
00376 unpack_visitor.unpack(v);
00377 }
00378
00379 template<typename T>
00380 void unpack( const std::vector<char>& msg, T& v )
00381 {
00382 if( msg.size() )
00383 unpack( &msg.front(), msg.size(), v );
00384 }
00385
00386
00387 } } }
00388
00389 #endif // _BOOST_RPC_DETAIL_RAW_HPP_
00390