Bytemaster's Boost Libraries
|
00001 #ifndef _BOOST_RPC_DYNAMIC_RAW_HPP_ 00002 #define _BOOST_RPC_DYNAMIC_RAW_HPP_ 00003 00010 namespace boost { namespace rpc { namespace dynamic { 00011 namespace raw { 00012 00013 template<typename T> 00014 class parser; 00015 class parser_base; 00016 class skip_parser; 00017 00018 class description_database { 00019 public: 00020 boost::optional<boost::rpc::description> get_description( const std::string& type_name )const { 00021 type_description_map::const_iterator itr = m_type_db.find(type_name); 00022 if( itr != m_type_db.end() ) 00023 return itr->second; 00024 return boost::optional<boost::rpc::description>(); 00025 } 00026 void set( const std::string& name, const boost::rpc::description& d ) { 00027 m_type_db[name]=d; 00028 } 00029 00030 template<typename T> 00031 parser<T>* get_parser(); 00032 00033 skip_parser* get_skip_parser(const std::string& type); 00034 00035 private: 00036 typedef std::map<std::string, boost::rpc::description> type_description_map; 00037 typedef std::map<std::string, skip_parser*> type_skipper_map; 00038 typedef std::map<std::string, parser_base*> type_parser_map; 00039 type_description_map m_type_db; 00040 type_skipper_map m_skipper_db; 00041 type_parser_map m_parser_db; 00042 }; 00043 00044 template<typename Class> 00045 class member_parser_base { 00046 public: 00047 virtual member_parser_base(){} 00048 virtual void unpack( std::istream& s, Class& self )=0; 00049 virtual void pack( std::ostream& s, const Class& self )=0; 00050 }; 00051 00052 template<typename T, typename Class> 00053 class member_parser : public member_parser_base<Class> { 00054 public: 00055 member_parser( T (Class::*m ), description_database& db ) 00056 :member(m) { 00057 member_parser = db.get_parser<T>(); 00058 } 00059 00060 void unpack( std::istream& s, Class& self ) { 00061 member_parser->unpack( s, self.*member ); 00062 } 00063 void pack( std::ostream& s, const Class& self ) { 00064 member_parser->pack( s, self.*member ); 00065 } 00066 00067 parser<T>* member_parser; 00068 T (Class::*member); 00069 }; 00070 00076 struct create_member_parser { 00077 create_member_parser( boost::rpc::description::field& f, description_database& db ) 00078 :m_parser(NULL), m_db(db), m_field(f){} 00079 00080 template<typename T> 00081 inline void operator()( T (Class::*p), const char* name )const { 00082 if( std::string(name) == m_field.name ) { 00083 if( m_field.type == boost::reflect::get_typename<T>() ) 00084 m_parser = new member_parser<T,Class>(p,m_db); 00085 else { 00086 // consider ignoring this as if it was not present... 00087 throw "fields with same name have different types"; 00088 } 00089 } 00090 } 00091 parser_base* m_parser; 00092 boost::rpc::description_database& m_db; 00093 boost::rpc::description::field& m_field; 00094 }; 00095 00096 template<typename Class> 00097 class skip_member_parser : public member_parser_base<Class> { 00098 public: 00099 skip_member_parser( boost::rpc::description::field& f, boost::rpc::description_database& db ) { 00100 m_parser = db.get_skip_parser( f.type ); 00101 } 00102 void unpack( std::istream& s, Class& ) { m_parser->skip( s ); } 00103 void pack( std::ostream& s, const Class& ) { m_parser->skip( s ); } 00104 private: 00105 skip_parser* m_parser; 00106 }; 00107 00108 class skip_parser { 00109 public: 00110 skip_parser( boost::rpc::description& d, description_database& db ) { 00111 for( uint32_t i = 0; i < d.fields.size(); ++i ) { 00112 m_fields.push_back( db.get_skip_parser( d.feilds[i].type ) ); 00113 } 00114 } 00115 00116 template<typename Stream> 00117 void skip( Stream& s ) { 00118 std::vector<skip_parser*>::iterator itr = m_fields.begin(); 00119 while( itr != m_fields.end() ) { 00120 (*itr)->skip(s); 00121 ++itr; 00122 } 00123 } 00124 std::vector<skip_parser*> m_fields; 00125 }; 00126 class public_base { 00127 public: 00128 virtual ~public_base(){}; 00129 }; 00130 00131 template<typename T> 00132 class parser : public parser_base { 00133 public: 00134 parser( boost::rpc::description& d, description_database& db ) { 00135 for( uint32_t i = 0; i < d.fields.size(); ++i ) { 00136 create_member_parser<T> v( d.fields[i], db ); 00137 boost::reflect::reflector<T>::visit( v ); 00138 // add the field to the parse order or create a skip parser 00139 m_fields.push_back( v.get_parser() ? v.get_parser() : new skip_member_parser<T>( d.fields[i], db ) ); 00140 } 00141 } 00142 virtual void unpack( std::istream& s, T& v ) { 00143 for( uint32_t i = 0; i < m_fields.size(); ++i ) { 00144 m_fields[i]->unpack( s, v ); 00145 } 00146 } 00147 virtual void pack( std::ostream& s, const T& v ) { 00148 for( uint32_t i = 0; i < m_fields.size(); ++i ) { 00149 m_fields[i]->pack( s, v ); 00150 } 00151 } 00152 private: 00153 std::vector<member_parser<T>*> m_fields; 00154 }; 00155 00156 } // namespace raw 00157 } } } // boost::rpc::dynamic 00158 00159 #endif