| 1 | #ifndef BOOST_SERIALIZATION_EXAMPLE_DEMO_XML_HPP | 
|---|
| 2 | #define BOOST_SERIALIZATION_EXAMPLE_DEMO_XML_HPP | 
|---|
| 3 |  | 
|---|
| 4 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 | 
|---|
| 5 | // | 
|---|
| 6 | // demo_xml.hpp | 
|---|
| 7 | // | 
|---|
| 8 | // (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com . | 
|---|
| 9 | // Use, modification and distribution is subject to the Boost Software | 
|---|
| 10 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | 
|---|
| 11 | // http://www.boost.org/LICENSE_1_0.txt) | 
|---|
| 12 |  | 
|---|
| 13 |  | 
|---|
| 14 | #include <string> | 
|---|
| 15 | #include <iomanip> | 
|---|
| 16 | #include <iostream> | 
|---|
| 17 | #include <fstream> | 
|---|
| 18 |  | 
|---|
| 19 | #include <boost/serialization/nvp.hpp> | 
|---|
| 20 | #include <boost/serialization/utility.hpp> | 
|---|
| 21 | #include <boost/serialization/list.hpp> | 
|---|
| 22 | #include <boost/serialization/version.hpp> | 
|---|
| 23 |  | 
|---|
| 24 | // This illustration models the bus system of a small city. | 
|---|
| 25 | // This includes, multiple bus stops,  bus routes and schedules. | 
|---|
| 26 | // There are different kinds of stops.  Bus stops in general will | 
|---|
| 27 | // will appear on multiple routes.  A schedule will include | 
|---|
| 28 | // muliple trips on the same route. | 
|---|
| 29 |  | 
|---|
| 30 | ///////////////////////////////////////////////////////////// | 
|---|
| 31 | // gps coordinate | 
|---|
| 32 | // | 
|---|
| 33 | // llustrates serialization for a simple type | 
|---|
| 34 | // | 
|---|
| 35 | class gps_position | 
|---|
| 36 | { | 
|---|
| 37 |     friend class boost::serialization::access; | 
|---|
| 38 |     friend std::ostream & operator<<(std::ostream &os, const gps_position &gp); | 
|---|
| 39 |  | 
|---|
| 40 |     int degrees; | 
|---|
| 41 |     int minutes; | 
|---|
| 42 |     float seconds; | 
|---|
| 43 |  | 
|---|
| 44 |     template<class Archive> | 
|---|
| 45 |     void serialize(Archive & ar, const unsigned int /* file_version */){ | 
|---|
| 46 |         ar  & BOOST_SERIALIZATION_NVP(degrees) | 
|---|
| 47 |             & BOOST_SERIALIZATION_NVP(minutes) | 
|---|
| 48 |             & BOOST_SERIALIZATION_NVP(seconds); | 
|---|
| 49 |     } | 
|---|
| 50 |  | 
|---|
| 51 | public: | 
|---|
| 52 |     // every serializable class needs a constructor | 
|---|
| 53 |     gps_position(){}; | 
|---|
| 54 |     gps_position(int _d, int _m, float _s) :  | 
|---|
| 55 |         degrees(_d), minutes(_m), seconds(_s) | 
|---|
| 56 |     {} | 
|---|
| 57 | }; | 
|---|
| 58 |  | 
|---|
| 59 | std::ostream & operator<<(std::ostream &os, const gps_position &gp) | 
|---|
| 60 | { | 
|---|
| 61 |     return os << ' ' << gp.degrees << (unsigned char)186 << gp.minutes << '\'' << gp.seconds << '"'; | 
|---|
| 62 | } | 
|---|
| 63 |  | 
|---|
| 64 | ///////////////////////////////////////////////////////////// | 
|---|
| 65 | // One bus stop | 
|---|
| 66 | // | 
|---|
| 67 | // illustrates serialization of serializable members | 
|---|
| 68 | // | 
|---|
| 69 |  | 
|---|
| 70 | class bus_stop | 
|---|
| 71 | { | 
|---|
| 72 |     friend class boost::serialization::access; | 
|---|
| 73 |     virtual std::string description() const = 0; | 
|---|
| 74 |     gps_position latitude; | 
|---|
| 75 |     gps_position longitude; | 
|---|
| 76 |  | 
|---|
| 77 |     template<class Archive> | 
|---|
| 78 |     void serialize(Archive &ar, const unsigned int version) | 
|---|
| 79 |     { | 
|---|
| 80 |         ar & BOOST_SERIALIZATION_NVP(latitude); | 
|---|
| 81 |         ar & BOOST_SERIALIZATION_NVP(longitude); | 
|---|
| 82 |     } | 
|---|
| 83 |  | 
|---|
| 84 | protected: | 
|---|
| 85 |     bus_stop(const gps_position & _lat, const gps_position & _long) : | 
|---|
| 86 |         latitude(_lat), longitude(_long) | 
|---|
| 87 |     {} | 
|---|
| 88 | public: | 
|---|
| 89 |     bus_stop(){} | 
|---|
| 90 |     friend std::ostream & operator<<(std::ostream &os, const bus_stop &gp); | 
|---|
| 91 |     virtual ~bus_stop(){} | 
|---|
| 92 | }; | 
|---|
| 93 |  | 
|---|
| 94 | BOOST_IS_ABSTRACT(bus_stop) | 
|---|
| 95 |  | 
|---|
| 96 | std::ostream & operator<<(std::ostream &os, const bus_stop &bs) | 
|---|
| 97 | { | 
|---|
| 98 |     return os << bs.latitude << bs.longitude << ' ' << bs.description(); | 
|---|
| 99 | } | 
|---|
| 100 |  | 
|---|
| 101 | ///////////////////////////////////////////////////////////// | 
|---|
| 102 | // Several kinds of bus stops | 
|---|
| 103 | // | 
|---|
| 104 | // illustrates serialization of derived types | 
|---|
| 105 | // | 
|---|
| 106 | class bus_stop_corner : public bus_stop | 
|---|
| 107 | { | 
|---|
| 108 |     friend class boost::serialization::access; | 
|---|
| 109 |     std::string street1; | 
|---|
| 110 |     std::string street2; | 
|---|
| 111 |     virtual std::string description() const | 
|---|
| 112 |     { | 
|---|
| 113 |         return street1 + " and " + street2; | 
|---|
| 114 |     } | 
|---|
| 115 |     template<class Archive> | 
|---|
| 116 |     void serialize(Archive &ar, const unsigned int version) | 
|---|
| 117 |     { | 
|---|
| 118 |         // save/load base class information | 
|---|
| 119 |         ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(bus_stop); | 
|---|
| 120 |         ar & BOOST_SERIALIZATION_NVP(street1); | 
|---|
| 121 |         ar & BOOST_SERIALIZATION_NVP(street2); | 
|---|
| 122 |     } | 
|---|
| 123 | public: | 
|---|
| 124 |     bus_stop_corner(){} | 
|---|
| 125 |     bus_stop_corner(const gps_position & _lat, const gps_position & _long, | 
|---|
| 126 |         const std::string & _s1, const std::string & _s2 | 
|---|
| 127 |     ) : | 
|---|
| 128 |         bus_stop(_lat, _long), street1(_s1), street2(_s2) | 
|---|
| 129 |     { | 
|---|
| 130 |     } | 
|---|
| 131 | }; | 
|---|
| 132 |  | 
|---|
| 133 | class bus_stop_destination : public bus_stop | 
|---|
| 134 | { | 
|---|
| 135 |     friend class boost::serialization::access; | 
|---|
| 136 |     std::string name; | 
|---|
| 137 |     virtual std::string description() const | 
|---|
| 138 |     { | 
|---|
| 139 |         return name; | 
|---|
| 140 |     } | 
|---|
| 141 |     template<class Archive> | 
|---|
| 142 |     void serialize(Archive &ar, const unsigned int version) | 
|---|
| 143 |     { | 
|---|
| 144 |         ar  & BOOST_SERIALIZATION_BASE_OBJECT_NVP(bus_stop) | 
|---|
| 145 |             & BOOST_SERIALIZATION_NVP(name); | 
|---|
| 146 |     } | 
|---|
| 147 | public: | 
|---|
| 148 |     bus_stop_destination(){} | 
|---|
| 149 |     bus_stop_destination( | 
|---|
| 150 |         const gps_position & _lat, const gps_position & _long, const std::string & _name | 
|---|
| 151 |     ) : | 
|---|
| 152 |         bus_stop(_lat, _long), name(_name) | 
|---|
| 153 |     { | 
|---|
| 154 |     } | 
|---|
| 155 | }; | 
|---|
| 156 |  | 
|---|
| 157 | ///////////////////////////////////////////////////////////// | 
|---|
| 158 | // a bus route is a collection of bus stops | 
|---|
| 159 | // | 
|---|
| 160 | // illustrates serialization of STL collection templates. | 
|---|
| 161 | // | 
|---|
| 162 | // illustrates serialzation of polymorphic pointer (bus stop *); | 
|---|
| 163 | // | 
|---|
| 164 | // illustrates storage and recovery of shared pointers is correct | 
|---|
| 165 | // and efficient.  That is objects pointed to by more than one | 
|---|
| 166 | // pointer are stored only once.  In such cases only one such | 
|---|
| 167 | // object is restored and pointers are restored to point to it | 
|---|
| 168 | // | 
|---|
| 169 | class bus_route | 
|---|
| 170 | { | 
|---|
| 171 |     friend class boost::serialization::access; | 
|---|
| 172 |     friend std::ostream & operator<<(std::ostream &os, const bus_route &br); | 
|---|
| 173 |     typedef bus_stop * bus_stop_pointer; | 
|---|
| 174 |     std::list<bus_stop_pointer> stops; | 
|---|
| 175 |     template<class Archive> | 
|---|
| 176 |     void serialize(Archive &ar, const unsigned int version) | 
|---|
| 177 |     { | 
|---|
| 178 |         // in this program, these classes are never serialized directly but rather | 
|---|
| 179 |         // through a pointer to the base class bus_stop. So we need a way to be | 
|---|
| 180 |         // sure that the archive contains information about these derived classes. | 
|---|
| 181 |         //ar.template register_type<bus_stop_corner>(); | 
|---|
| 182 |         ar.register_type(static_cast<bus_stop_corner *>(NULL)); | 
|---|
| 183 |         //ar.template register_type<bus_stop_destination>(); | 
|---|
| 184 |         ar.register_type(static_cast<bus_stop_destination *>(NULL)); | 
|---|
| 185 |         // serialization of stl collections is already defined | 
|---|
| 186 |         // in the header | 
|---|
| 187 |         ar & BOOST_SERIALIZATION_NVP(stops); | 
|---|
| 188 |     } | 
|---|
| 189 | public: | 
|---|
| 190 |     bus_route(){} | 
|---|
| 191 |     void append(bus_stop *_bs) | 
|---|
| 192 |     { | 
|---|
| 193 |         stops.insert(stops.end(), _bs); | 
|---|
| 194 |     } | 
|---|
| 195 | }; | 
|---|
| 196 | std::ostream & operator<<(std::ostream &os, const bus_route &br) | 
|---|
| 197 | { | 
|---|
| 198 |     std::list<bus_stop *>::const_iterator it; | 
|---|
| 199 |     // note: we're displaying the pointer to permit verification | 
|---|
| 200 |     // that duplicated pointers are properly restored. | 
|---|
| 201 |     for(it = br.stops.begin(); it != br.stops.end(); it++){ | 
|---|
| 202 |         os << '\n' << std::hex << "0x" << *it << std::dec << ' ' << **it; | 
|---|
| 203 |     } | 
|---|
| 204 |     return os; | 
|---|
| 205 | } | 
|---|
| 206 |  | 
|---|
| 207 | ///////////////////////////////////////////////////////////// | 
|---|
| 208 | // a bus schedule is a collection of routes each with a starting time | 
|---|
| 209 | // | 
|---|
| 210 | // Illustrates serialization of STL objects(pair) in a non-intrusive way. | 
|---|
| 211 | // See definition of operator<< <pair<F, S> >(ar, pair) | 
|---|
| 212 | //  | 
|---|
| 213 | // illustrates nesting of serializable classes | 
|---|
| 214 | // | 
|---|
| 215 | // illustrates use of version number to automatically grandfather older | 
|---|
| 216 | // versions of the same class. | 
|---|
| 217 |  | 
|---|
| 218 | class bus_schedule | 
|---|
| 219 | { | 
|---|
| 220 |     friend class boost::serialization::access; | 
|---|
| 221 |     friend std::ostream & operator<<(std::ostream &os, const bus_schedule &bs); | 
|---|
| 222 |     template<class Archive> | 
|---|
| 223 |     void serialize(Archive &ar, const unsigned int version) | 
|---|
| 224 |     { | 
|---|
| 225 |         ar & BOOST_SERIALIZATION_NVP(schedule); | 
|---|
| 226 |     } | 
|---|
| 227 |     // note: this structure was made public. because the friend declarations | 
|---|
| 228 |     // didn't seem to work as expected. | 
|---|
| 229 | public: | 
|---|
| 230 |     struct trip_info | 
|---|
| 231 |     { | 
|---|
| 232 |         template<class Archive> | 
|---|
| 233 |         void serialize(Archive &ar, const unsigned int file_version) | 
|---|
| 234 |         { | 
|---|
| 235 |             // in versions 2 or later | 
|---|
| 236 |             if(file_version >= 2) | 
|---|
| 237 |                 // read the drivers name | 
|---|
| 238 |                 ar & BOOST_SERIALIZATION_NVP(driver); | 
|---|
| 239 |             // all versions have the follwing info | 
|---|
| 240 |             ar  & BOOST_SERIALIZATION_NVP(hour) | 
|---|
| 241 |                 & BOOST_SERIALIZATION_NVP(minute); | 
|---|
| 242 |         } | 
|---|
| 243 |  | 
|---|
| 244 |         // starting time | 
|---|
| 245 |         int hour; | 
|---|
| 246 |         int minute; | 
|---|
| 247 |         // only after system shipped was the driver's name added to the class | 
|---|
| 248 |         std::string driver; | 
|---|
| 249 |  | 
|---|
| 250 |         trip_info(){} | 
|---|
| 251 |         trip_info(int _h, int _m, const std::string &_d) : | 
|---|
| 252 |             hour(_h), minute(_m), driver(_d) | 
|---|
| 253 |         {} | 
|---|
| 254 |         ~trip_info(){ | 
|---|
| 255 |         } | 
|---|
| 256 |     }; | 
|---|
| 257 | //  friend std::ostream & operator<<(std::ostream &os, const trip_info &ti); | 
|---|
| 258 | private: | 
|---|
| 259 |     std::list<std::pair<trip_info, bus_route *> > schedule; | 
|---|
| 260 | public: | 
|---|
| 261 |     void append(const std::string &_d, int _h, int _m, bus_route *_br) | 
|---|
| 262 |     { | 
|---|
| 263 |         schedule.insert(schedule.end(), std::make_pair(trip_info(_h, _m, _d), _br)); | 
|---|
| 264 |     } | 
|---|
| 265 |     bus_schedule(){} | 
|---|
| 266 | }; | 
|---|
| 267 |  | 
|---|
| 268 | BOOST_CLASS_VERSION(bus_schedule::trip_info, 3) | 
|---|
| 269 | BOOST_CLASS_VERSION(bus_schedule, 2) | 
|---|
| 270 |  | 
|---|
| 271 | std::ostream & operator<<(std::ostream &os, const bus_schedule::trip_info &ti) | 
|---|
| 272 | { | 
|---|
| 273 |     return os << '\n' << ti.hour << ':' << ti.minute << ' ' << ti.driver << ' '; | 
|---|
| 274 | } | 
|---|
| 275 | std::ostream & operator<<(std::ostream &os, const bus_schedule &bs) | 
|---|
| 276 | { | 
|---|
| 277 |     std::list<std::pair<bus_schedule::trip_info, bus_route *> >::const_iterator it; | 
|---|
| 278 |     for(it = bs.schedule.begin(); it != bs.schedule.end(); it++){ | 
|---|
| 279 |         os << it->first << *(it->second); | 
|---|
| 280 |     } | 
|---|
| 281 |     return os; | 
|---|
| 282 | } | 
|---|
| 283 |  | 
|---|
| 284 | #endif // BOOST_SERIALIZATION_EXAMPLE_DEMO_XML_HPP | 
|---|