1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
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)
10 #include <cstddef> // NULL
16 #include <boost/archive/tmpdir.hpp>
18 #include <boost/archive/text_iarchive.hpp>
19 #include <boost/archive/text_oarchive.hpp>
21 #include <boost/serialization/base_object.hpp>
22 #include <boost/serialization/utility.hpp>
23 #include <boost/serialization/list.hpp>
24 #include <boost/serialization/assume_abstract.hpp>
26 /////////////////////////////////////////////////////////////
27 // The intent of this program is to serve as a tutorial for
28 // users of the serialization package. An attempt has been made
29 // to illustrate most of the facilities of the package.
31 // The intent is to create an example suffciently complete to
32 // illustrate the usage and utility of the package while
33 // including a minimum of other code.
35 // This illustration models the bus system of a small city.
36 // This includes, multiple bus stops, bus routes and schedules.
37 // There are different kinds of stops. Bus stops in general will
38 // will appear on multiple routes. A schedule will include
39 // muliple trips on the same route.
41 /////////////////////////////////////////////////////////////
44 // llustrates serialization for a simple type
48 friend std::ostream
& operator<<(std::ostream
&os
, const gps_position
&gp
);
49 friend class boost::serialization::access
;
53 template<class Archive
>
54 void serialize(Archive
& ar
, const unsigned int /* file_version */){
55 ar
& degrees
& minutes
& seconds
;
58 // every serializable class needs a constructor
60 gps_position(int _d
, int _m
, float _s
) :
61 degrees(_d
), minutes(_m
), seconds(_s
)
64 std::ostream
& operator<<(std::ostream
&os
, const gps_position
&gp
)
66 return os
<< ' ' << gp
.degrees
<< (unsigned char)186 << gp
.minutes
<< '\'' << gp
.seconds
<< '"';
69 /////////////////////////////////////////////////////////////
72 // illustrates serialization of serializable members
77 friend class boost::serialization::access
;
78 friend std::ostream
& operator<<(std::ostream
&os
, const bus_stop
&gp
);
79 virtual std::string
description() const = 0;
80 gps_position latitude
;
81 gps_position longitude
;
82 template<class Archive
>
83 void serialize(Archive
&ar
, const unsigned int version
)
89 bus_stop(const gps_position
& _lat
, const gps_position
& _long
) :
90 latitude(_lat
), longitude(_long
)
97 BOOST_SERIALIZATION_ASSUME_ABSTRACT(bus_stop
)
99 std::ostream
& operator<<(std::ostream
&os
, const bus_stop
&bs
)
101 return os
<< bs
.latitude
<< bs
.longitude
<< ' ' << bs
.description();
104 /////////////////////////////////////////////////////////////
105 // Several kinds of bus stops
107 // illustrates serialization of derived types
109 class bus_stop_corner
: public bus_stop
111 friend class boost::serialization::access
;
114 virtual std::string
description() const
116 return street1
+ " and " + street2
;
118 template<class Archive
>
119 void serialize(Archive
&ar
, const unsigned int version
)
121 // save/load base class information
122 ar
& boost::serialization::base_object
<bus_stop
>(*this);
123 ar
& street1
& street2
;
128 bus_stop_corner(const gps_position
& _lat
, const gps_position
& _long
,
129 const std::string
& _s1
, const std::string
& _s2
131 bus_stop(_lat
, _long
), street1(_s1
), street2(_s2
)
136 class bus_stop_destination
: public bus_stop
138 friend class boost::serialization::access
;
140 virtual std::string
description() const
144 template<class Archive
>
145 void serialize(Archive
&ar
, const unsigned int version
)
147 ar
& boost::serialization::base_object
<bus_stop
>(*this) & name
;
151 bus_stop_destination(){}
152 bus_stop_destination(
153 const gps_position
& _lat
, const gps_position
& _long
, const std::string
& _name
155 bus_stop(_lat
, _long
), name(_name
)
160 /////////////////////////////////////////////////////////////
161 // a bus route is a collection of bus stops
163 // illustrates serialization of STL collection templates.
165 // illustrates serialzation of polymorphic pointer (bus stop *);
167 // illustrates storage and recovery of shared pointers is correct
168 // and efficient. That is objects pointed to by more than one
169 // pointer are stored only once. In such cases only one such
170 // object is restored and pointers are restored to point to it
174 friend class boost::serialization::access
;
175 friend std::ostream
& operator<<(std::ostream
&os
, const bus_route
&br
);
176 typedef bus_stop
* bus_stop_pointer
;
177 std::list
<bus_stop_pointer
> stops
;
178 template<class Archive
>
179 void serialize(Archive
&ar
, const unsigned int version
)
181 // in this program, these classes are never serialized directly but rather
182 // through a pointer to the base class bus_stop. So we need a way to be
183 // sure that the archive contains information about these derived classes.
184 //ar.template register_type<bus_stop_corner>();
185 ar
.register_type(static_cast<bus_stop_corner
*>(NULL
));
186 //ar.template register_type<bus_stop_destination>();
187 ar
.register_type(static_cast<bus_stop_destination
*>(NULL
));
188 // serialization of stl collections is already defined
194 void append(bus_stop
*_bs
)
196 stops
.insert(stops
.end(), _bs
);
199 std::ostream
& operator<<(std::ostream
&os
, const bus_route
&br
)
201 std::list
<bus_stop
*>::const_iterator it
;
202 // note: we're displaying the pointer to permit verification
203 // that duplicated pointers are properly restored.
204 for(it
= br
.stops
.begin(); it
!= br
.stops
.end(); it
++){
205 os
<< '\n' << std::hex
<< "0x" << *it
<< std::dec
<< ' ' << **it
;
210 /////////////////////////////////////////////////////////////
211 // a bus schedule is a collection of routes each with a starting time
213 // Illustrates serialization of STL objects(pair) in a non-intrusive way.
214 // See definition of operator<< <pair<F, S> >(ar, pair) and others in
217 // illustrates nesting of serializable classes
219 // illustrates use of version number to automatically grandfather older
220 // versions of the same class.
225 // note: this structure was made public. because the friend declarations
226 // didn't seem to work as expected.
229 template<class Archive
>
230 void serialize(Archive
&ar
, const unsigned int file_version
)
232 // in versions 2 or later
233 if(file_version
>= 2)
234 // read the drivers name
236 // all versions have the follwing info
243 // only after system shipped was the driver's name added to the class
247 trip_info(int _h
, int _m
, const std::string
&_d
) :
248 hour(_h
), minute(_m
), driver(_d
)
252 friend class boost::serialization::access
;
253 friend std::ostream
& operator<<(std::ostream
&os
, const bus_schedule
&bs
);
254 friend std::ostream
& operator<<(std::ostream
&os
, const bus_schedule::trip_info
&ti
);
255 std::list
<std::pair
<trip_info
, bus_route
*> > schedule
;
256 template<class Archive
>
257 void serialize(Archive
&ar
, const unsigned int version
)
262 void append(const std::string
&_d
, int _h
, int _m
, bus_route
*_br
)
264 schedule
.insert(schedule
.end(), std::make_pair(trip_info(_h
, _m
, _d
), _br
));
268 BOOST_CLASS_VERSION(bus_schedule::trip_info
, 2)
270 std::ostream
& operator<<(std::ostream
&os
, const bus_schedule::trip_info
&ti
)
272 return os
<< '\n' << ti
.hour
<< ':' << ti
.minute
<< ' ' << ti
.driver
<< ' ';
274 std::ostream
& operator<<(std::ostream
&os
, const bus_schedule
&bs
)
276 std::list
<std::pair
<bus_schedule::trip_info
, bus_route
*> >::const_iterator it
;
277 for(it
= bs
.schedule
.begin(); it
!= bs
.schedule
.end(); it
++){
278 os
<< it
->first
<< *(it
->second
);
283 void save_schedule(const bus_schedule
&s
, const char * filename
){
285 std::ofstream
ofs(filename
);
286 boost::archive::text_oarchive
oa(ofs
);
291 restore_schedule(bus_schedule
&s
, const char * filename
)
294 std::ifstream
ifs(filename
);
295 boost::archive::text_iarchive
ia(ifs
);
297 // restore the schedule from the archive
301 int main(int argc
, char *argv
[])
304 bus_schedule original_schedule
;
308 bus_stop
*bs0
= new bus_stop_corner(
309 gps_position(34, 135, 52.560f
),
310 gps_position(134, 22, 78.30f
),
311 "24th Street", "10th Avenue"
313 bus_stop
*bs1
= new bus_stop_corner(
314 gps_position(35, 137, 23.456f
),
315 gps_position(133, 35, 54.12f
),
316 "State street", "Cathedral Vista Lane"
318 bus_stop
*bs2
= new bus_stop_destination(
319 gps_position(35, 136, 15.456f
),
320 gps_position(133, 32, 15.300f
),
323 bus_stop
*bs3
= new bus_stop_destination(
324 gps_position(35, 134, 48.789f
),
325 gps_position(133, 32, 16.230f
),
335 // add trips to schedule
336 original_schedule
.append("bob", 6, 24, &route0
);
337 original_schedule
.append("bob", 9, 57, &route0
);
338 original_schedule
.append("alice", 11, 02, &route0
);
340 // make aother routes
346 // add trips to schedule
347 original_schedule
.append("ted", 7, 17, &route1
);
348 original_schedule
.append("ted", 9, 38, &route1
);
349 original_schedule
.append("alice", 11, 47, &route1
);
351 // display the complete schedule
352 std::cout
<< "original schedule";
353 std::cout
<< original_schedule
;
355 std::string
filename(boost::archive::tmpdir());
356 filename
+= "/demofile.txt";
359 save_schedule(original_schedule
, filename
.c_str());
361 // ... some time later
362 // make a new schedule
363 bus_schedule new_schedule
;
365 restore_schedule(new_schedule
, filename
.c_str());
368 std::cout
<< "\nrestored schedule";
369 std::cout
<< new_schedule
;
370 // should be the same as the old one. (except for the pointer values)