Connection.h 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. /*
  2. * Connection.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. #include <typeinfo> //XXX this is in namespace std if you want w/o use typeinfo.h?
  12. #include <boost/type_traits/is_fundamental.hpp>
  13. #include <boost/type_traits/is_enum.hpp>
  14. #include <boost/type_traits/is_pointer.hpp>
  15. #include <boost/type_traits/is_class.hpp>
  16. #include <boost/type_traits/is_base_of.hpp>
  17. #include <boost/type_traits/is_array.hpp>
  18. #include <boost/type_traits/remove_pointer.hpp>
  19. #include <boost/type_traits/remove_const.hpp>
  20. #include <boost/variant.hpp>
  21. #include <boost/mpl/eval_if.hpp>
  22. #include <boost/mpl/equal_to.hpp>
  23. #include <boost/mpl/int.hpp>
  24. #include <boost/mpl/identity.hpp>
  25. #include <boost/any.hpp>
  26. #include "ConstTransitivePtr.h"
  27. #include "CCreatureSet.h" //for CStackInstance
  28. #include "CObjectHandler.h" //for CArmedInstance
  29. #include "Mapping/CCampaignHandler.h" //for CCampaignState
  30. const ui32 version = 734;
  31. const TSlot COMMANDER_SLOT_PLACEHOLDER = -2;
  32. class CConnection;
  33. class CGObjectInstance;
  34. class CStackInstance;
  35. class CGameState;
  36. class CCreature;
  37. class LibClasses;
  38. class CHero;
  39. struct CPack;
  40. extern DLL_LINKAGE LibClasses * VLC;
  41. namespace mpl = boost::mpl;
  42. namespace boost
  43. {
  44. namespace asio
  45. {
  46. namespace ip
  47. {
  48. class tcp;
  49. }
  50. class io_service;
  51. template <typename Protocol> class stream_socket_service;
  52. template <typename Protocol,typename StreamSocketService>
  53. class basic_stream_socket;
  54. template <typename Protocol> class socket_acceptor_service;
  55. template <typename Protocol,typename SocketAcceptorService>
  56. class basic_socket_acceptor;
  57. }
  58. class mutex;
  59. }
  60. enum SerializationLvl
  61. {
  62. Wrong=0,
  63. Primitive,
  64. Array,
  65. Pointer,
  66. Enum,
  67. Serializable
  68. };
  69. struct TypeComparer
  70. {
  71. bool operator()(const std::type_info *a, const std::type_info *b) const
  72. {
  73. return a->before(*b);
  74. }
  75. };
  76. class DLL_LINKAGE CTypeList
  77. {
  78. typedef std::multimap<const std::type_info *,ui16,TypeComparer> TTypeMap;
  79. TTypeMap types;
  80. public:
  81. CTypeList();
  82. ui16 registerType(const std::type_info *type);
  83. template <typename T> ui16 registerType(const T * t = NULL)
  84. {
  85. return registerType(getTypeInfo(t));
  86. }
  87. ui16 getTypeID(const std::type_info *type);
  88. template <typename T> ui16 getTypeID(const T * t = NULL)
  89. {
  90. return getTypeID(getTypeInfo(t));
  91. }
  92. template <typename T> const std::type_info * getTypeInfo(const T * t = NULL)
  93. {
  94. if(t)
  95. return &typeid(*t);
  96. else
  97. return &typeid(T);
  98. }
  99. };
  100. extern DLL_LINKAGE CTypeList typeList;
  101. template<typename Ser,typename T>
  102. struct SavePrimitive
  103. {
  104. static void invoke(Ser &s, const T &data)
  105. {
  106. s.savePrimitive(data);
  107. }
  108. };
  109. template<typename Ser,typename T>
  110. struct SaveSerializable
  111. {
  112. static void invoke(Ser &s, const T &data)
  113. {
  114. s.saveSerializable(data);
  115. }
  116. };
  117. template<typename Ser,typename T>
  118. struct SaveEnum
  119. {
  120. static void invoke(Ser &s, const T &data)
  121. {
  122. s.saveEnum(data);
  123. }
  124. };
  125. template<typename Ser,typename T>
  126. struct LoadEnum
  127. {
  128. static void invoke(Ser &s, T &data)
  129. {
  130. s.loadEnum(data);
  131. }
  132. };
  133. template<typename Ser,typename T>
  134. struct LoadPrimitive
  135. {
  136. static void invoke(Ser &s, T &data)
  137. {
  138. s.loadPrimitive(data);
  139. }
  140. };
  141. template<typename Ser,typename T>
  142. struct SavePointer
  143. {
  144. static void invoke(Ser &s, const T &data)
  145. {
  146. s.savePointer(data);
  147. }
  148. };
  149. template<typename Ser,typename T>
  150. struct LoadPointer
  151. {
  152. static void invoke(Ser &s, T &data)
  153. {
  154. s.loadPointer(data);
  155. }
  156. };
  157. template<typename Ser,typename T>
  158. struct SaveArray
  159. {
  160. static void invoke(Ser &s, const T &data)
  161. {
  162. s.saveArray(data);
  163. }
  164. };
  165. template<typename Ser,typename T>
  166. struct LoadArray
  167. {
  168. static void invoke(Ser &s, T &data)
  169. {
  170. s.loadArray(data);
  171. }
  172. };
  173. template<typename Ser,typename T>
  174. struct LoadSerializable
  175. {
  176. static void invoke(Ser &s, T &data)
  177. {
  178. s.loadSerializable(data);
  179. }
  180. };
  181. template<typename Ser,typename T>
  182. struct SaveWrong
  183. {
  184. static void invoke(Ser &s, const T &data)
  185. {
  186. throw std::runtime_error("Wrong save serialization call!");
  187. }
  188. };
  189. template<typename Ser,typename T>
  190. struct LoadWrong
  191. {
  192. static void invoke(Ser &s, const T &data)
  193. {
  194. throw std::runtime_error("Wrong load serialization call!");
  195. }
  196. };
  197. template<typename T>
  198. struct SerializationLevel
  199. {
  200. typedef mpl::integral_c_tag tag;
  201. typedef
  202. typename mpl::eval_if<
  203. boost::is_fundamental<T>,
  204. mpl::int_<Primitive>,
  205. //else
  206. typename mpl::eval_if<
  207. boost::is_enum<T>,
  208. mpl::int_<Enum>,
  209. //else
  210. typename mpl::eval_if<
  211. boost::is_class<T>,
  212. mpl::int_<Serializable>,
  213. //else
  214. typename mpl::eval_if<
  215. boost::is_array<T>,
  216. mpl::int_<Array>,
  217. //else
  218. typename mpl::eval_if<
  219. boost::is_pointer<T>,
  220. mpl::int_<Pointer>,
  221. //else
  222. typename mpl::eval_if<
  223. boost::is_enum<T>,
  224. mpl::int_<Primitive>,
  225. //else
  226. mpl::int_<Wrong>
  227. >
  228. >
  229. >
  230. >
  231. >
  232. >::type type;
  233. static const int value = SerializationLevel::type::value;
  234. };
  235. template <typename T>
  236. struct VectorisedObjectInfo
  237. {
  238. const std::vector<ConstTransitivePtr<T> > *vector; //pointer to the appropriate vector
  239. const si32 T::*idPtr; //pointer to the field representing the position in the vector
  240. VectorisedObjectInfo(const std::vector< ConstTransitivePtr<T> > *Vector, const si32 T::*IdPtr)
  241. :vector(Vector), idPtr(IdPtr)
  242. {
  243. }
  244. };
  245. /// Class which is responsible for storing and loading data.
  246. class DLL_LINKAGE CSerializer
  247. {
  248. public:
  249. typedef std::map<const std::type_info *, boost::any, TypeComparer> TTypeVecMap;
  250. TTypeVecMap vectors; //entry must be a pointer to vector containing pointers to the objects of key type
  251. bool smartVectorMembersSerialization;
  252. bool sendStackInstanceByIds;
  253. CSerializer();
  254. ~CSerializer();
  255. virtual void reportState(CLogger &out){};
  256. template <typename T>
  257. void registerVectoredType(const std::vector<T*> *Vector, const si32 T::*IdPtr)
  258. {
  259. vectors[&typeid(T)] = VectorisedObjectInfo<T>(Vector, IdPtr);
  260. }
  261. template <typename T>
  262. void registerVectoredType(const std::vector<ConstTransitivePtr<T> > *Vector, const si32 T::*IdPtr)
  263. {
  264. vectors[&typeid(T)] = VectorisedObjectInfo<T>(Vector, IdPtr);
  265. }
  266. template <typename T>
  267. const VectorisedObjectInfo<T> *getVectorisedTypeInfo()
  268. {
  269. const std::type_info *myType = NULL;
  270. //
  271. // if(boost::is_base_of<CGObjectInstance, T>::value) //ugly workaround to support also types derived from CGObjectInstance -> if we encounter one, treat it aas CGObj..
  272. // myType = &typeid(CGObjectInstance);
  273. // else
  274. myType = &typeid(T);
  275. TTypeVecMap::iterator i = vectors.find(myType);
  276. if(i == vectors.end())
  277. return NULL;
  278. else
  279. {
  280. assert(!i->second.empty());
  281. assert(i->second.type() == typeid(VectorisedObjectInfo<T>));
  282. VectorisedObjectInfo<T> *ret = &(boost::any_cast<VectorisedObjectInfo<T>&>(i->second));
  283. return ret;
  284. }
  285. }
  286. template <typename T>
  287. T* getVectorItemFromId(const VectorisedObjectInfo<T> &oInfo, ui32 id) const
  288. {
  289. /* if(id < 0)
  290. return NULL;*/
  291. assert(oInfo.vector);
  292. assert(oInfo.vector->size() > id);
  293. return const_cast<T*>((*oInfo.vector)[id].get());
  294. }
  295. template <typename T>
  296. si32 getIdFromVectorItem(const VectorisedObjectInfo<T> &oInfo, const T* obj) const
  297. {
  298. if(!obj)
  299. return -1;
  300. return obj->*oInfo.idPtr;
  301. }
  302. void addStdVecItems(CGameState *gs, LibClasses *lib = VLC);
  303. };
  304. class DLL_LINKAGE CSaverBase : public virtual CSerializer
  305. {
  306. };
  307. class CBasicPointerSaver
  308. {
  309. public:
  310. virtual void savePtr(CSaverBase &ar, const void *data) const =0;
  311. virtual ~CBasicPointerSaver(){}
  312. };
  313. template <typename Serializer, typename T> class CPointerSaver : public CBasicPointerSaver
  314. {
  315. public:
  316. void savePtr(CSaverBase &ar, const void *data) const
  317. {
  318. Serializer &s = static_cast<Serializer&>(ar);
  319. const T *ptr = static_cast<const T*>(data);
  320. //T is most derived known type, it's time to call actual serialize
  321. const_cast<T&>(*ptr).serialize(s,version);
  322. }
  323. };
  324. template <typename T> //metafunction returning CGObjectInstance if T is its derivate or T elsewise
  325. struct VectorisedTypeFor
  326. {
  327. typedef typename
  328. //if
  329. mpl::eval_if<boost::is_base_of<CGObjectInstance,T>,
  330. mpl::identity<CGObjectInstance>,
  331. //else
  332. mpl::identity<T>
  333. >::type type;
  334. };
  335. template <typename Handler>
  336. struct VariantVisitorSaver : boost::static_visitor<>
  337. {
  338. Handler &h;
  339. VariantVisitorSaver(Handler &H):h(H)
  340. {
  341. }
  342. template <typename T>
  343. void operator()(const T &t)
  344. {
  345. h << t;
  346. }
  347. };
  348. template<typename Ser,typename T>
  349. struct SaveIfStackInstance
  350. {
  351. static bool invoke(Ser &s, const T &data)
  352. {
  353. return false;
  354. }
  355. };
  356. template<typename Ser>
  357. struct SaveIfStackInstance<Ser, CStackInstance *>
  358. {
  359. static bool invoke(Ser &s, const CStackInstance* const &data)
  360. {
  361. assert(data->armyObj);
  362. TSlot slot = -1;
  363. if(data->getNodeType() == Bonus::COMMANDER)
  364. slot = COMMANDER_SLOT_PLACEHOLDER;
  365. else
  366. slot = data->armyObj->findStack(data);
  367. assert(slot != -1);
  368. s << data->armyObj << slot;
  369. return true;
  370. }
  371. };
  372. template<typename Ser,typename T>
  373. struct LoadIfStackInstance
  374. {
  375. static bool invoke(Ser &s, T &data)
  376. {
  377. return false;
  378. }
  379. };
  380. template<typename Ser>
  381. struct LoadIfStackInstance<Ser, CStackInstance *>
  382. {
  383. static bool invoke(Ser &s, CStackInstance* &data)
  384. {
  385. CArmedInstance *armedObj;
  386. TSlot slot;
  387. s >> armedObj >> slot;
  388. if(slot != COMMANDER_SLOT_PLACEHOLDER)
  389. {
  390. assert(armedObj->hasStackAtSlot(slot));
  391. data = armedObj->stacks[slot];
  392. }
  393. else
  394. {
  395. auto hero = dynamic_cast<CGHeroInstance *>(armedObj);
  396. assert(hero);
  397. assert(hero->commander);
  398. data = hero->commander;
  399. }
  400. return true;
  401. }
  402. };
  403. /// The class which manages saving objects.
  404. template <typename Serializer> class DLL_LINKAGE COSer : public CSaverBase
  405. {
  406. public:
  407. bool saving;
  408. std::map<ui16,CBasicPointerSaver*> savers; // typeID => CPointerSaver<serializer,type>
  409. std::map<const void*, ui32> savedPointers;
  410. bool smartPointerSerialization;
  411. COSer()
  412. {
  413. saving=true;
  414. smartPointerSerialization = true;
  415. }
  416. ~COSer()
  417. {
  418. std::map<ui16,CBasicPointerSaver*>::iterator iter;
  419. for(iter = savers.begin(); iter != savers.end(); iter++)
  420. delete iter->second;
  421. }
  422. template<typename T> void registerType(const T * t=NULL)
  423. {
  424. ui16 ID = typeList.registerType(t);
  425. savers[ID] = new CPointerSaver<COSer<Serializer>,T>;
  426. }
  427. Serializer * This()
  428. {
  429. return static_cast<Serializer*>(this);
  430. }
  431. template<class T>
  432. Serializer & operator<<(const T &t)
  433. {
  434. this->This()->save(t);
  435. return * this->This();
  436. }
  437. template<class T>
  438. COSer & operator&(const T & t)
  439. {
  440. return * this->This() << t;
  441. }
  442. int write(const void * data, unsigned size);
  443. template <typename T>
  444. void savePrimitive(const T &data)
  445. {
  446. this->This()->write(&data,sizeof(data));
  447. }
  448. template <typename T>
  449. void savePointer(const T &data)
  450. {
  451. //write if pointer is not NULL
  452. ui8 hlp = (data!=NULL);
  453. *this << hlp;
  454. //if pointer is NULL then we don't need anything more...
  455. if(!hlp)
  456. return;
  457. if(smartVectorMembersSerialization)
  458. {
  459. typedef typename boost::remove_const<typename boost::remove_pointer<T>::type>::type TObjectType;
  460. typedef typename VectorisedTypeFor<TObjectType>::type VType;
  461. if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
  462. {
  463. si32 id = getIdFromVectorItem<VType>(*info, data);
  464. *this << id;
  465. if(id != -1) //vector id is enough
  466. return;
  467. }
  468. }
  469. if(sendStackInstanceByIds)
  470. {
  471. const bool gotSaved = SaveIfStackInstance<Serializer,T>::invoke(*This(), data);
  472. if(gotSaved)
  473. return;
  474. }
  475. if(smartPointerSerialization)
  476. {
  477. std::map<const void*,ui32>::iterator i = savedPointers.find(data);
  478. if(i != savedPointers.end())
  479. {
  480. //this pointer has been already serialized - write only it's id
  481. *this << i->second;
  482. return;
  483. }
  484. //give id to this pointer
  485. ui32 pid = (ui32)savedPointers.size();
  486. savedPointers[data] = pid;
  487. *this << pid;
  488. }
  489. //write type identifier
  490. ui16 tid = typeList.getTypeID(data);
  491. *this << tid;
  492. This()->savePointerHlp(tid, data);
  493. }
  494. //that part of ptr serialization was extracted to allow customization of its behavior in derived classes
  495. template <typename T>
  496. void savePointerHlp(ui16 tid, const T &data)
  497. {
  498. if(!tid)
  499. *this << *data; //if type is unregistered simply write all data in a standard way
  500. else
  501. savers[tid]->savePtr(*this,data); //call serializer specific for our real type
  502. }
  503. template <typename T>
  504. void saveArray(const T &data)
  505. {
  506. ui32 size = ARRAY_COUNT(data);
  507. for(ui32 i=0; i < size; i++)
  508. *this << data[i];
  509. }
  510. template <typename T>
  511. void save(const T &data)
  512. {
  513. typedef
  514. //if
  515. typename mpl::eval_if< mpl::equal_to<SerializationLevel<T>,mpl::int_<Primitive> >,
  516. mpl::identity<SavePrimitive<Serializer,T> >,
  517. //else if
  518. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Enum> >,
  519. mpl::identity<SaveEnum<Serializer,T> >,
  520. //else if
  521. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Pointer> >,
  522. mpl::identity<SavePointer<Serializer,T> >,
  523. //else if
  524. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Array> >,
  525. mpl::identity<SaveArray<Serializer,T> >,
  526. //else if
  527. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Serializable> >,
  528. mpl::identity<SaveSerializable<Serializer,T> >,
  529. //else
  530. mpl::identity<SaveWrong<Serializer,T> >
  531. >
  532. >
  533. >
  534. >
  535. >::type typex;
  536. typex::invoke(* this->This(), data);
  537. }
  538. template <typename T>
  539. void saveSerializable(const T &data)
  540. {
  541. const_cast<T&>(data).serialize(*this,version);
  542. }
  543. template <typename T>
  544. void saveSerializable(const shared_ptr<T> &data)
  545. {
  546. T *internalPtr = data.get();
  547. *this << internalPtr;
  548. }
  549. template <typename T>
  550. void saveSerializable(const unique_ptr<T> &data)
  551. {
  552. T *internalPtr = data.get();
  553. *this << internalPtr;
  554. }
  555. template <typename T>
  556. void saveSerializable(const std::vector<T> &data)
  557. {
  558. ui32 length = data.size();
  559. *this << length;
  560. for(ui32 i=0;i<length;i++)
  561. *this << data[i];
  562. }
  563. template <typename T>
  564. void saveSerializable(const std::set<T> &data)
  565. {
  566. std::set<T> &d = const_cast<std::set<T> &>(data);
  567. ui32 length = d.size();
  568. *this << length;
  569. for(typename std::set<T>::iterator i=d.begin();i!=d.end();i++)
  570. *this << *i;
  571. }
  572. template <typename T, typename U>
  573. void saveSerializable(const boost::unordered_set<T, U> &data)
  574. {
  575. boost::unordered_set<T, U> &d = const_cast<boost::unordered_set<T, U> &>(data);
  576. ui32 length = d.size();
  577. *this << length;
  578. for(typename boost::unordered_set<T, U>::iterator i=d.begin();i!=d.end();i++)
  579. *this << *i;
  580. }
  581. template <typename T>
  582. void saveSerializable(const std::list<T> &data)
  583. {
  584. std::list<T> &d = const_cast<std::list<T> &>(data);
  585. ui32 length = d.size();
  586. *this << length;
  587. for(typename std::list<T>::iterator i=d.begin();i!=d.end();i++)
  588. *this << *i;
  589. }
  590. void saveSerializable(const std::string &data)
  591. {
  592. *this << ui32(data.length());
  593. this->This()->write(data.c_str(),data.size());
  594. }
  595. template <typename T1, typename T2>
  596. void saveSerializable(const std::pair<T1,T2> &data)
  597. {
  598. *this << data.first << data.second;
  599. }
  600. template <typename T1, typename T2>
  601. void saveSerializable(const std::map<T1,T2> &data)
  602. {
  603. *this << ui32(data.size());
  604. for(typename std::map<T1,T2>::const_iterator i=data.begin();i!=data.end();i++)
  605. *this << i->first << i->second;
  606. }
  607. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  608. void saveSerializable(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &data)
  609. {
  610. si32 which = data.which();
  611. *this << which;
  612. VariantVisitorSaver<Serializer> visitor(*this->This());
  613. boost::apply_visitor(visitor, data);
  614. }
  615. template <typename E>
  616. void saveEnum(const E &data)
  617. {
  618. si32 writ = static_cast<si32>(data);
  619. *this << writ;
  620. }
  621. };
  622. class DLL_LINKAGE CLoaderBase : public virtual CSerializer
  623. {};
  624. class CBasicPointerLoader
  625. {
  626. public:
  627. virtual void loadPtr(CLoaderBase &ar, void *data, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
  628. virtual ~CBasicPointerLoader(){}
  629. };
  630. template <typename Serializer, typename T> class CPointerLoader : public CBasicPointerLoader
  631. {
  632. public:
  633. void loadPtr(CLoaderBase &ar, void *data, ui32 pid) const //data is pointer to the ACTUAL POINTER
  634. {
  635. Serializer &s = static_cast<Serializer&>(ar);
  636. T *&ptr = *static_cast<T**>(data);
  637. //create new object under pointer
  638. typedef typename boost::remove_pointer<T>::type npT;
  639. ptr = new npT;
  640. s.ptrAllocated(ptr, pid);
  641. //T is most derived known type, it's time to call actual serialize
  642. ptr->serialize(s,version);
  643. }
  644. };
  645. /// The class which manages loading of objects.
  646. template <typename Serializer> class DLL_LINKAGE CISer : public CLoaderBase
  647. {
  648. public:
  649. bool saving;
  650. std::map<ui16,CBasicPointerLoader*> loaders; // typeID => CPointerSaver<serializer,type>
  651. ui32 fileVersion;
  652. bool reverseEndianess; //if source has different endianess than us, we reverse bytes
  653. std::map<ui32, void*> loadedPointers;
  654. bool smartPointerSerialization;
  655. CISer()
  656. {
  657. saving = false;
  658. fileVersion = 0;
  659. smartPointerSerialization = true;
  660. reverseEndianess = false;
  661. }
  662. ~CISer()
  663. {
  664. std::map<ui16,CBasicPointerLoader*>::iterator iter;
  665. for(iter = loaders.begin(); iter != loaders.end(); iter++)
  666. delete iter->second;
  667. }
  668. template<typename T> void registerType(const T * t=NULL)
  669. {
  670. ui16 ID = typeList.registerType(t);
  671. loaders[ID] = new CPointerLoader<CISer<Serializer>,T>;
  672. }
  673. Serializer * This()
  674. {
  675. return static_cast<Serializer*>(this);
  676. }
  677. template<class T>
  678. Serializer & operator>>(T &t)
  679. {
  680. this->This()->load(t);
  681. return * this->This();
  682. }
  683. template<class T>
  684. CISer & operator&(T & t)
  685. {
  686. return * this->This() >> t;
  687. }
  688. int write(const void * data, unsigned size);
  689. template <typename T>
  690. void load(T &data)
  691. {
  692. typedef
  693. //if
  694. typename mpl::eval_if< mpl::equal_to<SerializationLevel<T>,mpl::int_<Primitive> >,
  695. mpl::identity<LoadPrimitive<Serializer,T> >,
  696. //else if
  697. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Enum> >,
  698. mpl::identity<LoadEnum<Serializer,T> >,
  699. //else if
  700. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Pointer> >,
  701. mpl::identity<LoadPointer<Serializer,T> >,
  702. //else if
  703. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Array> >,
  704. mpl::identity<LoadArray<Serializer,T> >,
  705. //else if
  706. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Serializable> >,
  707. mpl::identity<LoadSerializable<Serializer,T> >,
  708. //else
  709. mpl::identity<LoadWrong<Serializer,T> >
  710. >
  711. >
  712. >
  713. >
  714. >::type typex;
  715. typex::invoke(* this->This(), data);
  716. }
  717. template <typename T>
  718. void loadPrimitive(T &data)
  719. {
  720. if(0) //for testing #989
  721. {
  722. this->This()->read(&data,sizeof(data));
  723. }
  724. else
  725. {
  726. unsigned length = sizeof(data);
  727. char* dataPtr = (char*)&data;
  728. this->This()->read(dataPtr,length);
  729. if(reverseEndianess)
  730. std::reverse(dataPtr, dataPtr + length);
  731. }
  732. }
  733. template <typename T>
  734. void loadSerializableBySerializeCall(T &data)
  735. {
  736. ////that const cast is evil because it allows to implicitly overwrite const objects when deserializing
  737. typedef typename boost::remove_const<T>::type nonConstT;
  738. nonConstT &hlp = const_cast<nonConstT&>(data);
  739. hlp.serialize(*this,fileVersion);
  740. //data.serialize(*this,myVersion);
  741. }
  742. template <typename T>
  743. void loadSerializable(T &data)
  744. {
  745. loadSerializableBySerializeCall(data);
  746. }
  747. template <typename T>
  748. void loadArray(T &data)
  749. {
  750. ui32 size = ARRAY_COUNT(data);
  751. for(ui32 i = 0; i < size; i++)
  752. *this >> data[i];
  753. }
  754. template <typename T>
  755. void loadPointer(T &data)
  756. {
  757. ui8 hlp;
  758. *this >> hlp;
  759. if(!hlp)
  760. {
  761. data = NULL;
  762. return;
  763. }
  764. if(smartVectorMembersSerialization)
  765. {
  766. typedef typename boost::remove_const<typename boost::remove_pointer<T>::type>::type TObjectType; //eg: const CGHeroInstance * => CGHeroInstance
  767. typedef typename VectorisedTypeFor<TObjectType>::type VType; //eg: CGHeroInstance -> CGobjectInstance
  768. if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
  769. {
  770. si32 id;
  771. *this >> id;
  772. if(id != -1)
  773. {
  774. data = static_cast<T>(getVectorItemFromId(*info, id));
  775. return;
  776. }
  777. }
  778. }
  779. if(sendStackInstanceByIds)
  780. {
  781. bool gotLoaded = LoadIfStackInstance<Serializer,T>::invoke(*This(), data);
  782. if(gotLoaded)
  783. return;
  784. }
  785. ui32 pid = 0xffffffff; //pointer id (or maybe rather pointee id)
  786. if(smartPointerSerialization)
  787. {
  788. *this >> pid; //get the id
  789. std::map<ui32, void*>::iterator i = loadedPointers.find(pid); //lookup
  790. if(i != loadedPointers.end())
  791. {
  792. //we already got this pointer
  793. data = static_cast<T>(i->second);
  794. return;
  795. }
  796. }
  797. //get type id
  798. ui16 tid;
  799. *this >> tid;
  800. This()->loadPointerHlp(tid, data, pid);
  801. }
  802. //that part of ptr deserialization was extracted to allow customization of its behavior in derived classes
  803. template <typename T>
  804. void loadPointerHlp( ui16 tid, T & data, ui32 pid )
  805. {
  806. if(!tid)
  807. {
  808. typedef typename boost::remove_pointer<T>::type npT;
  809. typedef typename boost::remove_const<npT>::type ncpT;
  810. data = new ncpT;
  811. ptrAllocated(data, pid);
  812. *this >> *data;
  813. }
  814. else
  815. {
  816. loaders[tid]->loadPtr(*this,&data, pid);
  817. }
  818. }
  819. template <typename T>
  820. void ptrAllocated(const T *ptr, ui32 pid)
  821. {
  822. if(smartPointerSerialization && pid != 0xffffffff)
  823. loadedPointers[pid] = (void*)ptr; //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt
  824. }
  825. #define READ_CHECK_U32(x) \
  826. ui32 length; \
  827. *this >> length; \
  828. if(length > 500000) \
  829. { \
  830. tlog2 << "Warning: very big length: " << length << "\n" ;\
  831. reportState(tlog2); \
  832. };
  833. template <typename T>
  834. void loadSerializable(shared_ptr<T> &data)
  835. {
  836. T *internalPtr;
  837. *this >> internalPtr;
  838. data.reset(internalPtr);
  839. }
  840. template <typename T>
  841. void loadSerializable(unique_ptr<T> &data)
  842. {
  843. T *internalPtr;
  844. *this >> internalPtr;
  845. data.reset(internalPtr);
  846. }
  847. template <typename T>
  848. void loadSerializable(std::vector<T> &data)
  849. {
  850. READ_CHECK_U32(length);
  851. data.resize(length);
  852. for(ui32 i=0;i<length;i++)
  853. *this >> data[i];
  854. }
  855. template <typename T>
  856. void loadSerializable(std::set<T> &data)
  857. {
  858. READ_CHECK_U32(length);
  859. T ins;
  860. for(ui32 i=0;i<length;i++)
  861. {
  862. *this >> ins;
  863. data.insert(ins);
  864. }
  865. }
  866. template <typename T, typename U>
  867. void loadSerializable(boost::unordered_set<T, U> &data)
  868. {
  869. READ_CHECK_U32(length);
  870. T ins;
  871. for(ui32 i=0;i<length;i++)
  872. {
  873. *this >> ins;
  874. data.insert(ins);
  875. }
  876. }
  877. template <typename T>
  878. void loadSerializable(std::list<T> &data)
  879. {
  880. READ_CHECK_U32(length);
  881. T ins;
  882. for(ui32 i=0;i<length;i++)
  883. {
  884. *this >> ins;
  885. data.push_back(ins);
  886. }
  887. }
  888. template <typename T1, typename T2>
  889. void loadSerializable(std::pair<T1,T2> &data)
  890. {
  891. *this >> data.first >> data.second;
  892. }
  893. template <typename T1, typename T2>
  894. void loadSerializable(std::map<T1,T2> &data)
  895. {
  896. READ_CHECK_U32(length);
  897. T1 t;
  898. for(ui32 i=0;i<length;i++)
  899. {
  900. *this >> t;
  901. *this >> data[t];
  902. }
  903. }
  904. void loadSerializable(std::string &data)
  905. {
  906. READ_CHECK_U32(length);
  907. data.resize(length);
  908. this->This()->read((void*)data.c_str(),length);
  909. }
  910. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  911. void loadSerializable(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &data)
  912. {
  913. si32 which;
  914. *this >> which;
  915. if(which == 0)
  916. {
  917. T0 obj;
  918. *this >> obj;
  919. data = obj;
  920. }
  921. else if(which == 1)
  922. {
  923. T1 obj;
  924. *this >> obj;
  925. data = obj;
  926. }
  927. else
  928. assert(0);
  929. //TODO write more if needed, general solution would be much longer
  930. }
  931. void loadSerializable(CStackInstance *&s)
  932. {
  933. if(sendStackInstanceByIds)
  934. {
  935. CArmedInstance *armed;
  936. TSlot slot;
  937. *this >> armed >> slot;
  938. assert(armed->hasStackAtSlot(slot));
  939. s = armed->stacks[slot];
  940. }
  941. else
  942. loadSerializableBySerializeCall(s);
  943. }
  944. template <typename E>
  945. void loadEnum(E &data)
  946. {
  947. si32 read;
  948. *this >> read;
  949. data = static_cast<E>(read);
  950. }
  951. };
  952. class DLL_LINKAGE CSaveFile
  953. : public COSer<CSaveFile>
  954. {
  955. void dummyMagicFunction()
  956. {
  957. *this << std::string("This function makes stuff working.");
  958. }
  959. public:
  960. std::string fName;
  961. unique_ptr<std::ofstream> sfile;
  962. CSaveFile(const std::string &fname); //throws!
  963. ~CSaveFile();
  964. int write(const void * data, unsigned size);
  965. void openNextFile(const std::string &fname); //throws!
  966. void clear();
  967. void reportState(CLogger &out);
  968. };
  969. class DLL_LINKAGE CLoadFile
  970. : public CISer<CLoadFile>
  971. {
  972. void dummyMagicFunction()
  973. {
  974. std::string dummy = "This function makes stuff working.";
  975. *this >> dummy;
  976. }
  977. public:
  978. std::string fName;
  979. unique_ptr<std::ifstream> sfile;
  980. CLoadFile(const std::string &fname, int minimalVersion = version); //throws!
  981. ~CLoadFile();
  982. int read(const void * data, unsigned size); //throws!
  983. void openNextFile(const std::string &fname, int minimalVersion); //throws!
  984. void clear();
  985. void reportState(CLogger &out);
  986. };
  987. typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > TSocket;
  988. typedef boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > TAcceptor;
  989. class DLL_LINKAGE CConnection
  990. :public CISer<CConnection>, public COSer<CConnection>
  991. {
  992. //CGameState *gs;
  993. CConnection(void);
  994. void init();
  995. void reportState(CLogger &out);
  996. public:
  997. boost::mutex *rmx, *wmx; // read/write mutexes
  998. TSocket * socket;
  999. bool logging;
  1000. bool connected;
  1001. bool myEndianess, contactEndianess; //true if little endian, if endianess is different we'll have to revert received multi-byte vars
  1002. boost::asio::io_service *io_service;
  1003. std::string name; //who uses this connection
  1004. int connectionID;
  1005. boost::thread *handler;
  1006. bool receivedStop, sendStop;
  1007. CConnection(std::string host, std::string port, std::string Name);
  1008. CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, std::string Name);
  1009. CConnection(TSocket * Socket, std::string Name); //use immediately after accepting connection into socket
  1010. int write(const void * data, unsigned size);
  1011. int read(void * data, unsigned size);
  1012. void close();
  1013. bool isOpen() const;
  1014. template<class T>
  1015. CConnection &operator&(const T&);
  1016. virtual ~CConnection(void);
  1017. CPack *retreivePack(); //gets from server next pack (allocates it with new)
  1018. void sendPackToServer(const CPack &pack, ui8 player, ui32 requestID);
  1019. void disableStackSendingByID();
  1020. void enableStackSendingByID();
  1021. void disableSmartPointerSerialization();
  1022. void enableSmartPointerSerializatoin();
  1023. };
  1024. DLL_LINKAGE std::ostream &operator<<(std::ostream &str, const CConnection &cpc);
  1025. template<typename T>
  1026. class CApplier
  1027. {
  1028. public:
  1029. std::map<ui16,T*> apps;
  1030. ~CApplier()
  1031. {
  1032. typename std::map<ui16, T*>::iterator iter;
  1033. for(iter = apps.begin(); iter != apps.end(); iter++)
  1034. delete iter->second;
  1035. }
  1036. template<typename U> void registerType(const U * t=NULL)
  1037. {
  1038. ui16 ID = typeList.registerType(t);
  1039. apps[ID] = T::getApplier(t);
  1040. }
  1041. };