root/trunk/serialization/serializer.d

Revision 5, 6.2 kB (checked in by ChristianK, 5 years ago)

initial import of binary, unversioned serialization

Line 
1 /*******************************************************************************
2
3     Based on work from Tom S (h3r3tic) and Clay Smith
4     
5     License: See <a href="http://www.opensource.org/licenses/zlib-license.php">zlib/libpng license</a>
6
7 *******************************************************************************/
8
9
10 module serialization.serializer;
11
12 import serialization.basicarchive;
13 import serialization.classregister;
14 import std.stream;
15
16 // required for unittests
17 debug import std.stdio;
18 debug import std.gc;
19
20 //TODO-FEATURE: Allow for non-intrusive out-of-class/struct describe functions. How?
21
22 /*******************************************************************************
23
24     Simplifies saving and loading to a file
25
26 *******************************************************************************/
27 class Serializer
28 {
29 public:
30     /// open file with given name and filemode (FileMode.In or FileMode.Out)
31     this(char[] argFileName, FileMode mode)
32     {
33             // serializer doesn't work with filemodes besides these two
34             assert(mode == FileMode.In || mode == FileMode.Out, "Serializer.open only works with FileMode.In and FileMode.Out");
35             if(mode == FileMode.In)
36                 write_or_read = WriteRead.Read;
37             else if(mode == FileMode.Out)
38                 write_or_read = WriteRead.Write;
39            
40             file = new File(argFileName, mode);
41     }
42    
43     ~this()
44     {
45         delete file;
46     }
47    
48     mixin TBasicArchive!(Serializer);
49    
50     /// advances the stream b bytes
51     void advance(ulong b)
52     {
53         file.seek(b, SeekPos.Current);
54     }
55
56 private:
57     /// write data as array of bytes
58     void describe_primitive(T)(inout T x)
59     {
60         if (file.readable)
61         {
62             ubyte* ptr = cast(ubyte*)&x;
63             file.read(ptr[0 .. x.sizeof]);
64         }
65         else
66         {
67             ubyte* ptr = cast(ubyte*)&x;
68             file.write(ptr[0 .. x.sizeof]);
69         }
70     }
71    
72     /// return position in stream (for use with seek only)
73     ulong position()
74     {
75         return file.position();
76     }
77    
78     /// seeks to a position get by a call to position
79     void seek(ulong pos)
80     {
81         file.seek(pos, SeekPos.Set);
82     }
83
84 private:
85     /// filestream
86     File file; 
87 }
88
89
90 // integral types
91 unittest
92 {
93     writefln("Unittest - Serializer - plain data");
94    
95     bool boolv = true, boolvr;
96     byte bytev = 101, bytevr;
97     ushort ushortv = ushort.max, ushortvr;
98     long longv = -32001, longvr;
99     float floatv = 1.123, floatvr;
100     real realv = 1e120, realvr;
101     real real_infv = real.infinity, real_infvr;
102     creal crealv = 5. - 2.3123i, crealvr;
103     char charv = 'A', charvr;
104     dchar dcharv = cast(dchar)0xFFFFFFF0, dcharvr;
105    
106     int i = 42;
107     int* ptr1 = &i, ptr2 = &i, ptr3 = &i;
108     int* ptr1r, ptr2r, ptr3r;
109
110     {
111         Serializer s = new Serializer("integral_type_unittest", FileMode.Out);
112        
113         s.describe(boolv);
114         s.describe(bytev);
115         s.describe(ushortv);
116         s.describe(longv);
117         s.describe(floatv);
118         s.describe(realv);
119         s.describe(real_infv);
120         s.describe(crealv);
121         s.describe(charv);
122         s.describe(dcharv);
123        
124         s.describe(ptr1);
125         s.describe(ptr2);
126         s.describe(ptr3, Serializer.Tracking.Off);
127        
128         delete s;
129     }
130
131     {
132         Serializer s = new Serializer("integral_type_unittest", FileMode.In);
133        
134         s.describe(boolvr);
135         s.describe(bytevr);
136         s.describe(ushortvr);
137         s.describe(longvr);
138         s.describe(floatvr);
139         s.describe(realvr);
140         s.describe(real_infvr);
141         s.describe(crealvr);
142         s.describe(charvr);
143         s.describe(dcharvr);
144    
145         s.describe(ptr1r);
146         s.describe(ptr2r);
147         s.describe(ptr3r, Serializer.Tracking.Off);
148        
149         delete s;
150     }
151    
152     remove("integral_type_unittest");
153    
154     assert(boolv == boolvr);
155     assert(bytev == bytevr);
156     assert(ushortv == ushortvr);
157     assert(longv == longvr);
158     assert(floatv == floatvr);
159     assert(realv == realvr);
160     assert(real_infv == real_infvr);
161     assert(crealv == crealvr);
162     assert(charv == charvr);
163     assert(dcharv == dcharvr);
164     assert(*ptr1r == i);
165     assert(ptr1r == ptr2r);
166     assert(*ptr3r == i);
167     assert(ptr3r != ptr1r);
168
169     writefln("Unittest - Serializer - plain data - done");
170 }
171
172 // arrays and associative arrays
173 unittest
174 {
175     writefln("Unittest - Serializer - arrays and assoc arrays");
176    
177     real[] realv, realvr;
178     realv = [1.0, 2.3, 7];
179     int[float] aav, aavr;
180     aav[0.1] = 1;
181     aav[0.5] = 2;
182
183     {
184         Serializer s = new Serializer("array_aa_type_unittest", FileMode.Out);
185        
186         s.describe(realv);
187         s.describe(aav);
188        
189         delete s;
190     }
191
192     {
193         Serializer s = new Serializer("array_aa_type_unittest", FileMode.In);
194        
195         s.describe(realvr);
196         s.describe(aavr);
197        
198         delete s;
199     }
200    
201     remove("array_aa_type_unittest");
202    
203     assert(realv == realvr);
204     assert(aav.keys == aavr.keys);
205     assert(aav.values == aavr.values);
206
207     writefln("Unittest - Serializer - array and assoc array - done");
208 }
209
210 // these classes are for unittest only, but I can't declare them inside of unitclass scope
211 private
212 {
213     struct S
214     {
215         real a, b;
216         void describe(T)(T ar)
217         {
218             ar.describe(a);
219             ar.describe(b);
220         }
221     }
222    
223     class A
224     {
225         public:
226             int a;
227        
228             void describe(T)(T ar)
229             {
230                 ar.describe(a);
231             }
232     }
233
234     class B : A
235     {
236         public:
237             int b;
238        
239             void describe(T)(T ar)
240             {
241                 super.describe(ar);
242                 ar.describe(b);
243             }
244     }
245    
246     class C
247     {
248         public:
249             this(int a_)
250             {
251                 a = a_;
252             }
253             int a;
254            
255             void describe(T)(T ar)
256             {
257                 ar.describe(a);
258             }
259     }
260 }
261
262 // structs and classes
263 unittest
264 {  
265     writefln("Unittest - Serializer - classes");
266    
267     Serializer.registerClass!(A)();
268     Serializer.registerClass!(B)();
269     Serializer.registerClassConstructor!(C)({ return new C(0); });
270    
271     S sv, svr;
272     sv.a = 3;
273     sv.b = 2;
274    
275     A av = new A, avr;
276     av.a = 99;
277    
278     B bv = new B, bvr;
279     bv.a = 12;
280     bv.b = 99999;
281    
282     A b_in_av = bv, b_in_avr;
283     A b_in_a_notrackv = bv, b_in_a_notrackvr;
284    
285     C cv = new C(3), cvr;
286
287     {
288         Serializer s = new Serializer("class_struct_unittest", FileMode.Out);
289            
290         s.describe(sv);
291         s.describe(av);
292         s.describe(bv);
293         s.describe(b_in_av);
294         s.describe(b_in_a_notrackv, Serializer.Tracking.Off);
295         s.describe(cv);
296        
297         delete s;
298     }
299
300     {
301         Serializer s = new Serializer("class_struct_unittest", FileMode.In);
302        
303         s.describe(svr);
304         s.describe(avr);
305         s.describe(bvr);
306         s.describe(b_in_avr);
307         s.describe(b_in_a_notrackvr, Serializer.Tracking.Off);
308         s.describe(cvr);
309        
310         delete s;
311     }
312    
313     remove("class_struct_unittest");
314    
315     assert(sv == svr);
316     assert(av.a == avr.a);
317     assert(bv.a == bvr.a);
318     assert(bv.b == bvr.b);
319     assert(bv is b_in_av);
320     assert(!(bv is b_in_a_notrackvr));
321     B bvr2 = cast(B) b_in_a_notrackvr;
322     assert(bvr2);
323     assert(bv.a == bvr2.a);
324     assert(bv.b == bvr2.b);
325     assert(cv.a == cvr.a);
326    
327     writefln("Unittest - Serializer - classes - done");
328 }
Note: See TracBrowser for help on using the browser.