comparison orange/serialization/archives/XMLArchive.d @ 26:78e5fef4bbf2 experimental

Third step in refactoring the API. Stating to add unit tests.
author Jacob Carlborg <doob@me.com>
date Tue, 19 Oct 2010 10:22:10 +0200
parents b51e953f79eb
children bffcbc8c392b
comparison
equal deleted inserted replaced
25:b51e953f79eb 26:78e5fef4bbf2
10 import tango.util.Convert : to; 10 import tango.util.Convert : to;
11 11
12 else 12 else
13 import std.conv; 13 import std.conv;
14 14
15 import orange.core._;
15 import orange.serialization.archives._; 16 import orange.serialization.archives._;
17 import orange.serialization.Serializer;
16 import orange.util._; 18 import orange.util._;
17 import orange.xml.XMLDocument; 19 import orange.xml.XMLDocument;
18 20
19 final class XMLArchive (U = char) : Archive!(U) 21 final class XMLArchive (U = char) : Archive!(U)
20 { 22 {
21 private alias IArchive.IDataType IDataType; 23 private alias IArchive.Id Id;
22 24
23 private struct Tags 25 private struct Tags
24 { 26 {
25 static const DataType structTag = "struct"; 27 static const Data structTag = "struct";
26 static const DataType dataTag = "data"; 28 static const Data dataTag = "data";
27 static const DataType archiveTag = "archive"; 29 static const Data archiveTag = "archive";
28 static const DataType arrayTag = "array"; 30 static const Data arrayTag = "array";
29 static const DataType objectTag = "object"; 31 static const Data objectTag = "object";
30 static const DataType baseTag = "base"; 32 static const Data baseTag = "base";
31 static const DataType stringTag = "string"; 33 static const Data stringTag = "string";
32 static const DataType referenceTag = "reference"; 34 static const Data referenceTag = "reference";
33 static const DataType pointerTag = "pointer"; 35 static const Data pointerTag = "pointer";
34 static const DataType associativeArrayTag = "associativeArray"; 36 static const Data associativeArrayTag = "associativeArray";
35 static const DataType typedefTag = "typedef"; 37 static const Data typedefTag = "typedef";
36 static const DataType nullTag = "null"; 38 static const Data nullTag = "null";
37 static const DataType enumTag = "enum"; 39 static const Data enumTag = "enum";
38 static const DataType sliceTag = "slice"; 40 static const Data sliceTag = "slice";
41 static const Data elementTag = "element";
42 static const Data keyTag = "key";
43 static const Data valueTag = "value";
39 } 44 }
40 45
41 private struct Attributes 46 private struct Attributes
42 { 47 {
43 static const DataType typeAttribute = "type"; 48 static const Data typeAttribute = "type";
44 static const DataType versionAttribute = "version"; 49 static const Data versionAttribute = "version";
45 static const DataType lengthAttribute = "length"; 50 static const Data lengthAttribute = "length";
46 static const DataType keyAttribute = "key"; 51 static const Data keyAttribute = "key";
47 static const DataType runtimeTypeAttribute = "runtimeType"; 52 static const Data runtimeTypeAttribute = "runtimeType";
48 static const DataType idAttribute = "id"; 53 static const Data idAttribute = "id";
49 static const DataType keyTypeAttribute = "keyType"; 54 static const Data keyTypeAttribute = "keyType";
50 static const DataType valueTypeAttribute = "valueType"; 55 static const Data valueTypeAttribute = "valueType";
51 static const DataType offsetAttribute = "offset"; 56 static const Data offsetAttribute = "offset";
57 static const Data baseTypeAttribute = "baseType";
52 } 58 }
53 59
54 private struct ArrayNode 60 private struct ArrayNode
55 { 61 {
56 XMLDocument!(U).Node parent; 62 XMLDocument!(U).Node parent;
57 XMLDocument!(U).Node node; 63 XMLDocument!(U).Node node;
58 DataType id; 64 Id id;
59 DataType key; 65 string key;
60 } 66 }
61 67
62 private 68 private
63 { 69 {
64 DataType archiveType = "org.dsource.orange.xml"; 70 Data archiveType = "org.dsource.orange.xml";
65 DataType archiveVersion = "0.1"; 71 Data archiveVersion = "1.0.0";
66 72
67 XMLDocument!(U) doc; 73 XMLDocument!(U) doc;
68 doc.Node lastElement; 74 doc.Node lastElement;
69 75
70 bool hasBegunArchiving; 76 bool hasBegunArchiving;
71 bool hasBegunUnarchiving; 77 bool hasBegunUnarchiving;
72 78
73 ArrayNode[Array] arraysToBeArchived; 79 ArrayNode[Id] archivedArrays;
74 void[][DataType] unarchivedSlices; 80 void[][Data] unarchivedSlices;
75 } 81 }
76 82
77 this (ErrorCallback errorCallback = null) 83 this (ErrorCallback errorCallback = null)
78 { 84 {
79 super(errorCallback); 85 super(errorCallback);
92 98
93 hasBegunArchiving = true; 99 hasBegunArchiving = true;
94 } 100 }
95 } 101 }
96 102
97 public void beginUnarchiving (IDataType untypedData) 103 public void beginUnarchiving (UntypedData untypedData)
98 { 104 {
99 auto data = cast(DataType) untypedData; 105 auto data = cast(Data) untypedData;
100 106
101 if (!hasBegunUnarchiving) 107 if (!hasBegunUnarchiving)
102 { 108 {
103 doc.parse(data); 109 doc.parse(data);
104 hasBegunUnarchiving = true; 110 hasBegunUnarchiving = true;
110 116
111 else 117 else
112 { 118 {
113 if (errorCallback) 119 if (errorCallback)
114 { 120 {
121 auto dataTag = to!(string)(Tags.dataTag);
122
115 if (set.nodes.length == 0) 123 if (set.nodes.length == 0)
116 errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `The "` ~ to!(string)(Tags.dataTag) ~ `" tag could not be found.`, __FILE__, __LINE__), [Tags.dataTag]); 124 errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `The "` ~ to!(string)(Tags.dataTag) ~ `" tag could not be found.`, __FILE__, __LINE__), [dataTag]);
117 125
118 else 126 else
119 errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `There were more than one "` ~ to!(string)(Tags.dataTag) ~ `" tag.`, __FILE__, __LINE__), [Tags.dataTag]); 127 errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `There were more than one "` ~ to!(string)(Tags.dataTag) ~ `" tag.`, __FILE__, __LINE__), [dataTag]);
120 } 128 }
121 } 129 }
122 } 130 }
123 } 131 }
124 132
125 IDataType data () 133 UntypedData untypedData ()
126 { 134 {
127 return doc.toString(); 135 return doc.toString();
128 } 136 }
129 137
130 void postProcess () 138 Data data ()
131 { 139 {
132 bool foundSlice = true; 140 return doc.toString;
133
134 foreach (slice, sliceNode ; arraysToBeArchived)
135 {
136 foreach (array, arrayNode ; arraysToBeArchived)
137 {
138 if (slice.isSliceOf(array) && slice != array)
139 {
140 sliceNode.parent.element(Tags.sliceTag, arrayNode.id)
141 .attribute(Attributes.keyAttribute, sliceNode.key)
142 .attribute(Attributes.offsetAttribute, toDataType((slice.ptr - array.ptr) / slice.elementSize))
143 .attribute(Attributes.lengthAttribute, toDataType(slice.length));
144
145 foundSlice = true;
146 break;
147 }
148
149 else
150 foundSlice = false;
151 }
152
153 if (!foundSlice)
154 sliceNode.parent.attach(sliceNode.node);
155 }
156 } 141 }
157 142
158 void reset () 143 void reset ()
159 { 144 {
160 hasBegunArchiving = false; 145 hasBegunArchiving = false;
161 hasBegunUnarchiving = false; 146 hasBegunUnarchiving = false;
162 doc.reset; 147 doc.reset;
163 } 148 }
164 149
165 void archiveArray (Array array, string type, string key, size_t id, void delegate () dg) 150 void archiveArray (Array array, string type, string key, Id id, void delegate () dg)
166 { 151 {
167 internalArchiveArray(type, array, key, id, Tags.arrayTag); 152 restore(lastElement) in {
168 dg(); 153 internalArchiveArray(array, type, key, id, Tags.arrayTag);
169 } 154 dg();
170 155 };
171 private void internalArchiveArray(string type, Array array, string key, size_t id, DataType tag, DataType content = null) 156 }
157
158 private void internalArchiveArray(Array array, string type, string key, Id id, Data tag, Data content = null)
172 { 159 {
173 auto parent = lastElement; 160 auto parent = lastElement;
174 161
175 if (array.length == 0) 162 if (array.length == 0)
176 lastElement = lastElement.element(tag); 163 lastElement = lastElement.element(tag);
177 164
178 else 165 else
179 lastElement = doc.createNode(tag, content); 166 lastElement = doc.createNode(tag, content);
180 167
181 lastElement.attribute(Attributes.typeAttribute, toDataType(type)) 168 lastElement.attribute(Attributes.typeAttribute, toData(type))
182 .attribute(Attributes.lengthAttribute, toDataType(array.length)) 169 .attribute(Attributes.lengthAttribute, toData(array.length))
183 .attribute(Attributes.keyAttribute, toDataType(key)) 170 .attribute(Attributes.keyAttribute, toData(key))
184 .attribute(Attributes.idAttribute, toDataType(id)); 171 .attribute(Attributes.idAttribute, toData(id));
185 } 172
186 173 addArchivedArray(id, parent, lastElement, key);
187 void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id, void delegate () dg) 174 }
188 { 175
189 lastElement = lastElement.element(Tags.associativeArrayTag) 176 void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, Id id, void delegate () dg)
190 .attribute(Attributes.keyTypeAttribute, toDataType(keyType)) 177 {
191 .attribute(Attributes.valueTypeAttribute, toDataType(valueType)) 178 restore(lastElement) in {
192 .attribute(Attributes.lengthAttribute, toDataType(length)) 179 lastElement = lastElement.element(Tags.associativeArrayTag)
193 .attribute(Attributes.keyAttribute, key); 180 .attribute(Attributes.keyTypeAttribute, toData(keyType))
194 181 .attribute(Attributes.valueTypeAttribute, toData(valueType))
195 dg(); 182 .attribute(Attributes.lengthAttribute, toData(length))
196 } 183 .attribute(Attributes.keyAttribute, key);
197 184
198 void archiveEnum (bool value, string key, size_t id) 185 dg();
199 { 186 };
200 internalArchiveEnum(value, key, id); 187 }
201 } 188
202 189 void archiveAssociativeArrayKey (string key, void delegate () dg)
203 void archiveEnum (byte value, string key, size_t id) 190 {
204 { 191 internalArchiveAAKeyValue(key, Tags.keyTag, dg);
205 internalArchiveEnum(value, key, id); 192 }
206 } 193
207 194 void archiveAssociativeArrayValue (string key, void delegate () dg)
208 void archiveEnum (char value, string key, size_t id) 195 {
209 { 196 internalArchiveAAKeyValue(key, Tags.valueTag, dg);
210 internalArchiveEnum(value, key, id); 197 }
211 } 198
212 199 private void internalArchiveAAKeyValue (string key, Data tag, void delegate () dg)
213 void archiveEnum (dchar value, string key, size_t id) 200 {
214 { 201 restore(lastElement) in {
215 internalArchiveEnum(value, key, id); 202 lastElement = lastElement.element(tag)
216 } 203 .attribute(Attributes.keyAttribute, toData(key));
217 204
218 void archiveEnum (int value, string key, size_t id) 205 dg();
219 { 206 };
220 internalArchiveEnum(value, key, id); 207 }
221 } 208
222 209 void archiveEnum (bool value, string type, string key, Id id)
223 void archiveEnum (long value, string key, size_t id) 210 {
224 { 211 internalArchiveEnum(value, type, key, id);
225 internalArchiveEnum(value, key, id); 212 }
226 } 213
227 214 void archiveEnum (byte value, string type, string key, Id id)
228 void archiveEnum (short value, string key, size_t id) 215 {
229 { 216 internalArchiveEnum(value, type, key, id);
230 internalArchiveEnum(value, key, id); 217 }
231 } 218
232 219 void archiveEnum (char value, string type, string key, Id id)
233 void archiveEnum (ubyte value, string key, size_t id) 220 {
234 { 221 internalArchiveEnum(value, type, key, id);
235 internalArchiveEnum(value, key, id); 222 }
236 } 223
237 224 void archiveEnum (dchar value, string type, string key, Id id)
238 void archiveEnum (uint value, string key, size_t id) 225 {
239 { 226 internalArchiveEnum(value, type, key, id);
240 internalArchiveEnum(value, key, id); 227 }
241 } 228
242 229 void archiveEnum (int value, string type, string key, Id id)
243 void archiveEnum (ulong value, string key, size_t id) 230 {
244 { 231 internalArchiveEnum(value, type, key, id);
245 internalArchiveEnum(value, key, id); 232 }
246 } 233
247 234 void archiveEnum (long value, string type, string key, Id id)
248 void archiveEnum (ushort value, string key, size_t id) 235 {
249 { 236 internalArchiveEnum(value, type, key, id);
250 internalArchiveEnum(value, key, id); 237 }
251 } 238
252 239 void archiveEnum (short value, string type, string key, Id id)
253 void archiveEnum (wchar value, string key, size_t id) 240 {
254 { 241 internalArchiveEnum(value, type, key, id);
255 internalArchiveEnum(value, key, id); 242 }
256 } 243
257 244 void archiveEnum (ubyte value, string type, string key, Id id)
258 private void internalArchiveEnum (T) (T value, string key, size_t id) 245 {
259 { 246 internalArchiveEnum(value, type, key, id);
260 lastElement.element(Tags.enumTag, toDataType(value)) 247 }
261 .attribute(Attributes.typeAttribute, toDataType(T.stringof)) 248
262 .attribute(Attributes.keyAttribute, toDataType(key)); 249 void archiveEnum (uint value, string type, string key, Id id)
263 } 250 {
264 251 internalArchiveEnum(value, type, key, id);
265 void archiveBaseClass (string type, string key, size_t id) 252 }
266 { 253
267 lastElement = lastElement.element(Tags.baseTag) 254 void archiveEnum (ulong value, string type, string key, Id id)
268 .attribute(Attributes.typeAttribute, toDataType(type)) 255 {
269 .attribute(Attributes.keyAttribute, toDataType(key)); 256 internalArchiveEnum(value, type, key, id);
257 }
258
259 void archiveEnum (ushort value, string type, string key, Id id)
260 {
261 internalArchiveEnum(value, type, key, id);
262 }
263
264 void archiveEnum (wchar value, string type, string key, Id id)
265 {
266 internalArchiveEnum(value, type, key, id);
267 }
268
269 private void internalArchiveEnum (T) (T value, string type, string key, Id id)
270 {
271 lastElement.element(Tags.enumTag, toData(value))
272 .attribute(Attributes.typeAttribute, toData(type))
273 .attribute(Attributes.baseTypeAttribute, toData(T.stringof))
274 .attribute(Attributes.keyAttribute, toData(key));
275 }
276
277 void archiveBaseClass (string type, string key, Id id)
278 {
279 restore(lastElement) in {
280 lastElement = lastElement.element(Tags.baseTag)
281 .attribute(Attributes.typeAttribute, toData(type))
282 .attribute(Attributes.keyAttribute, toData(key));
283 };
270 } 284 }
271 285
272 void archiveNull (string type, string key) 286 void archiveNull (string type, string key)
273 { 287 {
274 lastElement.element(Tags.nullTag) 288 lastElement.element(Tags.nullTag)
275 .attribute(Attributes.typeAttribute, toDataType(type)) 289 .attribute(Attributes.typeAttribute, toData(type))
276 .attribute(Attributes.keyAttribute, toDataType(key)); 290 .attribute(Attributes.keyAttribute, toData(key));
277 } 291 }
278 292
279 void archiveObject (string runtimeType, string type, string key, size_t id, void delegate () dg) 293 void archiveObject (string runtimeType, string type, string key, Id id, void delegate () dg)
280 { 294 {
281 lastElement = lastElement.element(Tags.objectTag) 295 restore(lastElement) in {
282 .attribute(Attributes.runtimeTypeAttribute, toDataType(runtimeType)) 296 lastElement = lastElement.element(Tags.objectTag)
283 .attribute(Attributes.typeAttribute, toDataType(type)) 297 .attribute(Attributes.runtimeTypeAttribute, toData(runtimeType))
284 .attribute(Attributes.keyAttribute, toDataType(key)) 298 .attribute(Attributes.typeAttribute, toData(type))
285 .attribute(Attributes.idAttribute, toDataType(id)); 299 .attribute(Attributes.keyAttribute, toData(key))
286 300 .attribute(Attributes.idAttribute, toData(id));
287 dg(); 301
288 } 302 dg();
289 303 };
290 void archivePointer (string key, size_t id) 304 }
305
306 void archivePointer (string key, Id id, void delegate () dg)
307 {
308 restore(lastElement) in {
309 lastElement = lastElement.element(Tags.pointerTag)
310 .attribute(Attributes.keyAttribute, toData(key))
311 .attribute(Attributes.idAttribute, toData(id));
312
313 dg();
314 };
315 }
316
317 void archiveReference (string key, Id id)
318 {
319 lastElement.element(Tags.referenceTag, toData(id))
320 .attribute(Attributes.keyAttribute, toData(key));
321 }
322
323 void archiveSlice (Slice slice, Id sliceId, Id arrayId)
324 {
325 if (auto sliceNode = getArchivedArray(sliceId))
326 {
327 if (auto arrayNode = getArchivedArray(arrayId))
328 {
329 sliceNode.parent.element(Tags.sliceTag, toData(arrayNode.id))
330 .attribute(Attributes.keyAttribute, toData(sliceNode.key))
331 .attribute(Attributes.offsetAttribute, toData(slice.offset))
332 .attribute(Attributes.lengthAttribute, toData(slice.length));
333 }
334 }
335 }
336
337 void archiveStruct (string type, string key, Id id, void delegate () dg)
338 {
339 restore(lastElement) in {
340 lastElement = lastElement.element(Tags.structTag)
341 .attribute(Attributes.typeAttribute, toData(type))
342 .attribute(Attributes.keyAttribute, toData(key));
343
344 dg();
345 };
346 }
347
348 void archiveTypedef (string type, string key, Id id, void delegate () dg)
349 {
350 restore(lastElement) in {
351 lastElement = lastElement.element(Tags.typedefTag)
352 .attribute(Attributes.typeAttribute, toData(type))
353 .attribute(Attributes.keyAttribute, toData(key));
354
355 dg();
356 };
357 }
358
359 void archive (string value, string key, Id id)
360 {
361 archiveString(value, key, id);
362 }
363
364 void archive (wstring value, string key, Id id)
365 {
366 archiveString(value, key, id);
367 }
368
369 void archive (dstring value, string key, Id id)
370 {
371 archiveString(value, key, id);
372 }
373
374 private void archiveString (T) (T value, string key, Id id)
375 {
376 restore(lastElement) in {
377 alias ElementTypeOfArray!(T) ElementType;
378 auto array = Array(value.ptr, value.length, ElementType.sizeof);
379
380 internalArchiveArray(array, ElementType.stringof, key, id, Tags.stringTag, toData(value));
381 };
382 }
383
384 void archive (bool value, string key, Id id)
385 {
386 archivePrimitive(value, key);
387 }
388
389 void archive (byte value, string key, Id id)
390 {
391 archivePrimitive(value, key);
392 }
393
394 // currently not suppported by to!()
395 /*void archive (cdouble value, string key, Id id)
396 {
397 archivePrimitive(value, key);
398 }*/
399
400 //currently not implemented but a reserved keyword
401 /*void archive (cent value, string key, Id id)
402 {
403 archivePrimitive(value, key);
404 }*/
405
406 //currently not suppported by to!()
407 /*void archive (cfloat value, string key, Id id)
408 {
409 archivePrimitive(value, key);
410 }*/
411
412 void archive (char value, string key, Id id)
413 {
414 archivePrimitive(value, key);
415 }
416
417 //currently not suppported by to!()
418 /*void archive (creal value, string key, Id id)
419 {
420 archivePrimitive(value, key);
421 }*/
422
423 void archive (dchar value, string key, Id id)
424 {
425 archivePrimitive(value, key);
426 }
427
428 void archive (double value, string key, Id id)
429 {
430 archivePrimitive(value, key);
431 }
432
433 void archive (float value, string key, Id id)
434 {
435 archivePrimitive(value, key);
436 }
437
438 //currently not suppported by to!()
439 /*void archive (idouble value, string key, Id id)
440 {
441 archivePrimitive(value, key);
442 }*/
443
444 //currently not suppported by to!()
445 /*void archive (ifloat value, string key, Id id)
446 {
447 archivePrimitive(value, key);
448 }*/
449
450 void archive (int value, string key, Id id)
451 {
452 archivePrimitive(value, key);
453 }
454
455 //currently not suppported by to!()
456 /*void archive (ireal value, string key, Id id)
457 {
458 archivePrimitive(value, key);
459 }*/
460
461 void archive (long value, string key, Id id)
462 {
463 archivePrimitive(value, key);
464 }
465
466 void archive (real value, string key, Id id)
467 {
468 archivePrimitive(value, key);
469 }
470
471 void archive (short value, string key, Id id)
472 {
473 archivePrimitive(value, key);
474 }
475
476 void archive (ubyte value, string key, Id id)
477 {
478 archivePrimitive(value, key);
479 }
480
481 //currently not implemented but a reserved keyword
482 /*void archive (ucent value, string key, Id id)
483 {
484 archivePrimitive(value, key);
485 }*/
486
487 void archive (uint value, string key, Id id)
488 {
489 archivePrimitive(value, key);
490 }
491
492 void archive (ulong value, string key, Id id)
493 {
494 archivePrimitive(value, key);
495 }
496
497 void archive (ushort value, string key, Id id)
498 {
499 archivePrimitive(value, key);
500 }
501
502 void archive (wchar value, string key, Id id)
503 {
504 archivePrimitive(value, key);
505 }
506
507 private void archivePrimitive (T) (T value, string key)
508 {
509 lastElement.element(toData(T.stringof), toData(value))
510 .attribute(Attributes.keyAttribute, toData(key));
511 }
512
513 Id unarchiveArray (string key, void delegate (size_t) dg)
514 {
515 return restore!(Id)(lastElement) in {
516 auto element = getElement(Tags.arrayTag, key);
517
518 if (!element.isValid)
519 return Id.max;
520
521 lastElement = element;
522 auto len = getValueOfAttribute(Attributes.lengthAttribute);
523
524 if (!len)
525 return Id.max;
526
527 auto length = fromData!(size_t)(len);
528 auto id = getValueOfAttribute(Attributes.idAttribute);
529
530 if (!id)
531 return Id.max;
532
533 dg(length);
534
535 return id.toId();
536 };
537 }
538
539 void unarchiveArray (Id id, void delegate (size_t) dg)
540 {
541 restore(lastElement) in {
542 auto element = getElement(Tags.arrayTag, to!(string)(id), Attributes.idAttribute);
543
544 if (!element.isValid)
545 return;
546
547 lastElement = element;
548 auto len = getValueOfAttribute(Attributes.lengthAttribute);
549
550 if (!len)
551 return;
552
553 auto length = fromData!(size_t)(len);
554 auto stringId = getValueOfAttribute(Attributes.idAttribute);
555
556 if (!stringId)
557 return;
558
559 dg(length);
560 };
561 }
562
563 void unarchiveAssociativeArray (string key, void delegate (size_t length) dg)
564 {
565 restore(lastElement) in {
566 auto element = getElement(Tags.associativeArrayTag, key);
567
568 if (!element.isValid)
569 return;
570
571 lastElement = element;
572 auto len = getValueOfAttribute(Attributes.lengthAttribute);
573
574 if (!len)
575 return;
576
577 auto length = fromData!(size_t)(len);
578
579 dg(length);
580 };
581 }
582
583 void unarchiveAssociativeArrayKey (string key, void delegate () dg)
584 {
585 internalUnarchiveAAKeyValue(key, Tags.keyTag, dg);
586 }
587
588 void unarchiveAssociativeArrayValue (string key, void delegate () dg)
589 {
590 internalUnarchiveAAKeyValue(key, Tags.valueTag, dg);
591 }
592
593 private void internalUnarchiveAAKeyValue (string key, Data tag, void delegate () dg)
594 {
595 restore(lastElement) in {
596 auto element = getElement(tag, key);
597
598 if (!element.isValid)
599 return;
600
601 lastElement = element;
602
603 dg();
604 };
605 }
606
607 bool unarchiveEnumBool (string key)
608 {
609 return unarchiveEnum!(bool)(key);
610 }
611
612 byte unarchiveEnumByte (string key)
613 {
614 return unarchiveEnum!(byte)(key);
615 }
616
617 char unarchiveEnumChar (string key)
618 {
619 return unarchiveEnum!(char)(key);
620 }
621
622 dchar unarchiveEnumDchar (string key)
623 {
624 return unarchiveEnum!(dchar)(key);
625 }
626
627 int unarchiveEnumInt (string key)
628 {
629 return unarchiveEnum!(int)(key);
630 }
631
632 long unarchiveEnumLong (string key)
633 {
634 return unarchiveEnum!(long)(key);
635 }
636
637 short unarchiveEnumShort (string key)
638 {
639 return unarchiveEnum!(short)(key);
640 }
641
642 ubyte unarchiveEnumUbyte (string key)
643 {
644 return unarchiveEnum!(ubyte)(key);
645 }
646
647 uint unarchiveEnumUint (string key)
648 {
649 return unarchiveEnum!(uint)(key);
650 }
651
652 ulong unarchiveEnumUlong (string key)
653 {
654 return unarchiveEnum!(ulong)(key);
655 }
656
657 ushort unarchiveEnumUshort (string key)
658 {
659 return unarchiveEnum!(ushort)(key);
660 }
661
662 wchar unarchiveEnumWchar (string key)
663 {
664 return unarchiveEnum!(wchar)(key);
665 }
666
667 private T unarchiveEnum (T) (string key)
668 {
669 auto element = getElement(Tags.enumTag, key);
670
671 if (!element.isValid)
672 return T.init;
673
674 return fromData!(T)(element.value);
675 }
676
677 void unarchiveObject (string key, out Id id, out Object result, void delegate () dg)
678 {
679 restore(lastElement) in {
680 auto tmp = getElement(Tags.objectTag, key, Attributes.keyAttribute, false);
681
682 if (!tmp.isValid)
683 {
684 lastElement = getElement(Tags.nullTag, key);
685 return;
686 }
687
688 lastElement = tmp;
689
690 auto runtimeType = getValueOfAttribute(Attributes.runtimeTypeAttribute);
691
692 if (!runtimeType)
693 return;
694
695 auto name = fromData!(string)(runtimeType);
696 auto stringId = getValueOfAttribute(Attributes.idAttribute);
697
698 if (!stringId)
699 return;
700
701 id = stringId.toId();
702 result = newInstance(name);
703 dg();
704 };
705 }
706
707 Id unarchivePointer (string key, void delegate () dg)
708 {
709 return restore!(Id)(lastElement) in {
710 auto tmp = getElement(Tags.pointerTag, key, Attributes.keyAttribute, false);
711
712 if (!tmp.isValid)
713 {
714 lastElement = getElement(Tags.nullTag, key);
715 return Id.max;
716 }
717
718 lastElement = tmp;
719 auto stringId = getValueOfAttribute(Attributes.idAttribute);
720
721 if (!stringId)
722 return Id.max;
723
724 dg();
725
726 return stringId.toId();
727 };
728 }
729
730 Id unarchiveReference (string key)
731 {
732 auto element = getElement(Tags.referenceTag, key, Attributes.keyAttribute, false);
733
734 if (element.isValid)
735 return toId(element.value);
736
737 return Id.max;
738 }
739
740 Slice unarchiveSlice (string key)
741 {
742 auto element = getElement(Tags.sliceTag, key, Attributes.keyAttribute, false);
743
744 if (element.isValid)
745 {
746 auto length = fromData!(size_t)(getValueOfAttribute(Attributes.lengthAttribute, element));
747 auto offset = fromData!(size_t)(getValueOfAttribute(Attributes.offsetAttribute, element));
748 auto id = toId(element.value);
749
750 return Slice(length, offset, id);
751 }
752
753 return Slice.init;
754 }
755
756 void unarchiveStruct (string key, void delegate () dg)
757 {
758 restore(lastElement) in {
759 auto element = getElement(Tags.structTag, key);
760
761 if (!element.isValid)
762 return;
763
764 lastElement = element;
765 dg();
766 };
767 }
768
769 private T unarchiveTypeDef (T) (DataType key)
770 {
771 auto element = getElement(Tags.typedefTag, key);
772
773 if (element.isValid)
774 lastElement = element;
775
776 return T.init;
777 }
778
779 void unarchiveTypedef (string key, void delegate () dg)
780 {
781 restore(lastElement) in {
782 auto element = getElement(Tags.typedefTag, key);
783
784 if (!element.isValid)
785 return;
786
787 lastElement = element;
788 dg();
789 };
790 }
791
792 string unarchiveString (string key, out Id id)
793 {
794 return internalUnarchiveString!(string)(key, id);
795 }
796
797 wstring unarchiveWstring (string key, out Id id)
798 {
799 return internalUnarchiveString!(wstring)(key, id);
800 }
801
802 dstring unarchiveDstring (string key, out Id id)
803 {
804 return internalUnarchiveString!(dstring)(key, id);
805 }
806
807 private T internalUnarchiveString (T) (string key, out Id id)
808 {
809 auto element = getElement(Tags.stringTag, key);
810
811 if (!element.isValid)
812 return T.init;
813
814 auto value = fromData!(T)(element.value);
815 auto stringId = getValueOfAttribute(Attributes.idAttribute, element);
816
817 if (!stringId)
818 return T.init;
819
820 id = stringId.toId();
821 return value;
822 }
823
824 string unarchiveString (Id id)
825 {
826 return internalUnarchiveString!(string)(id);
827 }
828
829 wstring unarchiveWstring (Id id)
830 {
831 return internalUnarchiveString!(wstring)(id);
832 }
833
834 dstring unarchiveDstring (Id id)
835 {
836 return internalUnarchiveString!(dstring)(id);
837 }
838
839 private T internalUnarchiveString (T) (Id id)
840 {
841 auto element = getElement(Tags.stringTag, to!(string)(id), Attributes.idAttribute);
842
843 if (!element.isValid)
844 return T.init;
845
846 return fromData!(T)(element.value);
847 }
848
849 bool unarchiveBool (string key)
850 {
851 return unarchivePrimitive!(bool)(key);
852 }
853
854 byte unarchiveByte (string key)
855 {
856 return unarchivePrimitive!(byte)(key);
857 }
858
859 //currently not suppported by to!()
860 /*cdouble unarchiveCdouble (string key)
861 {
862 return unarchivePrimitive!(cdouble)(key);
863 }*/
864
865 //currently not implemented but a reserved keyword
866 /*cent unarchiveCent (string key)
867 {
868 return unarchivePrimitive!(cent)(key);
869 }*/
870
871 // currently not suppported by to!()
872 /*cfloat unarchiveCfloat (string key)
873 {
874 return unarchivePrimitive!(cfloat)(key);
875 }*/
876
877 char unarchiveChar (string key)
878 {
879 return unarchivePrimitive!(char)(key);
880 }
881
882 //currently not implemented but a reserved keyword
883 /*creal unarchiveCreal (string key)
884 {
885 return unarchivePrimitive!(creal)(key);
886 }*/
887
888 dchar unarchiveDchar (string key)
889 {
890 return unarchivePrimitive!(dchar)(key);
891 }
892
893 double unarchiveDouble (string key)
894 {
895 return unarchivePrimitive!(double)(key);
896 }
897
898 float unarchiveFloat (string key)
899 {
900 return unarchivePrimitive!(float)(key);
901 }
902
903 //currently not suppported by to!()
904 /*idouble unarchiveIdouble (string key)
905 {
906 return unarchivePrimitive!(idouble)(key);
907 }*/
908
909 // currently not suppported by to!()*/
910 /*ifloat unarchiveIfloat (string key)
911 {
912 return unarchivePrimitive!(ifloat)(key);
913 }*/
914
915 int unarchiveInt (string key)
916 {
917 return unarchivePrimitive!(int)(key);
918 }
919
920 // currently not suppported by to!()
921 /*ireal unarchiveIreal (string key)
922 {
923 return unarchivePrimitive!(ireal)(key);
924 }*/
925
926 long unarchiveLong (string key)
927 {
928 return unarchivePrimitive!(long)(key);
929 }
930
931 real unarchiveReal (string key)
932 {
933 return unarchivePrimitive!(real)(key);
934 }
935
936 short unarchiveShort (string key)
937 {
938 return unarchivePrimitive!(short)(key);
939 }
940
941 ubyte unarchiveUbyte (string key)
942 {
943 return unarchivePrimitive!(ubyte)(key);
944 }
945
946 // currently not implemented but a reserved keyword
947 /*ucent unarchiveCcent (string key)
948 {
949 return unarchivePrimitive!(ucent)(key);
950 }*/
951
952 uint unarchiveUint (string key)
953 {
954 return unarchivePrimitive!(uint)(key);
955 }
956
957 ulong unarchiveUlong (string key)
958 {
959 return unarchivePrimitive!(ulong)(key);
960 }
961
962 ushort unarchiveUshort (string key)
963 {
964 return unarchivePrimitive!(ushort)(key);
965 }
966
967 wchar unarchiveWchar (string key)
968 {
969 return unarchivePrimitive!(wchar)(key);
970 }
971
972 T unarchivePrimitive (T) (string key)
973 {
974 auto element = getElement(toData(T.stringof), key);
975
976 if (!element.isValid)
977 return T.init;
978
979 return fromData!(T)(element.value);
980 }
981
982 void postProcessArray (Id id)
983 {
984 if (auto array = getArchivedArray(id))
985 array.parent.attach(array.node);
986 }
987
988 private void addArchivedArray (Id id, doc.Node parent, doc.Node element, string key)
989 {
990 archivedArrays[id] = ArrayNode(parent, element, id, key);
991 }
992
993 private ArrayNode* getArchivedArray (Id id)
994 {
995 if (auto array = id in archivedArrays)
996 return array;
997
998 errorCallback(new ArchiveException(`Could not continue archiving due to no array with the Id "` ~ to!(string)(id) ~ `" was found.`, __FILE__, __LINE__), [to!(string)(id)]);
999
1000 return null;
1001 }
1002
1003 private doc.Node getElement (Data tag, string k, Data attribute = Attributes.keyAttribute, bool throwOnError = true)
291 { 1004 {
292 lastElement = lastElement.element(Tags.pointerTag) 1005 auto key = toData(k);
293 .attribute(Attributes.keyAttribute, toDataType(key)) 1006
294 .attribute(Attributes.idAttribute, toDataType(id)); 1007 auto set = lastElement.query[tag].attribute((doc.Node node) {
295 } 1008 if (node.name == attribute && node.value == key)
296 1009 return true;
297 void archiveReference (string key, size_t id) 1010
298 { 1011 return false;
299 lastElement.element(Tags.referenceTag, toDataType(id)) 1012 });
300 .attribute(Attributes.keyAttribute, toDataType(key)); 1013
301 } 1014 if (set.nodes.length == 1)
302 1015 return set.nodes[0].parent;
303 /*void archiveSlice (Array array, Array slice) 1016
304 { 1017 else
305 sliceNode.parent.element(Tags.sliceTag, arrayNode.id) 1018 {
306 .attribute(Attributes.keyAttribute, sliceNode.key) 1019 if (throwOnError && errorCallback)
307 .attribute(Attributes.offsetAttribute, toDataType((slice.ptr - array.ptr) / slice.elementSize)) 1020 {
308 .attribute(Attributes.lengthAttribute, toDataType(slice.length)); 1021 if (set.nodes.length == 0)
309 }*/ 1022 errorCallback(new ArchiveException(`Could not find an element "` ~ to!(string)(tag) ~ `" with the attribute "` ~ to!(string)(Attributes.keyAttribute) ~ `" with the value "` ~ to!(string)(key) ~ `".`, __FILE__, __LINE__), [tag, Attributes.keyAttribute, key]);
310 1023
311 void archiveStruct (string type, string key, size_t id, void delegate () dg) 1024 else
312 { 1025 errorCallback(new ArchiveException(`Could not unarchive the value with the key "` ~ to!(string)(key) ~ `" due to malformed data.`, __FILE__, __LINE__), [tag, Attributes.keyAttribute, key]);
313 lastElement = lastElement.element(Tags.structTag) 1026 }
314 .attribute(Attributes.typeAttribute, toDataType(type)) 1027
315 .attribute(Attributes.keyAttribute, toDataType(key)); 1028 return doc.Node.invalid;
316 1029 }
317 dg(); 1030 }
318 } 1031
319 1032 private Data getValueOfAttribute (Data attribute, doc.Node element = doc.Node.invalid)
320 void archiveTypedef (string type, string key, size_t id, void delegate () dg) 1033 {
321 { 1034 if (!element.isValid)
322 lastElement = lastElement.element(Tags.typedefTag) 1035 element = lastElement;
323 .attribute(Attributes.typeAttribute, toDataType(type)) 1036
324 .attribute(Attributes.keyAttribute, toDataType(key)); 1037 auto set = element.query.attribute(attribute);
325 1038
326 dg(); 1039 if (set.nodes.length == 1)
327 } 1040 return set.nodes[0].value;
328 1041
329 void archive (string value, string key, size_t id) 1042 else
330 { 1043 {
331 archiveString(value, key, id); 1044 if (errorCallback)
332 } 1045 {
333 1046 if (set.nodes.length == 0)
334 void archive (wstring value, string key, size_t id) 1047 errorCallback(new ArchiveException(`Could not find the attribute "` ~ to!(string)(attribute) ~ `".`, __FILE__, __LINE__), [attribute]);
335 { 1048
336 archiveString(value, key, id); 1049 else
337 } 1050 errorCallback(new ArchiveException(`Could not unarchive the value of the attribute "` ~ to!(string)(attribute) ~ `" due to malformed data.`, __FILE__, __LINE__), [attribute]);
338 1051 }
339 void archive (dstring value, string key, size_t id) 1052 }
340 { 1053
341 archiveString(value, key, id); 1054 return null;
342 }
343
344 private void archiveString (T) (T value, string key, size_t id)
345 {
346 alias BaseTypeOfArray!(T) ArrayBaseType;
347 auto array = Array(value.ptr, value.length, ArrayBaseType.sizeof);
348
349 internalArchiveArray(ArrayBaseType.stringof, array, key, id, Tags.stringTag, toDataType(value));
350 }
351
352 void archive (bool value, string key, size_t id)
353 {
354 archivePrimitive(value, key);
355 }
356
357 void archive (byte value, string key, size_t id)
358 {
359 archivePrimitive(value, key);
360 }
361
362 /*void archive (cdouble value, string key, size_t id)
363 {
364 archivePrimitive(value, key);
365 }*/
366
367 /*void archive (cent value, string key, size_t id)
368 {
369 archivePrimitive(value, key);
370 }*/
371
372 /*void archive (cfloat value, string key, size_t id)
373 {
374 archivePrimitive(value, key);
375 }*/
376
377 void archive (char value, string key, size_t id)
378 {
379 archivePrimitive(value, key);
380 }
381
382 /*void archive (creal value, string key, size_t id)
383 {
384 archivePrimitive(value, key);
385 }*/
386
387 void archive (dchar value, string key, size_t id)
388 {
389 archivePrimitive(value, key);
390 }
391
392 void archive (double value, string key, size_t id)
393 {
394 archivePrimitive(value, key);
395 }
396
397 void archive (float value, string key, size_t id)
398 {
399 archivePrimitive(value, key);
400 }
401
402 /*void archive (idouble value, string key, size_t id)
403 {
404 archivePrimitive(value, key);
405 }*/
406
407 /*void archive (ifloat value, string key, size_t id)
408 {
409 archivePrimitive(value, key);
410 }*/
411
412 void archive (int value, string key, size_t id)
413 {
414 archivePrimitive(value, key);
415 }
416
417 /*void archive (ireal value, string key, size_t id)
418 {
419 archivePrimitive(value, key);
420 }*/
421
422 void archive (long value, string key, size_t id)
423 {
424 archivePrimitive(value, key);
425 }
426
427 void archive (real value, string key, size_t id)
428 {
429 archivePrimitive(value, key);
430 }
431
432 void archive (short value, string key, size_t id)
433 {
434 archivePrimitive(value, key);
435 }
436
437 void archive (ubyte value, string key, size_t id)
438 {
439 archivePrimitive(value, key);
440 }
441
442 /*void archive (ucent value, string key, size_t id)
443 {
444 archivePrimitive(value, key);
445 }*/
446
447 void archive (uint value, string key, size_t id)
448 {
449 archivePrimitive(value, key);
450 }
451
452 void archive (ulong value, string key, size_t id)
453 {
454 archivePrimitive(value, key);
455 }
456
457 void archive (ushort value, string key, size_t id)
458 {
459 archivePrimitive(value, key);
460 }
461
462 void archive (wchar value, string key, size_t id)
463 {
464 archivePrimitive(value, key);
465 }
466
467 private void archivePrimitive (T) (T value, string key)
468 {
469 lastElement.element(toDataType(T.stringof), toDataType(value))
470 .attribute(Attributes.keyAttribute, toDataType(key));
471 } 1055 }
472 1056
473 version (Tango) 1057 version (Tango)
474 { 1058 {
475 private template errorMessage (ArchiveMode mode = ArchiveMode.archiving) 1059 private template errorMessage (ArchiveMode mode = ArchiveMode.archiving)