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