1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_non_intrursive.cpp
3
4 // (C) Copyright 2002 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
9 // should pass compilation and execution
10
11 // this tests:
12 // a) non-intrusive method of implementing serialization
13 // b) usage of a non-default constructor
14
15 #include <fstream>
16 #include <cstdlib> // for rand()
17 #include <cstdio> // remove
18 #include <boost/config.hpp>
19 #include <boost/detail/workaround.hpp>
20 #include <boost/limits.hpp>
21 #include <boost/math/special_functions/next.hpp>
22
23 #if defined(BOOST_NO_STDC_NAMESPACE)
24 namespace std{
25 using ::rand;
26 using ::remove;
27 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
28 using ::numeric_limits;
29 #endif
30 }
31 #endif
32
33 #include <boost/archive/archive_exception.hpp>
34 #include "test_tools.hpp"
35
36 ///////////////////////////////////////////////////////
37 // simple class test - using non-intrusive syntax
38 // illustrates the usage of the non-intrusve syntax
39 class A
40 {
41 public:
42 signed char s;
43 unsigned char t;
44 signed int u;
45 unsigned int v;
46 float w;
47 double x;
48 A();
49 bool operator==(const A & rhs) const;
50 bool operator<(const A & rhs) const;
51 };
52
A()53 A::A() :
54 s(static_cast<signed char>(0xff & std::rand())),
55 t(static_cast<signed char>(0xff & std::rand())),
56 u(std::rand()),
57 v(std::rand()),
58 w((float)std::rand() / std::rand()),
59 x((double)std::rand() / std::rand())
60 {
61 }
62
operator ==(const A & rhs) const63 bool A::operator==(const A &rhs) const
64 {
65 return
66 s == rhs.s
67 && t == rhs.t
68 && u == rhs.u
69 && v == rhs.v
70 && std::abs( boost::math::float_distance(w, rhs.w)) < 2
71 && std::abs( boost::math::float_distance(x, rhs.x)) < 2
72 ;
73 }
74
operator <(const A & rhs) const75 bool A::operator<(const A &rhs) const
76 {
77 if(! (s == rhs.s) )
78 return s < rhs.s;
79 if(! (t == rhs.t) )
80 return t < rhs.t;
81 if(! (u == rhs.u) )
82 return t < rhs.u;
83 if(! (v == rhs.v) )
84 return t < rhs.v;
85 if(std::abs( boost::math::float_distance(w, rhs.w)) > 1)
86 return false;
87 if(std::abs( boost::math::float_distance(x, rhs.x)) > 1)
88 return false;
89 return false;
90 }
91
92 // note the following:
93
94 // function specializations must be defined in the appropriate
95 // namespace - boost::serialization
96 namespace boost {
97 namespace serialization {
98
99 // This first set of overrides should work with all compilers.
100
101 // The last argument is int while the default versions
102 // defined in serialization.hpp have long as the last argument.
103 // This is part of the work around for compilers that don't
104 // support correct function template ordering. These functions
105 // are always called with 0 (i.e. an int) as the last argument.
106 // Our specialized versions also have int as the last argument
107 // while the default versions have a long as the last argument.
108 // This makes our specialized versions a better match than the
109 // default ones as no argument conversion is required to make a match
110 template<class Archive>
serialize(Archive & ar,A & a,const unsigned int)111 void serialize(
112 Archive & ar,
113 A & a,
114 const unsigned int /* file_version */
115 ){
116 ar & boost::serialization::make_nvp("s", a.s);
117 ar & boost::serialization::make_nvp("t", a.t);
118 ar & boost::serialization::make_nvp("u", a.u);
119 ar & boost::serialization::make_nvp("v", a.v);
120 ar & boost::serialization::make_nvp("w", a.w);
121 ar & boost::serialization::make_nvp("x", a.x);
122 }
123
124 } // serialization
125 } // namespace boost
126
save(const char * testfile)127 void save(const char * testfile){
128 test_ostream os(testfile, TEST_STREAM_FLAGS);
129 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
130 A a;
131
132 oa << BOOST_SERIALIZATION_NVP(a);
133
134 // save a copy pointer to this item
135 A *pa1 = &a;
136 oa << BOOST_SERIALIZATION_NVP(pa1);
137
138 // save pointer to a new object
139 A *pa2 = new A();
140 oa << BOOST_SERIALIZATION_NVP(pa2);
141
142 delete pa2;
143 }
144
load(const char * testfile)145 void load(const char * testfile){
146 test_istream is(testfile, TEST_STREAM_FLAGS);
147 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
148
149 A a;
150 ia >> BOOST_SERIALIZATION_NVP(a);
151
152 A *pa1;
153 ia >> BOOST_SERIALIZATION_NVP(pa1);
154 BOOST_CHECK_MESSAGE(pa1 == &a, "Copy of pointer not correctly restored");
155
156 A *pa2;
157 ia >> BOOST_SERIALIZATION_NVP(pa2);
158 BOOST_CHECK_MESSAGE(pa2 != &a, "Pointer not correctly restored");
159
160 delete pa2;
161 }
162
163 int
test_main(int,char * [])164 test_main( int /* argc */, char* /* argv */[] )
165 {
166 const char * testfile = boost::archive::tmpnam(NULL);
167 BOOST_REQUIRE(NULL != testfile);
168 save(testfile);
169 load(testfile);
170 std::remove(testfile);
171 return EXIT_SUCCESS;
172 }
173
174 // EOF
175