demo.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  2. // demo.cpp
  3. //
  4. // (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com .
  5. // Use, modification and distribution is subject to the Boost Software
  6. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. #include <cstddef> // NULL
  9. #include <iomanip>
  10. #include <iostream>
  11. #include <fstream>
  12. #include <string>
  13. #include <boost/archive/tmpdir.hpp>
  14. #include <boost/archive/text_iarchive.hpp>
  15. #include <boost/archive/text_oarchive.hpp>
  16. #include <boost/serialization/base_object.hpp>
  17. #include <boost/serialization/utility.hpp>
  18. #include <boost/serialization/list.hpp>
  19. #include <boost/serialization/assume_abstract.hpp>
  20. /////////////////////////////////////////////////////////////
  21. // The intent of this program is to serve as a tutorial for
  22. // users of the serialization package. An attempt has been made
  23. // to illustrate most of the facilities of the package.
  24. //
  25. // The intent is to create an example suffciently complete to
  26. // illustrate the usage and utility of the package while
  27. // including a minimum of other code.
  28. //
  29. // This illustration models the bus system of a small city.
  30. // This includes, multiple bus stops, bus routes and schedules.
  31. // There are different kinds of stops. Bus stops in general will
  32. // will appear on multiple routes. A schedule will include
  33. // muliple trips on the same route.
  34. /////////////////////////////////////////////////////////////
  35. // gps coordinate
  36. //
  37. // llustrates serialization for a simple type
  38. //
  39. class gps_position
  40. {
  41. friend std::ostream & operator<<(std::ostream &os, const gps_position &gp);
  42. friend class boost::serialization::access;
  43. int degrees;
  44. int minutes;
  45. float seconds;
  46. template<class Archive>
  47. void serialize(Archive & ar, const unsigned int /* file_version */){
  48. ar & degrees & minutes & seconds;
  49. }
  50. public:
  51. // every serializable class needs a constructor
  52. gps_position(){};
  53. gps_position(int _d, int _m, float _s) :
  54. degrees(_d), minutes(_m), seconds(_s)
  55. {}
  56. };
  57. std::ostream & operator<<(std::ostream &os, const gps_position &gp)
  58. {
  59. return os << ' ' << gp.degrees << (unsigned char)186 << gp.minutes << '\'' << gp.seconds << '"';
  60. }
  61. /////////////////////////////////////////////////////////////
  62. // One bus stop
  63. //
  64. // illustrates serialization of serializable members
  65. //
  66. class bus_stop
  67. {
  68. friend class boost::serialization::access;
  69. friend std::ostream & operator<<(std::ostream &os, const bus_stop &gp);
  70. virtual std::string description() const = 0;
  71. gps_position latitude;
  72. gps_position longitude;
  73. template<class Archive>
  74. void serialize(Archive &ar, const unsigned int version)
  75. {
  76. ar & latitude;
  77. ar & longitude;
  78. }
  79. protected:
  80. bus_stop(const gps_position & _lat, const gps_position & _long) :
  81. latitude(_lat), longitude(_long)
  82. {}
  83. public:
  84. bus_stop(){}
  85. virtual ~bus_stop(){}
  86. };
  87. BOOST_SERIALIZATION_ASSUME_ABSTRACT(bus_stop)
  88. std::ostream & operator<<(std::ostream &os, const bus_stop &bs)
  89. {
  90. return os << bs.latitude << bs.longitude << ' ' << bs.description();
  91. }
  92. /////////////////////////////////////////////////////////////
  93. // Several kinds of bus stops
  94. //
  95. // illustrates serialization of derived types
  96. //
  97. class bus_stop_corner : public bus_stop
  98. {
  99. friend class boost::serialization::access;
  100. std::string street1;
  101. std::string street2;
  102. virtual std::string description() const
  103. {
  104. return street1 + " and " + street2;
  105. }
  106. template<class Archive>
  107. void serialize(Archive &ar, const unsigned int version)
  108. {
  109. // save/load base class information
  110. ar & boost::serialization::base_object<bus_stop>(*this);
  111. ar & street1 & street2;
  112. }
  113. public:
  114. bus_stop_corner(){}
  115. bus_stop_corner(const gps_position & _lat, const gps_position & _long,
  116. const std::string & _s1, const std::string & _s2
  117. ) :
  118. bus_stop(_lat, _long), street1(_s1), street2(_s2)
  119. {
  120. }
  121. };
  122. class bus_stop_destination : public bus_stop
  123. {
  124. friend class boost::serialization::access;
  125. std::string name;
  126. virtual std::string description() const
  127. {
  128. return name;
  129. }
  130. template<class Archive>
  131. void serialize(Archive &ar, const unsigned int version)
  132. {
  133. ar & boost::serialization::base_object<bus_stop>(*this) & name;
  134. }
  135. public:
  136. bus_stop_destination(){}
  137. bus_stop_destination(
  138. const gps_position & _lat, const gps_position & _long, const std::string & _name
  139. ) :
  140. bus_stop(_lat, _long), name(_name)
  141. {
  142. }
  143. };
  144. /////////////////////////////////////////////////////////////
  145. // a bus route is a collection of bus stops
  146. //
  147. // illustrates serialization of STL collection templates.
  148. //
  149. // illustrates serialzation of polymorphic pointer (bus stop *);
  150. //
  151. // illustrates storage and recovery of shared pointers is correct
  152. // and efficient. That is objects pointed to by more than one
  153. // pointer are stored only once. In such cases only one such
  154. // object is restored and pointers are restored to point to it
  155. //
  156. class bus_route
  157. {
  158. friend class boost::serialization::access;
  159. friend std::ostream & operator<<(std::ostream &os, const bus_route &br);
  160. typedef bus_stop * bus_stop_pointer;
  161. std::list<bus_stop_pointer> stops;
  162. template<class Archive>
  163. void serialize(Archive &ar, const unsigned int version)
  164. {
  165. // in this program, these classes are never serialized directly but rather
  166. // through a pointer to the base class bus_stop. So we need a way to be
  167. // sure that the archive contains information about these derived classes.
  168. //ar.template register_type<bus_stop_corner>();
  169. ar.register_type(static_cast<bus_stop_corner *>(NULL));
  170. //ar.template register_type<bus_stop_destination>();
  171. ar.register_type(static_cast<bus_stop_destination *>(NULL));
  172. // serialization of stl collections is already defined
  173. // in the header
  174. ar & stops;
  175. }
  176. public:
  177. bus_route(){}
  178. void append(bus_stop *_bs)
  179. {
  180. stops.insert(stops.end(), _bs);
  181. }
  182. };
  183. std::ostream & operator<<(std::ostream &os, const bus_route &br)
  184. {
  185. std::list<bus_stop *>::const_iterator it;
  186. // note: we're displaying the pointer to permit verification
  187. // that duplicated pointers are properly restored.
  188. for(it = br.stops.begin(); it != br.stops.end(); it++){
  189. os << '\n' << std::hex << "0x" << *it << std::dec << ' ' << **it;
  190. }
  191. return os;
  192. }
  193. /////////////////////////////////////////////////////////////
  194. // a bus schedule is a collection of routes each with a starting time
  195. //
  196. // Illustrates serialization of STL objects(pair) in a non-intrusive way.
  197. // See definition of operator<< <pair<F, S> >(ar, pair) and others in
  198. // serialization.hpp
  199. //
  200. // illustrates nesting of serializable classes
  201. //
  202. // illustrates use of version number to automatically grandfather older
  203. // versions of the same class.
  204. class bus_schedule
  205. {
  206. public:
  207. // note: this structure was made public. because the friend declarations
  208. // didn't seem to work as expected.
  209. struct trip_info
  210. {
  211. template<class Archive>
  212. void serialize(Archive &ar, const unsigned int file_version)
  213. {
  214. // in versions 2 or later
  215. if(file_version >= 2)
  216. // read the drivers name
  217. ar & driver;
  218. // all versions have the follwing info
  219. ar & hour & minute;
  220. }
  221. // starting time
  222. int hour;
  223. int minute;
  224. // only after system shipped was the driver's name added to the class
  225. std::string driver;
  226. trip_info(){}
  227. trip_info(int _h, int _m, const std::string &_d) :
  228. hour(_h), minute(_m), driver(_d)
  229. {}
  230. };
  231. private:
  232. friend class boost::serialization::access;
  233. friend std::ostream & operator<<(std::ostream &os, const bus_schedule &bs);
  234. friend std::ostream & operator<<(std::ostream &os, const bus_schedule::trip_info &ti);
  235. std::list<std::pair<trip_info, bus_route *> > schedule;
  236. template<class Archive>
  237. void serialize(Archive &ar, const unsigned int version)
  238. {
  239. ar & schedule;
  240. }
  241. public:
  242. void append(const std::string &_d, int _h, int _m, bus_route *_br)
  243. {
  244. schedule.insert(schedule.end(), std::make_pair(trip_info(_h, _m, _d), _br));
  245. }
  246. bus_schedule(){}
  247. };
  248. BOOST_CLASS_VERSION(bus_schedule::trip_info, 2)
  249. std::ostream & operator<<(std::ostream &os, const bus_schedule::trip_info &ti)
  250. {
  251. return os << '\n' << ti.hour << ':' << ti.minute << ' ' << ti.driver << ' ';
  252. }
  253. std::ostream & operator<<(std::ostream &os, const bus_schedule &bs)
  254. {
  255. std::list<std::pair<bus_schedule::trip_info, bus_route *> >::const_iterator it;
  256. for(it = bs.schedule.begin(); it != bs.schedule.end(); it++){
  257. os << it->first << *(it->second);
  258. }
  259. return os;
  260. }
  261. void save_schedule(const bus_schedule &s, const char * filename){
  262. // make an archive
  263. std::ofstream ofs(filename);
  264. boost::archive::text_oarchive oa(ofs);
  265. oa << s;
  266. }
  267. void
  268. restore_schedule(bus_schedule &s, const char * filename)
  269. {
  270. // open the archive
  271. std::ifstream ifs(filename);
  272. boost::archive::text_iarchive ia(ifs);
  273. // restore the schedule from the archive
  274. ia >> s;
  275. }
  276. int main(int argc, char *argv[])
  277. {
  278. // make the schedule
  279. bus_schedule original_schedule;
  280. // fill in the data
  281. // make a few stops
  282. bus_stop *bs0 = new bus_stop_corner(
  283. gps_position(34, 135, 52.560f),
  284. gps_position(134, 22, 78.30f),
  285. "24th Street", "10th Avenue"
  286. );
  287. bus_stop *bs1 = new bus_stop_corner(
  288. gps_position(35, 137, 23.456f),
  289. gps_position(133, 35, 54.12f),
  290. "State street", "Cathedral Vista Lane"
  291. );
  292. bus_stop *bs2 = new bus_stop_destination(
  293. gps_position(35, 136, 15.456f),
  294. gps_position(133, 32, 15.300f),
  295. "White House"
  296. );
  297. bus_stop *bs3 = new bus_stop_destination(
  298. gps_position(35, 134, 48.789f),
  299. gps_position(133, 32, 16.230f),
  300. "Lincoln Memorial"
  301. );
  302. // make a routes
  303. bus_route route0;
  304. route0.append(bs0);
  305. route0.append(bs1);
  306. route0.append(bs2);
  307. // add trips to schedule
  308. original_schedule.append("bob", 6, 24, &route0);
  309. original_schedule.append("bob", 9, 57, &route0);
  310. original_schedule.append("alice", 11, 02, &route0);
  311. // make aother routes
  312. bus_route route1;
  313. route1.append(bs3);
  314. route1.append(bs2);
  315. route1.append(bs1);
  316. // add trips to schedule
  317. original_schedule.append("ted", 7, 17, &route1);
  318. original_schedule.append("ted", 9, 38, &route1);
  319. original_schedule.append("alice", 11, 47, &route1);
  320. // display the complete schedule
  321. std::cout << "original schedule";
  322. std::cout << original_schedule;
  323. std::string filename(boost::archive::tmpdir());
  324. filename += "/demofile.txt";
  325. // save the schedule
  326. save_schedule(original_schedule, filename.c_str());
  327. // ... some time later
  328. // make a new schedule
  329. bus_schedule new_schedule;
  330. restore_schedule(new_schedule, filename.c_str());
  331. // and display
  332. std::cout << "\nrestored schedule";
  333. std::cout << new_schedule;
  334. // should be the same as the old one. (except for the pointer values)
  335. delete bs0;
  336. delete bs1;
  337. delete bs2;
  338. delete bs3;
  339. return 0;
  340. }