#ifndef __CONNECTION_H__ #define __CONNECTION_H__ #include "../global.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include const ui32 version = 63; class CConnection; namespace mpl = boost::mpl; template char (&_ArrayCountObj(const T (&)[N]))[N]; #define ARRAY_COUNT(arr) (sizeof(_ArrayCountObj(arr))) 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, Array, Pointer, Serializable }; 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 SaveArray { static void invoke(Ser &s, const T &data) { s.saveArray(data); } }; template struct LoadArray { static void invoke(Ser &s, T &data) { s.loadArray(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::string("Wrong save serialization call!"); } }; template struct LoadWrong { static void invoke(Ser &s, const T &data) { throw std::string("Wrong load serialization call!"); } }; 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&(const T & t) { return * this->This() << t; } int write(const void * data, unsigned size); template void savePrimitive(const T &data) { this->This()->write(&data,sizeof(data)); } template void savePointer(const T &data) { ui8 hlp = (data!=NULL); *this << hlp; if(hlp) *this << *data; } template void saveArray(const T &data) { ui32 size = ARRAY_COUNT(data); for(ui32 i=0; i < size; i++) *this << data[i]; } 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 if typename mpl::eval_if,mpl::int_ >, mpl::identity >, //else mpl::identity > > > > >::type typex; typex::invoke(* this->This(), data); } template void saveSerializable(const T &data) { const_cast(data).serialize(*this,version); } template void saveSerializable(const std::vector &data) { boost::uint32_t length = data.size(); *this << length; for(ui32 i=0;i 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 saveSerializable(const std::list &data) { std::list &d = const_cast &>(data); boost::uint32_t length = d.size(); *this << length; for(typename std::list::iterator i=d.begin();i!=d.end();i++) *this << *i; } void saveSerializable(const std::string &data) { *this << ui32(data.length()); this->This()->write(data.c_str(),data.size()); } template void saveSerializable(const 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 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; } int write(const void * data, unsigned size); 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 if typename mpl::eval_if,mpl::int_ >, mpl::identity >, //else mpl::identity > > > > >::type typex; typex::invoke(* this->This(), data); } template void loadPrimitive(T &data) { this->This()->read(&data,sizeof(data)); } template void loadSerializable(T &data) { data.serialize(*this,version); } template void loadArray(T &data) { ui32 size = ARRAY_COUNT(data); for(ui32 i=0; i < size; i++) *this >> data[i]; } template void loadPointer(T &data) { ui8 hlp; *this >> hlp; if(!hlp) { data = NULL; return; } tlog5<<"Allocating memory for pointer!"<::type npT; data = new npT; *this >> *data; } template void loadSerializable(std::vector &data) { boost::uint32_t length; *this >> length; data.resize(length); for(ui32 i=0;i> data[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 loadSerializable(std::list &data) { boost::uint32_t length; *this >> length; T ins; for(ui32 i=0;i> ins; data.push_back(ins); } } template void loadSerializable(std::pair &data) { *this >> data.first >> data.second; } template void loadSerializable(std::map &data) { ui32 length; *this >> length; T1 t; for(int i=0;i> t; *this >> data[t]; } } void loadSerializable(std::string &data) { ui32 length; *this >> length; data.resize(length); this->This()->read((void*)data.c_str(),length); } }; class DLL_EXPORT CSaveFile : public COSer { void dummyMagicFunction() { *this << std::string("This function makes stuff working."); } public: std::ofstream *sfile; CSaveFile(const std::string &fname); ~CSaveFile(); int write(const void * data, unsigned size); }; class DLL_EXPORT CLoadFile : public CISer { void dummyMagicFunction() { std::string dummy = "This function makes stuff working."; *this >> dummy; } public: std::ifstream *sfile; CLoadFile(const std::string &fname); ~CLoadFile(); int read(const void * data, unsigned size); }; class DLL_EXPORT CConnection :public CISer, public COSer { CConnection(void); void init(); public: boost::mutex *rmx, *wmx; // read/write mutexes 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); CConnection (boost::asio::basic_socket_acceptor > * acceptor, boost::asio::io_service *Io_service, std::string Name); CConnection (boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service > * Socket, std::string Name); //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); }; #endif // __CONNECTION_H__