#pragma once #include "../global.h" #include #include #include #include #include #include #include #include #include #include #include #include const int version = 63; class CConnection; namespace mpl = boost::mpl; namespace boost { namespace asio { namespace ip { class tcp; } class io_service; template class stream_socket_service; template class basic_stream_socket; template class socket_acceptor_service; template class basic_socket_acceptor; } class mutex; }; enum SerializationLvl { Wrong=0, Primitive, Pointer, Serializable }; template struct SerializationLevel { typedef mpl::integral_c_tag tag; typedef typename mpl::eval_if< boost::is_fundamental, mpl::int_, //else typename mpl::eval_if< boost::is_class, mpl::int_, //else typename mpl::eval_if< boost::is_array, mpl::int_, //else typename mpl::eval_if< boost::is_pointer, mpl::int_, //else typename mpl::eval_if< boost::is_enum, mpl::int_, //else mpl::int_ > > > > >::type type; static const int value = SerializationLevel::type::value; }; template class DLL_EXPORT COSer { public: bool saving; COSer(){saving=true;}; Serializer * This() { return static_cast(this); } template Serializer & operator<<(const T &t) { this->This()->save(t); return * this->This(); } template COSer & operator&(T & t){ return * this->This() << t; } }; template class DLL_EXPORT CISer { public: bool saving; CISer(){saving = false;}; Serializer * This() { return static_cast(this); } template Serializer & operator>>(T &t) { this->This()->load(t); return * this->This(); } template CISer & operator&(T & t){ return * this->This() >> t; } }; template struct SavePrimitive { static void invoke(Ser &s, const T &data) { s.savePrimitive(data); } }; template struct SaveSerializable { static void invoke(Ser &s, const T &data) { s.saveSerializable(data); } }; template struct LoadPrimitive { static void invoke(Ser &s, T &data) { s.loadPrimitive(data); } }; template struct SavePointer { static void invoke(Ser &s, const T &data) { s.savePointer(data); } }; template struct LoadPointer { static void invoke(Ser &s, T &data) { s.loadPointer(data); } }; template struct LoadSerializable { static void invoke(Ser &s, T &data) { s.loadSerializable(data); } }; template struct SaveWrong { static void invoke(Ser &s, const T &data) { throw std::exception("Wrong save serialization call!"); } }; template struct LoadWrong { static void invoke(Ser &s, const T &data) { throw std::exception("Wrong load serialization call!"); } }; class DLL_EXPORT CConnection :public CISer, public COSer { std::ostream &out; CConnection(void); void init(); public: boost::mutex *rmx, *wmx; // read/write mutexes template void savePrimitive(const T &data) { write(&data,sizeof(data)); } template void loadPrimitive(T &data) { read(&data,sizeof(data)); } template void saveSerializable(const T &data) { const_cast(data).serialize(*static_cast*>(this),version); } template void loadSerializable(T &data) { data.serialize(*static_cast*>(this),version); } template void savePointer(const T &data) { *this << *data; } template void loadPointer(T &data) { std::cout<<"Allocating memory for pointer!"<::type npT; data = new npT; *this >> *data; } template void saveSerializable(const std::vector &data) { boost::uint32_t length = data.size(); *this << length; for(ui32 i=0;i void loadSerializable(std::vector &data) { boost::uint32_t length; *this >> length; data.resize(length); for(ui32 i=0;i> data[i]; } template void saveSerializable(const std::set &data) { std::set &d = const_cast &>(data); boost::uint32_t length = d.size(); *this << length; for(typename std::set::iterator i=d.begin();i!=d.end();i++) *this << *i; } template void loadSerializable(std::set &data) { boost::uint32_t length; *this >> length; T ins; for(ui32 i=0;i> ins; data.insert(ins); } } template void saveSerializable(const std::pair &data) { *this << data.first << data.second; } template void loadSerializable(std::pair &data) { *this >> data.first >> data.second; } template void saveSerializable(const std::map &data) { *this << ui32(data.size()); for(typename std::map::const_iterator i=data.begin();i!=data.end();i++) *this << i->first << i->second; } template void loadSerializable(std::map &data) { ui32 length; *this >> length; T1 t; for(int i=0;i> t; *this >> data[t]; } } template void save(const T &data) { typedef //if typename mpl::eval_if< mpl::equal_to,mpl::int_ >, mpl::identity >, //else if typename mpl::eval_if,mpl::int_ >, mpl::identity >, //else if typename mpl::eval_if,mpl::int_ >, mpl::identity >, //else mpl::identity > > > >::type typex; typex::invoke(*this, data); } template void load(T &data) { typedef //if typename mpl::eval_if< mpl::equal_to,mpl::int_ >, mpl::identity >, //else if typename mpl::eval_if,mpl::int_ >, mpl::identity >, //else if typename mpl::eval_if,mpl::int_ >, mpl::identity >, //else mpl::identity > > > >::type typex; typex::invoke(*this, data); } boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service > * socket; bool logging; bool connected; bool myEndianess, contactEndianess; //true if little endian, if ednianess is different we'll have to revert recieved multi-byte vars boost::asio::io_service *io_service; std::string name; //who uses this connection CConnection (std::string host, std::string port, std::string Name, std::ostream & Out); CConnection (boost::asio::basic_socket_acceptor > * acceptor, boost::asio::io_service *Io_service, std::string Name, std::ostream & Out); CConnection (boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service > * Socket, std::string Name, std::ostream & Out); //use immediately after accepting connection into socket int write(const void * data, unsigned size); int read(void * data, unsigned size); int readLine(void * data, unsigned maxSize); void close(); ~CConnection(void); }; template<> DLL_EXPORT void CConnection::saveSerializable(const std::string &data); template <>DLL_EXPORT void CConnection::loadSerializable(std::string &data);