1 /*
2   Copyright (c) 2014, Randolph Voorhies, Shane Grant
3   All rights reserved.
4 
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions are met:
7       * Redistributions of source code must retain the above copyright
8         notice, this list of conditions and the following disclaimer.
9       * Redistributions in binary form must reproduce the above copyright
10         notice, this list of conditions and the following disclaimer in the
11         documentation and/or other materials provided with the distribution.
12       * Neither the name of cereal nor the
13         names of its contributors may be used to endorse or promote products
14         derived from this software without specific prior written permission.
15 
16   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
20   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #ifndef CEREAL_TEST_STRUCTS_MINIMAL_H_
28 #define CEREAL_TEST_STRUCTS_MINIMAL_H_
29 #include "common.hpp"
30 
31 struct BogusBase
32 {
33   template <class Archive>
serializeBogusBase34   void serialize( Archive & ) {}
35 
36   template <class Archive>
saveBogusBase37   void save( Archive & ) const {}
38 
39   template <class Archive>
loadBogusBase40   void load( Archive & ) {}
41 
42   template <class Archive>
save_minimalBogusBase43   int save_minimal( Archive const & ) const { return 0; }
44 
45   template <class Archive>
load_minimalBogusBase46   void load_minimal( Archive const &, int const & ) {}
47 };
48 
49 struct BogusBaseVersioned
50 {
51   template <class Archive>
serializeBogusBaseVersioned52   void serialize( Archive &, const std::uint32_t ) {}
53 
54   template <class Archive>
saveBogusBaseVersioned55   void save( Archive &, const std::uint32_t ) const {}
56 
57   template <class Archive>
loadBogusBaseVersioned58   void load( Archive &, const std::uint32_t ) {}
59 
60   template <class Archive>
save_minimalBogusBaseVersioned61   int save_minimal( Archive const &, const std::uint32_t ) const { return 0; }
62 
63   template <class Archive>
load_minimalBogusBaseVersioned64   void load_minimal( Archive const &, int const &, const std::uint32_t ) {}
65 };
66 
67 struct BogusBasePolymorphic
68 {
69   template <class Archive>
serializeBogusBasePolymorphic70   void serialize( Archive & ) {}
71 
doesNothingBogusBasePolymorphic72   virtual void doesNothing() {}
73 };
74 
75 class SpecializedMSerialize : public BogusBase
76 {
77   public:
78     SpecializedMSerialize() = default;
SpecializedMSerialize(int xx)79     SpecializedMSerialize( int xx ) : x(xx) {}
80 
81     int x;
82 
83   private:
84     friend class cereal::access;
85     template <class Archive>
serialize(Archive & ar)86     void serialize( Archive & ar )
87     {
88       ar( x );
89     }
90 };
91 
92 class SpecializedMSerializeVersioned : public BogusBaseVersioned
93 {
94   public:
95     SpecializedMSerializeVersioned() = default;
SpecializedMSerializeVersioned(int xx)96     SpecializedMSerializeVersioned( int xx ) : x(xx) {}
97 
98     int x;
99 
100   private:
101     friend class cereal::access;
102     template <class Archive>
serialize(Archive & ar,const std::uint32_t)103     void serialize( Archive & ar, const std::uint32_t )
104     {
105       ar( x );
106     }
107 };
108 
109 class SpecializedMSplit : public BogusBase
110 {
111   public:
112     SpecializedMSplit() = default;
SpecializedMSplit(int xx)113     SpecializedMSplit( int xx ) : x(xx) {}
114 
115     int x;
116 
117   private:
118     friend class cereal::access;
119     template <class Archive>
save(Archive & ar) const120     void save( Archive & ar ) const
121     {
122       ar( x );
123     }
124 
125     template <class Archive>
load(Archive & ar)126     void load( Archive & ar )
127     {
128       ar( x );
129     }
130 };
131 
132 class SpecializedMSplitVersioned : public BogusBaseVersioned
133 {
134   public:
135     SpecializedMSplitVersioned() = default;
SpecializedMSplitVersioned(int xx)136     SpecializedMSplitVersioned( int xx ) : x(xx) {}
137 
138     int x;
139 
140   private:
141     friend class cereal::access;
142     template <class Archive>
save(Archive & ar,const std::uint32_t) const143     void save( Archive & ar, const std::uint32_t ) const
144     {
145       ar( x );
146     }
147 
148     template <class Archive>
load(Archive & ar,const std::uint32_t)149     void load( Archive & ar, const std::uint32_t )
150     {
151       ar( x );
152     }
153 };
154 
155 class SpecializedMSplitPolymorphic : public BogusBasePolymorphic
156 {
157   public:
158     SpecializedMSplitPolymorphic() = default;
SpecializedMSplitPolymorphic(int xx)159     SpecializedMSplitPolymorphic( int xx ) : x(xx) {}
160 
161     int x;
162 
163   private:
164     friend class cereal::access;
165     template <class Archive>
save(Archive & ar) const166     void save( Archive & ar ) const
167     {
168       ar( x );
169     }
170 
171     template <class Archive>
load(Archive & ar)172     void load( Archive & ar )
173     {
174       ar( x );
175     }
176 };
177 
178 class SpecializedMSplitMinimal : public BogusBase
179 {
180   public:
181     SpecializedMSplitMinimal() = default;
SpecializedMSplitMinimal(int xx)182     SpecializedMSplitMinimal( int xx ) : x(xx) {}
183 
184     int x;
185 
186   private:
187     friend class cereal::access;
188     template <class Archive>
save_minimal(Archive const &) const189     int save_minimal( Archive const & ) const
190     {
191       return x;
192     }
193 
194     template <class Archive>
load_minimal(Archive const &,int const & value)195     void load_minimal( Archive const &, int const & value )
196     {
197       x = value;
198     }
199 };
200 
201 class SpecializedMSplitVersionedMinimal : public BogusBaseVersioned
202 {
203   public:
204     SpecializedMSplitVersionedMinimal() = default;
SpecializedMSplitVersionedMinimal(int xx)205     SpecializedMSplitVersionedMinimal( int xx ) : x(xx) {}
206 
207     int x;
208 
209   private:
210     friend class cereal::access;
211     template <class Archive>
save_minimal(Archive const &,const std::uint32_t) const212     int save_minimal( Archive const &, const std::uint32_t ) const
213     {
214       return x;
215     }
216 
217     template <class Archive>
load_minimal(Archive const &,int const & value,const std::uint32_t)218     void load_minimal( Archive const &, int const & value, const std::uint32_t )
219     {
220       x = value;
221     }
222 };
223 
224 class SpecializedNMSerialize : public BogusBase
225 {
226   public:
227     SpecializedNMSerialize() = default;
SpecializedNMSerialize(int xx)228     SpecializedNMSerialize( int xx ) : x(xx) {}
229 
230     int x;
231 };
232 
233 template <class Archive>
serialize(Archive & ar,SpecializedNMSerialize & s)234 void serialize( Archive & ar, SpecializedNMSerialize & s )
235 {
236   ar( s.x );
237 }
238 
239 class SpecializedNMSerializeVersioned : public BogusBaseVersioned
240 {
241   public:
242     SpecializedNMSerializeVersioned() = default;
SpecializedNMSerializeVersioned(int xx)243     SpecializedNMSerializeVersioned( int xx ) : x(xx) {}
244 
245     int x;
246 };
247 
248 template <class Archive>
serialize(Archive & ar,SpecializedNMSerializeVersioned & s)249 void serialize( Archive & ar, SpecializedNMSerializeVersioned & s )
250 {
251   ar( s.x );
252 }
253 
254 class SpecializedNMSplit : public BogusBase
255 {
256   public:
257     SpecializedNMSplit() = default;
SpecializedNMSplit(int xx)258     SpecializedNMSplit( int xx ) : x(xx) {}
259 
260     int x;
261 };
262 
263 template <class Archive>
load(Archive & ar,SpecializedNMSplit & s)264 void load( Archive & ar, SpecializedNMSplit & s )
265 {
266   ar( s.x );
267 }
268 
269 template <class Archive>
save(Archive & ar,SpecializedNMSplit const & s)270 void save( Archive & ar, SpecializedNMSplit const & s )
271 {
272   ar( s.x );
273 }
274 
275 class SpecializedNMSplitVersioned : public BogusBaseVersioned
276 {
277   public:
278     SpecializedNMSplitVersioned() = default;
SpecializedNMSplitVersioned(int xx)279     SpecializedNMSplitVersioned( int xx ) : x(xx) {}
280 
281     int x;
282 };
283 
284 template <class Archive>
load(Archive & ar,SpecializedNMSplitVersioned & s,const std::uint32_t)285 void load( Archive & ar, SpecializedNMSplitVersioned & s, const std::uint32_t )
286 {
287   ar( s.x );
288 }
289 
290 template <class Archive>
save(Archive & ar,SpecializedNMSplitVersioned const & s,const std::uint32_t)291 void save( Archive & ar, SpecializedNMSplitVersioned const & s, const std::uint32_t )
292 {
293   ar( s.x );
294 }
295 
296 class SpecializedNMSplitMinimal : public BogusBase
297 {
298   public:
299     SpecializedNMSplitMinimal() = default;
SpecializedNMSplitMinimal(int xx)300     SpecializedNMSplitMinimal( int xx ) : x(xx) {}
301 
302     int x;
303 };
304 
305 template <class Archive>
load_minimal(Archive const &,SpecializedNMSplitMinimal & s,int const & value)306 void load_minimal( Archive const &, SpecializedNMSplitMinimal & s, int const & value )
307 {
308   s.x = value;
309 }
310 
311 template <class Archive>
save_minimal(Archive const &,SpecializedNMSplitMinimal const & s)312 int save_minimal( Archive const &, SpecializedNMSplitMinimal const & s )
313 {
314   return s.x;
315 }
316 
317 class SpecializedNMSplitVersionedMinimal : public BogusBaseVersioned
318 {
319   public:
320     SpecializedNMSplitVersionedMinimal() = default;
SpecializedNMSplitVersionedMinimal(int xx)321     SpecializedNMSplitVersionedMinimal( int xx ) : x(xx) {}
322 
323     int x;
324 };
325 
326 template <class Archive>
load_minimal(Archive const &,SpecializedNMSplitVersionedMinimal & s,int const & value,const std::uint32_t)327 void load_minimal( Archive const &, SpecializedNMSplitVersionedMinimal & s, int const & value, const std::uint32_t )
328 {
329   s.x = value;
330 }
331 
332 template <class Archive>
save_minimal(Archive const &,SpecializedNMSplitVersionedMinimal const & s,const std::uint32_t)333 int save_minimal( Archive const &, SpecializedNMSplitVersionedMinimal const & s, const std::uint32_t )
334 {
335   return s.x;
336 }
337 
338 namespace cereal
339 {
340   template <class Archive> struct specialize<Archive, SpecializedMSerialize, cereal::specialization::member_serialize> {};
341   template <class Archive> struct specialize<Archive, SpecializedMSerializeVersioned, cereal::specialization::member_serialize> {};
342 
343   template <class Archive> struct specialize<Archive, SpecializedMSplit, cereal::specialization::member_load_save> {};
344   template <class Archive> struct specialize<Archive, SpecializedMSplitVersioned, cereal::specialization::member_load_save> {};
345   template <class Archive> struct specialize<Archive, SpecializedMSplitPolymorphic, cereal::specialization::member_load_save> {};
346 
347   template <class Archive> struct specialize<Archive, SpecializedMSplitMinimal, cereal::specialization::member_load_save_minimal> {};
348   template <class Archive> struct specialize<Archive, SpecializedMSplitVersionedMinimal, cereal::specialization::member_load_save_minimal> {};
349 
350   template <class Archive> struct specialize<Archive, SpecializedNMSerialize, cereal::specialization::non_member_serialize> {};
351   template <class Archive> struct specialize<Archive, SpecializedNMSerializeVersioned, cereal::specialization::non_member_serialize> {};
352 
353   template <class Archive> struct specialize<Archive, SpecializedNMSplit, cereal::specialization::non_member_load_save> {};
354   template <class Archive> struct specialize<Archive, SpecializedNMSplitVersioned, cereal::specialization::non_member_load_save> {};
355 
356   template <class Archive> struct specialize<Archive, SpecializedNMSplitMinimal,
357            cereal::specialization::non_member_load_save_minimal> {};
358   template <class Archive> struct specialize<Archive, SpecializedNMSplitVersionedMinimal,
359            cereal::specialization::non_member_load_save_minimal> {};
360 }
361 
362 CEREAL_REGISTER_TYPE(SpecializedMSplitPolymorphic)
CEREAL_REGISTER_POLYMORPHIC_RELATION(BogusBasePolymorphic,SpecializedMSplitPolymorphic)363 CEREAL_REGISTER_POLYMORPHIC_RELATION(BogusBasePolymorphic, SpecializedMSplitPolymorphic)
364 
365 template <class IArchive, class OArchive> inline
366 void test_structs_specialized()
367 {
368   std::random_device rd;
369   std::mt19937 gen(rd());
370 
371   for(int ii=0; ii<100; ++ii)
372   {
373     SpecializedMSerialize               o_iser          = { random_value<int>(gen) };
374     SpecializedMSerializeVersioned      o_iserv         = { random_value<int>(gen) };
375 
376     SpecializedMSplit                   o_ispl          = { random_value<int>(gen) };
377     SpecializedMSplitVersioned          o_isplv         = { random_value<int>(gen) };
378 
379     // added re: issue #180
380     std::shared_ptr<BogusBasePolymorphic> o_shared_ispl = std::make_shared<SpecializedMSplitPolymorphic>( random_value<int>(gen) );
381 
382     SpecializedMSplitMinimal            o_isplm         = { random_value<int>(gen) };
383     SpecializedMSplitVersionedMinimal   o_isplvm        = { random_value<int>(gen) };
384 
385     SpecializedNMSerialize              o_eser          = { random_value<int>(gen) };
386     SpecializedNMSerializeVersioned     o_eserv         = { random_value<int>(gen) };
387 
388     SpecializedNMSplit                  o_espl          = { random_value<int>(gen) };
389     SpecializedNMSplitVersioned         o_esplv         = { random_value<int>(gen) };
390 
391     SpecializedNMSplitMinimal           o_esplm         = { random_value<int>(gen) };
392     SpecializedNMSplitVersionedMinimal  o_esplvm        = { random_value<int>(gen) };
393 
394 
395     std::ostringstream os;
396     {
397       OArchive oar(os);
398 
399       oar( o_iser, o_iserv,
400            o_ispl, o_isplv, o_shared_ispl,
401            o_isplm, o_isplvm,
402            o_eser, o_eserv,
403            o_espl, o_esplv,
404            o_esplm, o_esplvm );
405     }
406 
407     decltype(o_iser) i_iser;
408     decltype(o_iserv) i_iserv;
409 
410     decltype(o_ispl) i_ispl;
411     decltype(o_isplv) i_isplv;
412 
413     decltype(o_shared_ispl) i_shared_ispl;
414 
415     decltype(o_isplm) i_isplm;
416     decltype(o_isplvm) i_isplvm;
417 
418     decltype(o_eser) i_eser;
419     decltype(o_eserv) i_eserv;
420 
421     decltype(o_espl) i_espl;
422     decltype(o_esplv) i_esplv;
423 
424     decltype(o_esplm) i_esplm;
425     decltype(o_esplvm) i_esplvm;
426 
427     std::istringstream is(os.str());
428     {
429       IArchive iar(is);
430 
431       iar( i_iser, i_iserv,
432            i_ispl, i_isplv, i_shared_ispl,
433            i_isplm, i_isplvm,
434            i_eser, i_eserv,
435            i_espl, i_esplv,
436            i_esplm, i_esplvm );
437     }
438 
439     CHECK_EQ(i_iser.x, o_iser.x);
440     CHECK_EQ(i_iserv.x, o_iserv.x);
441 
442     CHECK_EQ(i_ispl.x, o_ispl.x);
443     CHECK_EQ(i_isplv.x, o_isplv.x);
444 
445     CHECK_EQ(dynamic_cast<SpecializedMSplitPolymorphic*>(i_shared_ispl.get())->x, dynamic_cast<SpecializedMSplitPolymorphic*>(o_shared_ispl.get())->x);
446 
447     CHECK_EQ(i_isplm.x, o_isplm.x);
448     CHECK_EQ(i_isplvm.x, o_isplvm.x);
449 
450     CHECK_EQ(i_eser.x, o_eser.x);
451     CHECK_EQ(i_eserv.x, o_eserv.x);
452 
453     CHECK_EQ(i_espl.x, o_espl.x);
454     CHECK_EQ(i_esplv.x, o_esplv.x);
455 
456     CHECK_EQ(i_esplm.x, o_esplm.x);
457     CHECK_EQ(i_esplvm.x, o_esplvm.x);
458   }
459 }
460 
461 #endif // CEREAL_TEST_STRUCTS_SPECIALIZED_H_
462