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 
28 #include <cereal/cereal.hpp>
29 #include <cereal/archives/binary.hpp>
30 #include <cereal/archives/json.hpp>
31 
32 #include <cereal/types/string.hpp>
33 #include <cereal/types/utility.hpp>
34 #include <cereal/types/memory.hpp>
35 #include <cereal/types/complex.hpp>
36 #include <cereal/types/base_class.hpp>
37 #include <cereal/types/array.hpp>
38 #include <cereal/types/vector.hpp>
39 #include <cereal/types/map.hpp>
40 
41 #include <sstream>
42 #include <fstream>
43 #include <cassert>
44 #include <complex>
45 #include <iostream>
46 #include <iomanip>
47 #include <string>
48 
49 // ###################################
50 struct Test1
51 {
52   int a;
53 
54   private:
55     friend class cereal::access;
56     template<class Archive>
serializeTest157     void serialize(Archive & ar)
58     {
59       ar(CEREAL_NVP(a));
60     }
61 };
62 
63 // ###################################
64 class Test2
65 {
66   public:
Test2()67     Test2() {}
Test2(int x)68     Test2( int x ) : a( x ) {}
69     int a;
70 
71   private:
72     friend class cereal::access;
73 
74     template<class Archive>
save(Archive & ar) const75       void save(Archive & ar) const
76       {
77         ar(a);
78       }
79 
80     template<class Archive>
load(Archive & ar)81       void load(Archive & ar)
82       {
83         ar(a);
84       }
85 };
86 
87 // ###################################
88 struct Test3
89 {
90   int a;
91 };
92 
93 template<class Archive>
serialize(Archive & ar,Test3 & t)94 void serialize(Archive & ar, Test3 & t)
95 {
96   ar(CEREAL_NVP(t.a));
97 }
98 
99 namespace test4
100 {
101   // ###################################
102   struct Test4
103   {
104     int a;
105   };
106 
107   template<class Archive>
save(Archive & ar,Test4 const & t)108   void save(Archive & ar, Test4 const & t)
109   {
110     ar(CEREAL_NVP(t.a));
111   }
112 
113   template<class Archive>
load(Archive & ar,Test4 & t)114   void load(Archive & ar, Test4 & t)
115   {
116     ar(CEREAL_NVP(t.a));
117   }
118 }
119 
120 class Private
121 {
122   public:
Private()123     Private() : a('z') {}
124 
125   private:
126     char a;
127 
128     friend class cereal::access;
129 
130     template<class Archive>
serialize(Archive & ar)131       void serialize(Archive & ar)
132       {
133         ar(a);
134       }
135 };
136 
137 struct Everything
138 {
139   int x;
140   int y;
141   Test1 t1;
142   Test2 t2;
143   Test3 t3;
144   test4::Test4 t4;
145   std::string s;
146 
147   template<class Archive>
serializeEverything148   void serialize(Archive & ar)
149   {
150     ar(CEREAL_NVP(x));
151     ar(CEREAL_NVP(y));
152     ar(CEREAL_NVP(t1));
153     ar(CEREAL_NVP(t2));
154     ar(CEREAL_NVP(t3));
155     ar(CEREAL_NVP(t4));
156     ar(CEREAL_NVP(s));
157   }
158 
operator ==Everything159   bool operator==(Everything const & o)
160   {
161     return
162       x == o.x &&
163       y == o.y &&
164       t1.a == o.t1.a &&
165       t2.a == o.t2.a &&
166       t3.a == o.t3.a &&
167       t4.a == o.t4.a &&
168       s == o.s;
169   }
170 };
171 
172 
173 struct SubFixture
174 {
SubFixtureSubFixture175   SubFixture() : a( 3 ),
176     b( 9999 ),
177     c( 100.1f ),
178     d( 2000.9 ),
179     s( "hello, world!" )
180   {}
181 
182   int a;
183   uint64_t b;
184   float c;
185   double d;
186   std::string s;
187 
188     template<class Archive>
serializeSubFixture189       void serialize(Archive & ar)
190       {
191         ar( CEREAL_NVP(a),
192             b,
193             c,
194             CEREAL_NVP(d),
195             CEREAL_NVP(s) );
196       }
changeSubFixture197     void change()
198     {
199       a = 4;
200       b = 4;
201       c = 4;
202       d = 4;
203       s = "4";
204     }
205 };
206 
207 struct Fixture
208 {
209   SubFixture f1, f2, f3;
210   int array[4];
211 
FixtureFixture212   Fixture()
213   {
214     array[0] = 1;
215     array[1] = 2;
216     array[2] = 3;
217     array[3] = 4;
218   }
219 
220   template<class Archive>
saveFixture221   void save(Archive & ar) const
222   {
223     ar( f1,
224         CEREAL_NVP(f2),
225         f3 );
226     ar.saveBinaryValue( array, sizeof(int)*4, "cool array man" );
227   }
228 
229   template<class Archive>
loadFixture230   void load(Archive & ar)
231   {
232     ar( f1,
233         CEREAL_NVP(f2),
234         f3 );
235     ar.loadBinaryValue( array, sizeof(int)*4 );
236   }
237 
changeFixture238     void change()
239     {
240       f1.change();
241       f2.change();
242       f3.change();
243     }
244 };
245 
246 struct AAA
247 {
AAAAAA248   AAA() : one( 1 ), two( 2 ), three( { {1, 2, 3}, { 4, 5, 6 }, {} } ) {}
249   int one, two;
250 
251   std::vector<std::vector<int>> three;
252 
253   template<class Archive>
serializeAAA254     void serialize(Archive & ar)
255     {
256       ar( CEREAL_NVP(one), CEREAL_NVP(two) );
257       //ar( CEREAL_NVP(three) );
258     }
259 };
260 
261 class Stuff
262 {
263   public:
Stuff()264     Stuff() {}
265 
fillData()266     void fillData()
267     {
268       std::vector<std::complex<float>> t1{ {0, -1.0f},
269                           { 0, -2.9932f },
270                           { 0, -3.5f } };
271       std::vector<std::complex<float>> t2{ {1.0f, 0},
272                      { 2.2f, 0 },
273                      { 3.3f, 0 } };
274       data["imaginary"] = t1;
275       data["real"] = t2;
276     }
277 
278   private:
279     std::map<std::string, std::vector<std::complex<float>>> data;
280 
281     friend class cereal::access;
282 
283     template <class Archive>
serialize(Archive & ar)284     void serialize( Archive & ar )
285     {
286       ar( CEREAL_NVP(data) );
287     }
288 };
289 
290 struct OOJson
291 {
292   OOJson() = default;
OOJsonOOJson293   OOJson( int aa, int bb, bool cc, double dd ) :
294     a( aa ), b( bb ), c{ cc, dd }
295   {
296     d[0] = 0; d[1] = 1; d[2] = 2;
297   }
298 
299   int a;
300   int b;
301   std::pair<bool, double> c;
302   float d[3];
303 
304   template <class Archive>
serializeOOJson305   void serialize( Archive & ar )
306   {
307     ar( CEREAL_NVP(c) );
308     ar( CEREAL_NVP(a) );
309     ar( b );
310     ar( CEREAL_NVP(d) );
311   }
312 };
313 
314 // ######################################################################
main()315 int main()
316 {
317   std::cout << std::boolalpha << std::endl;
318 
319   {
320     std::ofstream os("file.json");
321     cereal::JSONOutputArchive oar( os );
322 
323     //auto f = std::make_shared<Fixture>();
324     //auto f2 = f;
325     //oar( f );
326     //oar( f2 );
327     Stuff s; s.fillData();
328     oar( cereal::make_nvp("best data ever", s) );
329   }
330 
331   {
332     std::ifstream is("file.json");
333     std::string str((std::istreambuf_iterator<char>(is)), std::istreambuf_iterator<char>());
334     std::cout << "---------------------" << std::endl << str << std::endl << "---------------------" << std::endl;
335   }
336 
337   // playground
338   {
339     cereal::JSONOutputArchive archive( std::cout );
340     bool arr[] = {true, false};
341     std::vector<int> vec = {1, 2, 3, 4, 5};
342     archive( CEREAL_NVP(vec),
343         arr );
344     auto f = std::make_shared<Fixture>();
345     auto f2 = f;
346     archive( f );
347     archive( f2 );
348   }
349 
350   // test out of order
351   std::stringstream oos;
352   {
353     cereal::JSONOutputArchive ar(oos);
354     cereal::JSONOutputArchive ar2(std::cout,
355         cereal::JSONOutputArchive::Options(2, cereal::JSONOutputArchive::Options::IndentChar::space, 2) );
356 
357     ar( cereal::make_nvp( "1", 1 ),
358         cereal::make_nvp( "2", 2 ),
359         3,
360         0, // unused
361         cereal::make_nvp( "4", 4 ),
362         cereal::make_nvp( "5", 5 ) );
363 
364     int x = 33;
365     ar.saveBinaryValue( &x, sizeof(int), "bla" );
366 
367     ar2( cereal::make_nvp( "1", 1 ),
368          cereal::make_nvp( "2", 2 ),
369          3,
370          0, // unused
371          cereal::make_nvp( "4", 4 ),
372          cereal::make_nvp( "5", 5 ) );
373     ar2.saveBinaryValue( &x, sizeof(int), "bla" );
374 
375     OOJson oo( 1, 2, true, 4.2 );
376     ar( CEREAL_NVP(oo) );
377     ar2( CEREAL_NVP(oo) );
378 
379     // boost stuff
380     ar & cereal::make_nvp("usingop&", oo ) & 6;
381     ar << 5 << 4 << 3;
382 
383     ar2 & cereal::make_nvp("usingop&", oo ) & 6;
384     ar2 << 5 << 4 << 3;
385 
386     long double ld = std::numeric_limits<long double>::max();
387     long long ll = std::numeric_limits<long long>::max();
388     unsigned long long ull = std::numeric_limits<unsigned long long>::max();
389 
390     ar( CEREAL_NVP(ld),
391         CEREAL_NVP(ll),
392         CEREAL_NVP(ull) );
393 
394     ar2( CEREAL_NVP(ld),
395          CEREAL_NVP(ll),
396          CEREAL_NVP(ull) );
397   }
398 
399   {
400     cereal::JSONInputArchive ar(oos);
401     int i1, i2, i3, i4, i5, x;
402 
403     ar( i1 );
404     ar( cereal::make_nvp( "2", i2 ), i3 );
405 
406     ar( cereal::make_nvp( "4", i4 ),
407         i5 );
408 
409     ar.loadBinaryValue( &x, sizeof(int) );
410 
411     OOJson ii;
412     ar( cereal::make_nvp("oo", ii) );
413     ar( cereal::make_nvp( "2", i2 ) );
414 
415     std::cout << i1 << " " << i2 << " " << i3 << " " << i4 << " " << i5 << std::endl;
416     std::cout << x << std::endl;
417     std::cout << ii.a << " " << ii.b << " " << ii.c.first << " " << ii.c.second << " ";
418     for( auto z : ii.d )
419       std::cout << z << " ";
420     std::cout << std::endl;
421 
422     OOJson oo;
423     ar >> cereal::make_nvp("usingop&", oo );
424     std::cout << oo.a << " " << oo.b << " " << oo.c.first << " " << oo.c.second << " ";
425     for( auto z : oo.d )
426       std::cout << z << " ";
427 
428     int aa, a, b, c;
429     ar & aa & a & b & c;
430     std::cout << aa << " " << a << " " << b << " " << c << std::endl;
431 
432     long double ld;
433     long long ll;
434     unsigned long long ull;
435 
436     ar( CEREAL_NVP(ld),
437         CEREAL_NVP(ll),
438         CEREAL_NVP(ull) );
439 
440     std::cout << (ld  == std::numeric_limits<long double>::max()) << std::endl;
441     std::cout << (ll  == std::numeric_limits<long long>::max()) << std::endl;
442     std::cout << (ull == std::numeric_limits<unsigned long long>::max()) << std::endl;
443   }
444 
445   return 0;
446 }
447