comparison orange/serialization/archives/XMLArchive.d @ 24:55f0a9d5df8d experimental

First step in refactoring the API.
author Jacob Carlborg <doob@me.com>
date Tue, 05 Oct 2010 21:59:46 +0200
parents 963b756ed579
children b51e953f79eb
comparison
equal deleted inserted replaced
23:947c32ec0ea7 24:55f0a9d5df8d
14 14
15 import orange.serialization.archives._; 15 import orange.serialization.archives._;
16 import orange.util._; 16 import orange.util._;
17 import orange.xml.XMLDocument; 17 import orange.xml.XMLDocument;
18 18
19 private enum ArchiveMode 19 final class XMLArchive (U = char) : Archive!(U)
20 { 20 {
21 archiving,
22 unarchiving
23 }
24
25 class XMLArchive (U = char) : Archive!(U)
26 {
27 static assert (isChar!(U), format!(`The given type "`, U, `" is not a valid type. Valid types are: "char", "wchar" and "dchar".`));
28
29 private struct Tags 21 private struct Tags
30 { 22 {
31 static const DataType structTag = "struct"; 23 static const DataType structTag = "struct";
32 static const DataType dataTag = "data"; 24 static const DataType dataTag = "data";
33 static const DataType archiveTag = "archive"; 25 static const DataType archiveTag = "archive";
57 static const DataType offsetAttribute = "offset"; 49 static const DataType offsetAttribute = "offset";
58 } 50 }
59 51
60 private 52 private
61 { 53 {
62 struct ArrayNode
63 {
64 XMLDocument!(U).Node parent;
65 XMLDocument!(U).Node node;
66 DataType id;
67 DataType key;
68 }
69
70 struct Array
71 {
72 void* ptr;
73 size_t length;
74 size_t elementSize;
75
76 static Array opCall (T) (T[] value)
77 {
78 Array array;
79 array.ptr = value.ptr;
80 array.length = value.length;
81 array.elementSize = T.sizeof;
82
83 return array;
84 }
85
86 bool isSliceOf (Array b)
87 {
88 return ptr >= b.ptr && ptr + length * elementSize <= b.ptr + b.length * b.elementSize;
89 }
90 }
91
92 struct Slice
93 {
94 size_t length;
95 size_t offset;
96 DataType id;
97 }
98
99 DataType archiveType = "org.dsource.orange.xml"; 54 DataType archiveType = "org.dsource.orange.xml";
100 DataType archiveVersion = "0.1"; 55 DataType archiveVersion = "0.1";
101 56
102 XMLDocument!(U) doc; 57 XMLDocument!(U) doc;
103 doc.Node lastElement; 58 doc.Node lastElement;
104 //DocPrinter!(U) printer;
105 doc.Node lastElementSaved;
106 59
107 bool hasBegunArchiving; 60 bool hasBegunArchiving;
108 bool hasBegunUnarchiving; 61 bool hasBegunUnarchiving;
109 62
110 DataType[void*] archivedReferences;
111 void*[DataType] unarchivedReferences;
112
113 ArrayNode[Array] arraysToBeArchived; 63 ArrayNode[Array] arraysToBeArchived;
114 void[][DataType] unarchivedSlices; 64 void[][DataType] unarchivedSlices;
115 65 }
116 size_t idCounter; 66
117 } 67 this (ErrorCallback errorCallback)
118 68 {
119 this () 69 this.errorCallback = errorCallback;
120 {
121 doc = new XMLDocument!(U); 70 doc = new XMLDocument!(U);
122 } 71 }
123 72
124 public void beginArchiving () 73 public void beginArchiving ()
125 { 74 {
133 82
134 hasBegunArchiving = true; 83 hasBegunArchiving = true;
135 } 84 }
136 } 85 }
137 86
138 public void beginUnarchiving (DataType data) 87 public void beginUnarchiving (IDataType untypedData)
139 { 88 {
89 auto data = cast(DataType) untypedData;
90
140 if (!hasBegunUnarchiving) 91 if (!hasBegunUnarchiving)
141 { 92 {
142 doc.parse(data); 93 doc.parse(data);
143 hasBegunUnarchiving = true; 94 hasBegunUnarchiving = true;
144 95
159 } 110 }
160 } 111 }
161 } 112 }
162 } 113 }
163 114
164 public DataType data () 115 IDataType data ()
165 { 116 {
166 /*if (!printer)
167 printer = new DocPrinter!(U);
168
169 return printer.print(doc);*/
170
171 return doc.toString(); 117 return doc.toString();
172 } 118 }
173 119
174 public void reset () 120 void postProcess ()
175 {
176 hasBegunArchiving = false;
177 hasBegunUnarchiving = false;
178 idCounter = 0;
179 doc.reset;
180 }
181
182 private void begin ()
183 {
184 lastElementSaved = lastElement;
185 }
186
187 private void end ()
188 {
189 lastElement = lastElementSaved;
190 }
191
192 public void archive (T) (T value, DataType key, void delegate () dg = null)
193 {
194 if (!hasBegunArchiving)
195 beginArchiving();
196
197 restore(lastElement) in {
198 bool callDelegate = true;
199
200 static if (isTypeDef!(T))
201 archiveTypeDef(value, key);
202
203 else static if (isObject!(T))
204 archiveObject(value, key, callDelegate);
205
206 else static if (isStruct!(T))
207 archiveStruct(value, key);
208
209 else static if (isString!(T))
210 archiveString(value, key);
211
212 else static if (isArray!(T))
213 archiveArray(value, key);
214
215 else static if (isAssociativeArray!(T))
216 archiveAssociativeArray(value, key);
217
218 else static if (isPrimitive!(T))
219 archivePrimitive(value, key);
220
221 else static if (isPointer!(T))
222 archivePointer(value, key, callDelegate);
223
224 else static if (isEnum!(T))
225 archiveEnum(value, key);
226
227 else
228 static assert(false, format!(`The type "`, T, `" cannot be archived.`));
229
230 if (callDelegate && dg)
231 dg();
232 };
233 }
234
235 private void archiveObject (T) (T value, DataType key, ref bool callDelegate)
236 {
237 if (!value)
238 {
239 lastElement.element(Tags.nullTag)
240 .attribute(Attributes.typeAttribute, toDataType(T.stringof))
241 .attribute(Attributes.keyAttribute, key);
242 callDelegate = false;
243 }
244
245 else if (auto reference = getArchivedReference(value))
246 {
247 archiveReference(key, reference);
248 callDelegate = false;
249 }
250
251 else
252 {
253 DataType id = nextId;
254
255 lastElement = lastElement.element(Tags.objectTag)
256 .attribute(Attributes.runtimeTypeAttribute, toDataType(value.classinfo.name))
257 .attribute(Attributes.typeAttribute, toDataType(T.stringof))
258 .attribute(Attributes.keyAttribute, key)
259 .attribute(Attributes.idAttribute, id);
260
261 addArchivedReference(value, id);
262 }
263 }
264
265 private void archiveStruct (T) (T value, DataType key)
266 {
267 lastElement = lastElement.element(Tags.structTag)
268 .attribute(Attributes.typeAttribute, toDataType(T.stringof))
269 .attribute(Attributes.keyAttribute, key);
270 }
271
272 private void archiveString (T) (T value, DataType key)
273 {
274 archiveArrayImpl(value, key, Tags.stringTag, toDataType(value));
275 }
276
277 private void archiveArray (T) (T value, DataType key)
278 {
279 archiveArrayImpl(value, key, Tags.arrayTag);
280 }
281
282 private void archiveArrayImpl (T) (T value, DataType key, DataType tag, DataType content = null)
283 {
284 DataType id = nextId;
285 auto parent = lastElement;
286
287 if (value.length == 0)
288 lastElement = lastElement.element(tag);
289
290 else
291 lastElement = doc.createNode(tag, content);
292
293 lastElement.attribute(Attributes.typeAttribute, toDataType(BaseTypeOfArray!(T).stringof))
294 .attribute(Attributes.lengthAttribute, toDataType(value.length))
295 .attribute(Attributes.keyAttribute, key)
296 .attribute(Attributes.idAttribute, id);
297
298 arraysToBeArchived[Array(value)] = ArrayNode(parent, lastElement, id, key);
299 }
300
301 private void archiveAssociativeArray (T) (T value, DataType key)
302 {
303 lastElement = lastElement.element(Tags.associativeArrayTag)
304 .attribute(Attributes.keyTypeAttribute, toDataType(KeyTypeOfAssociativeArray!(T).stringof))
305 .attribute(Attributes.valueTypeAttribute, toDataType(ValueTypeOfAssociativeArray!(T).stringof))
306 .attribute(Attributes.lengthAttribute, toDataType(value.length))
307 .attribute(Attributes.keyAttribute, key);
308 }
309
310 private void archivePointer (T) (T value, DataType key, ref bool callDelegate)
311 {
312 if (auto reference = getArchivedReference(value))
313 {
314 archiveReference(key, reference);
315 callDelegate = false;
316 }
317
318 else
319 {
320 DataType id = nextId;
321
322 lastElement = lastElement.element(Tags.pointerTag)
323 .attribute(Attributes.keyAttribute, key)
324 .attribute(Attributes.idAttribute, id);
325
326 addArchivedReference(value, id);
327 }
328 }
329
330 private void archiveEnum (T) (T value, DataType key)
331 {
332 lastElement.element(Tags.enumTag, toDataType(value))
333 .attribute(Attributes.typeAttribute, toDataType(T.stringof))
334 .attribute(Attributes.keyAttribute, key);
335 }
336
337 private void archivePrimitive (T) (T value, DataType key)
338 {
339 lastElement.element(toDataType(T.stringof), toDataType(value))
340 .attribute(Attributes.keyAttribute, key);
341 }
342
343 private void archiveTypeDef (T) (T value, DataType key)
344 {
345 lastElement = lastElement.element(Tags.typedefTag)
346 .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfTypeDef!(T).stringof));
347 .attribute(Attributes.key, key);
348 }
349
350 public T unarchive (T) (DataType key, T delegate (T) dg = null)
351 {
352 if (!hasBegunUnarchiving)
353 beginUnarchiving(data);
354
355 return restore!(T)(lastElement) in {
356 T value;
357
358 bool callDelegate = true;
359
360 static if (isTypeDef!(T))
361 value = unarchiveTypeDef!(T)(key);
362
363 else static if (isObject!(T))
364 value = unarchiveObject!(T)(key, callDelegate);
365
366 else static if (isStruct!(T))
367 value = unarchiveStruct!(T)(key);
368
369 else static if (isString!(T))
370 value = unarchiveString!(T)(key);
371
372 else static if (isArray!(T))
373 value = unarchiveArray!(T)(key, callDelegate);
374
375 else static if (isAssociativeArray!(T))
376 value = unarchiveAssociativeArray!(T)(key);
377
378 else static if (isPrimitive!(T))
379 value = unarchivePrimitive!(T)(key);
380
381 else static if (isPointer!(T))
382 value = unarchivePointer!(T)(key, callDelegate);
383
384 else static if (isEnum!(T))
385 value = unarchiveEnum!(T)(key);
386
387 else
388 static assert(false, format!(`The type "`, T, `" cannot be unarchived.`));
389
390 if (callDelegate && dg)
391 return dg(value);
392
393 return value;
394 };
395 }
396
397 private T unarchiveObject (T) (DataType key, ref bool callDelegate)
398 {
399 DataType id = unarchiveReference(key);
400
401 if (auto reference = getUnarchivedReference!(T)(id))
402 {
403 callDelegate = false;
404 return *reference;
405 }
406
407 auto tmp = getElement(Tags.objectTag, key, Attributes.keyAttribute, false);
408
409 if (!tmp.isValid)
410 {
411 lastElement = getElement(Tags.nullTag, key);
412 callDelegate = false;
413 return null;
414 }
415
416 lastElement = tmp;
417
418 auto runtimeType = getValueOfAttribute(Attributes.runtimeTypeAttribute);
419
420 if (!runtimeType)
421 return T.init;
422
423 auto name = fromDataType!(string)(runtimeType);
424 id = getValueOfAttribute(Attributes.idAttribute);
425
426 if (!id)
427 return T.init;
428
429 T result = cast(T) newInstance(name);
430
431 addUnarchivedReference(result, id);
432
433 return result;
434 }
435
436 private T unarchiveStruct (T) (DataType key)
437 {
438 auto element = getElement(Tags.structTag, key);
439
440 if (element.isValid)
441 lastElement = element;
442
443 return T.init;
444 }
445
446 private T unarchiveString (T) (DataType key)
447 {
448 auto slice = unarchiveSlice(key);
449
450 if (auto tmp = getUnarchivedSlice!(T)(slice))
451 return *tmp;
452
453 auto element = getElement(Tags.stringTag, key);
454
455 if (!element.isValid)
456 return T.init;
457
458 auto value = fromDataType!(T)(element.value);
459 slice.id = getValueOfAttribute(Attributes.idAttribute, element);
460
461 if (!slice.id)
462 return T.init;
463
464 addUnarchivedSlice(value, slice.id);
465
466 return value;
467 }
468
469 private T unarchiveArray (T) (DataType key, ref bool callDelegate)
470 {
471 auto slice = unarchiveSlice(key);
472
473 if (auto tmp = getUnarchivedSlice!(T)(slice))
474 {
475 callDelegate = false;
476 return *tmp;
477 }
478
479 T value;
480
481 auto element = getElement(Tags.arrayTag, key);
482
483 if (!element.isValid)
484 return T.init;
485
486 lastElement = element;
487 auto length = getValueOfAttribute(Attributes.lengthAttribute);
488
489 if (!length)
490 return T.init;
491
492 value.length = fromDataType!(size_t)(length);
493 slice.id = getValueOfAttribute(Attributes.idAttribute);
494
495 if (!slice.id)
496 return T.init;
497
498 addUnarchivedSlice(value, slice.id);
499
500 return value;
501 }
502
503 private T unarchiveAssociativeArray (T) (DataType key)
504 {
505 auto element = getElement(Tags.associativeArrayTag, key);
506
507 if (element.isValid)
508 lastElement = element;
509
510 return T.init;
511 }
512
513 private T unarchivePointer (T) (DataType key, ref bool callDelegate)
514 {
515 DataType id = unarchiveReference(key);
516
517 if (auto reference = getUnarchivedReference!(T)(id))
518 {
519 callDelegate = false;
520 return *reference;
521 }
522
523 auto element = getElement(Tags.pointerTag, key);
524
525 if (!element.isValid)
526 return T.init;
527
528 lastElement = element;
529 id = getValueOfAttribute(Attributes.idAttribute);
530
531 if (!id)
532 return T.init;
533
534 T result = new BaseTypeOfPointer!(T);
535
536 addUnarchivedReference(result, id);
537
538 return result;
539 }
540
541 private T unarchiveEnum (T) (DataType key)
542 {
543 auto element = getElement(Tags.enumTag, key);
544
545 if (!element.isValid)
546 return T.init;
547
548 return fromDataType!(T)(element.value);
549 }
550
551 private T unarchivePrimitive (T) (DataType key)
552 {
553 auto element = getElement(toDataType(T.stringof), key);
554
555 if (!element.isValid)
556 return T.init;
557
558 return fromDataType!(T)(element.value);
559 }
560
561 private T unarchiveTypeDef (T) (DataType key)
562 {
563 auto element = getElement(Tags.typedefTag, key);
564
565 if (element.isValid)
566 lastElement = element;
567
568 return T.init;
569 }
570
571 public AssociativeArrayVisitor!(KeyTypeOfAssociativeArray!(T), ValueTypeOfAssociativeArray!(T)) unarchiveAssociativeArrayVisitor (T) ()
572 {
573 return AssociativeArrayVisitor!(KeyTypeOfAssociativeArray!(T), ValueTypeOfAssociativeArray!(T))(this);
574 }
575
576 public void archiveBaseClass (T : Object) (DataType key)
577 {
578 lastElement = lastElement.element(Tags.baseTag)
579 .attribute(Attributes.typeAttribute, toDataType(T.stringof))
580 .attribute(Attributes.keyAttribute, key);
581 }
582
583 public void unarchiveBaseClass (T : Object) (DataType key)
584 {
585 auto element = getElement(Tags.baseTag, key);
586
587 if (element.isValid)
588 lastElement = element;
589 }
590
591 version (Tango)
592 {
593 template errorMessage (ArchiveMode mode = ArchiveMode.archiving)
594 {
595 static if (mode == ArchiveMode.archiving)
596 const errorMessage = "Could not continue archiving due to unrecognized data format: ";
597
598 else static if (mode == ArchiveMode.unarchiving)
599 const errorMessage = "Could not continue unarchiving due to unrecognized data format: ";
600 }
601 }
602
603 else
604 {
605 mixin(
606 `template errorMessage (ArchiveMode mode = ArchiveMode.archiving)
607 {
608 static if (mode == ArchiveMode.archiving)
609 enum errorMessage = "Could not continue archiving due to unrecognized data format: ";
610
611 else static if (mode == ArchiveMode.unarchiving)
612 enum errorMessage = "Could not continue unarchiving due to unrecognized data format: ";
613 }`
614 );
615 }
616
617 private doc.Node getElement (DataType tag, DataType key, DataType attribute = Attributes.keyAttribute, bool throwOnError = true)
618 {
619 auto set = lastElement.query[tag].attribute((doc.Node node) {
620 if (node.name == attribute && node.value == key)
621 return true;
622
623 return false;
624 });
625
626 if (set.nodes.length == 1)
627 return set.nodes[0].parent;
628
629 else
630 {
631 if (throwOnError && errorCallback)
632 {
633 if (set.nodes.length == 0)
634 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]);
635
636 else
637 errorCallback(new ArchiveException(`Could not unarchive the value with the key "` ~ to!(string)(key) ~ `" due to malformed data.`, __FILE__, __LINE__), [tag, Attributes.keyAttribute, key]);
638 }
639
640 return doc.Node.invalid;
641 }
642 }
643
644 private DataType getValueOfAttribute (DataType attribute, doc.Node element = doc.Node.invalid)
645 {
646 if (!element.isValid) element = lastElement;
647
648 auto set = element.query.attribute(attribute);
649
650 if (set.nodes.length == 1)
651 return set.nodes[0].value;
652
653 else
654 {
655 if (errorCallback)
656 {
657 if (set.nodes.length == 0)
658 errorCallback(new ArchiveException(`Could not find the attribute "` ~ to!(string)(attribute) ~ `".`, __FILE__, __LINE__), [attribute]);
659
660 else
661 errorCallback(new ArchiveException(`Could not unarchive the value of the attribute "` ~ to!(string)(attribute) ~ `" due to malformed data.`, __FILE__, __LINE__), [attribute]);
662 }
663 }
664
665 return null;
666 }
667
668 private void addArchivedReference (T) (T value, DataType id)
669 {
670 static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`));
671
672 archivedReferences[cast(void*) value] = id;
673 }
674
675 private void addUnarchivedReference (T) (T value, DataType id)
676 {
677 static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`));
678
679 unarchivedReferences[id] = cast(void*) value;
680 }
681
682 private void addUnarchivedSlice (T) (T value, DataType id)
683 {
684 static assert(isArray!(T) || isString!(T), format!(`The given type "`, T, `" is not a slice type, i.e. array or string.`));
685
686 unarchivedSlices[id] = value;
687 }
688
689 private DataType getArchivedReference (T) (T value)
690 {
691 if (auto tmp = cast(void*) value in archivedReferences)
692 return *tmp;
693
694 return null;
695 }
696
697 private T* getUnarchivedReference (T) (DataType id)
698 {
699 if (auto reference = id in unarchivedReferences)
700 return cast(T*) reference;
701
702 return null;
703 }
704
705 private T* getUnarchivedSlice (T) (Slice slice)
706 {
707 if (auto array = slice.id in unarchivedSlices)
708 return &(cast(T) *array)[slice.offset .. slice.length + 1]; // dereference the array, cast it to the right type,
709 // slice it and then return a pointer to the result
710 return null;
711 }
712
713 private DataType nextId ()
714 {
715 return toDataType(idCounter++);
716 }
717
718 private void archiveReference (DataType key, DataType id)
719 {
720 lastElement.element(Tags.referenceTag, id)
721 .attribute(Attributes.keyAttribute, key);
722 }
723
724 private DataType unarchiveReference (DataType key)
725 {
726 auto element = getElement(Tags.referenceTag, key, Attributes.keyAttribute, false);
727
728 if (element.isValid)
729 return element.value;
730
731 return cast(DataType) null;
732 }
733
734 private Slice unarchiveSlice (DataType key)
735 {
736 auto element = getElement(Tags.sliceTag, key, Attributes.keyAttribute, false);
737
738 if (element.isValid)
739 {
740 auto length = fromDataType!(size_t)(getValueOfAttribute(Attributes.lengthAttribute, element));
741 auto offset = fromDataType!(size_t)(getValueOfAttribute(Attributes.offsetAttribute, element));
742
743 return Slice(length, offset, element.value);
744 }
745
746 return Slice.init;
747 }
748
749 private struct AssociativeArrayVisitor (Key, Value)
750 {
751 private XMLArchive archive;
752
753 static AssociativeArrayVisitor opCall (XMLArchive archive)
754 {
755 AssociativeArrayVisitor aai;
756 aai.archive = archive;
757
758 return aai;
759 }
760
761 int opApply(int delegate(ref Key, ref Value) dg)
762 {
763 int result;
764
765 foreach (node ; archive.lastElement.children)
766 {
767 restore(archive.lastElement) in {
768 archive.lastElement = node;
769
770 if (node.attributes.exist)
771 {
772 Key key = to!(Key)(archive.getValueOfAttribute(Attributes.keyAttribute));
773 Value value = to!(Value)(node.value);
774
775 result = dg(key, value);
776 }
777 };
778
779 if (result)
780 break;
781 }
782
783 return result;
784 }
785 }
786
787 public void postProcess ()
788 { 121 {
789 bool foundSlice = true; 122 bool foundSlice = true;
790 123
791 foreach (slice, sliceNode ; arraysToBeArchived) 124 foreach (slice, sliceNode ; arraysToBeArchived)
792 { 125 {
808 } 141 }
809 142
810 if (!foundSlice) 143 if (!foundSlice)
811 sliceNode.parent.attach(sliceNode.node); 144 sliceNode.parent.attach(sliceNode.node);
812 } 145 }
146 }
147
148 void reset ()
149 {
150 hasBegunArchiving = false;
151 hasBegunUnarchiving = false;
152 doc.reset;
153 }
154
155 void archiveArray (Array array, string type, string key, size_t id)
156 {
157 internalArchiveArray(type, array, key, id, Tags.arrayTag);
158 }
159
160 private void internalArchiveArray(string type, Array array, string key, size_t id, DataType tag, DataType content = null)
161 {
162 auto parent = lastElement;
163
164 if (value.length == 0)
165 lastElement = lastElement.element(tag);
166
167 else
168 lastElement = doc.createNode(tag, content);
169
170 lastElement.attribute(Attributes.typeAttribute, toDataType(type))
171 .attribute(Attributes.lengthAttribute, toDataType(length))
172 .attribute(Attributes.keyAttribute, toDataType(key))
173 .attribute(Attributes.idAttribute, toDataType(id));
174 }
175
176 void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id)
177 {
178 lastElement = lastElement.element(Tags.associativeArrayTag)
179 .attribute(Attributes.keyTypeAttribute, toDataType(keyType))
180 .attribute(Attributes.valueTypeAttribute, toDataType(valueType))
181 .attribute(Attributes.lengthAttribute, toDataType(length))
182 .attribute(Attributes.keyAttribute, key);
183 }
184
185 void archiveEnum (bool value, string key, size_t id)
186 {
187 internalArchiveEnum(value, key, id);
188 }
189
190 void archiveEnum (byte value, string key, size_t id)
191 {
192 internalArchiveEnum(value, key, id);
193 }
194
195 void archiveEnum (char value, string key, size_t id)
196 {
197 internalArchiveEnum(value, key, id);
198 }
199
200 void archiveEnum (dchar value, string key, size_t id)
201 {
202 internalArchiveEnum(value, key, id);
203 }
204
205 void archiveEnum (int value, string key, size_t id)
206 {
207 internalArchiveEnum(value, key, id);
208 }
209
210 void archiveEnum (long value, string key, size_t id)
211 {
212 internalArchiveEnum(value, key, id);
213 }
214
215 void archiveEnum (short value, string key, size_t id)
216 {
217 internalArchiveEnum(value, key, id);
218 }
219
220 void archiveEnum (ubyte value, string key, size_t id)
221 {
222 internalArchiveEnum(value, key, id);
223 }
224
225 void archiveEnum (uint value, string key, size_t id)
226 {
227 internalArchiveEnum(value, key, id);
228 }
229
230 void archiveEnum (ulong value, string key, size_t id)
231 {
232 internalArchiveEnum(value, key, id);
233 }
234
235 void archiveEnum (ushort value, string key, size_t id)
236 {
237 internalArchiveEnum(value, key, id);
238 }
239
240 void archiveEnum (wchar value, string key, size_t id)
241 {
242 internalArchiveEnum(value, key, id);
243 }
244
245 private void internalArchiveEnum (T) (T value, string key, size_t id)
246 {
247 lastElement.element(Tags.enumTag, toDataType(value))
248 .attribute(Attributes.typeAttribute, toDataType(T.stringof))
249 .attribute(Attributes.keyAttribute, toDataType(key));
250 }
251
252 void archiveNull (string type, string key)
253 {
254 lastElement.element(Tags.nullTag)
255 .attribute(Attributes.typeAttribute, toDataType(T.stringof))
256 .attribute(Attributes.keyAttribute, key);
257 }
258
259 void archiveObject (string runtimeType, string type, string key, size_t id)
260 {
261 lastElement = lastElement.element(Tags.objectTag)
262 .attribute(Attributes.runtimeTypeAttribute, toDataType(name))
263 .attribute(Attributes.typeAttribute, toDataType(type))
264 .attribute(Attributes.keyAttribute, toDataType(key))
265 .attribute(Attributes.idAttribute, toDataType(id));
266 }
267
268 void archivePointer (string key, size_t id)
269 {
270 lastElement = lastElement.element(Tags.pointerTag)
271 .attribute(Attributes.keyAttribute, toDataType(key))
272 .attribute(Attributes.idAttribute, toDataType(id));
273 }
274
275 void archiveReference (size_t key, size_t id)
276 {
277 lastElement.element(Tags.referenceTag, toDataType(id))
278 .attribute(Attributes.keyAttribute, toDataType(key));
279 }
280
281 /*void archiveSlice (Array array, Array slice)
282 {
283 sliceNode.parent.element(Tags.sliceTag, arrayNode.id)
284 .attribute(Attributes.keyAttribute, sliceNode.key)
285 .attribute(Attributes.offsetAttribute, toDataType((slice.ptr - array.ptr) / slice.elementSize))
286 .attribute(Attributes.lengthAttribute, toDataType(slice.length));
287 }*/
288
289 void archiveStruct (string type, size_t key, size_t id)
290 {
291 lastElement = lastElement.element(Tags.structTag)
292 .attribute(Attributes.typeAttribute, toDataType(type))
293 .attribute(Attributes.keyAttribute, key);
294 }
295
296 void archiveTypedef (string type, size_t key, size_t id)
297 {
298 lastElement = lastElement.element(Tags.typedefTag)
299 .attribute(Attributes.typeAttribute, toDataType(type));
300 .attribute(Attributes.key, toDataType(key));
301 }
302
303 void archive (string value, string key, size_t id)
304 {
305 archiveString(value, key, id);
306 }
307
308 void archive (wstring value, string key, size_t id)
309 {
310 archiveString(value, key, id);
311 }
312
313 void archive (dstring value, string key, size_t id)
314 {
315 archiveString(value, key, id);
316 }
317
318 private void archiveString (T) (T value, string key, size_t id)
319 {
320 alias BaseTypeOfArray!(T) ArrayBaseType;
321 auto array = Array(value.ptr, value.length, ArrayBaseType.sizeof);
322
323 internalArchiveArray(ArrayBaseType.stringof, array, key, id, Tags.stringTag, toDataType(value));
324 }
325
326 void archive (bool value, string key, size_t id)
327 {
328 archivePrimitive (value, key);
329 }
330
331 void archive (byte value, string key, size_t id)
332 {
333 archivePrimitive (value, key);
334 }
335
336 void archive (cdouble value, string key, size_t id)
337 {
338 archivePrimitive (value, key);
339 }
340
341 /*void archive (cent value, string key, size_t id)
342 {
343 archivePrimitive (value, key);
344 }*/
345
346 void archive (cfloat value, string key, size_t id)
347 {
348 archivePrimitive (value, key);
349 }
350
351 void archive (char value, string key, size_t id)
352 {
353 archivePrimitive (value, key);
354 }
355
356 void archive (creal value, string key, size_t id)
357 {
358 archivePrimitive (value, key);
359 }
360
361 void archive (dchar value, string key, size_t id)
362 {
363 archivePrimitive (value, key);
364 }
365
366 void archive (double value, string key, size_t id)
367 {
368 archivePrimitive (value, key);
369 }
370
371 void archive (float value, string key, size_t id)
372 {
373 archivePrimitive (value, key);
374 }
375
376 void archive (idouble value, string key, size_t id)
377 {
378 archivePrimitive (value, key);
379 }
380
381 void archive (ifloat value, string key, size_t id)
382 {
383 archivePrimitive (value, key);
384 }
385
386 void archive (int value, string key, size_t id)
387 {
388 archivePrimitive (value, key);
389 }
390
391 void archive (ireal value, string key, size_t id)
392 {
393 archivePrimitive (value, key);
394 }
395
396 void archive (long value, string key, size_t id)
397 {
398 archivePrimitive (value, key);
399 }
400
401 void archive (real value, string key, size_t id)
402 {
403 archivePrimitive (value, key);
404 }
405
406 void archive (short value, string key, size_t id)
407 {
408 archivePrimitive (value, key);
409 }
410
411 void archive (ubyte value, string key, size_t id)
412 {
413 archivePrimitive (value, key);
414 }
415
416 /*void archive (ucent value, string key, size_t id)
417 {
418 archivePrimitive (value, key);
419 }*/
420
421 void archive (uint value, string key, size_t id)
422 {
423 archivePrimitive (value, key);
424 }
425
426 void archive (ulong value, string key, size_t id)
427 {
428 archivePrimitive (value, key);
429 }
430
431 void archive (ushort value, string key, size_t id)
432 {
433 archivePrimitive (value, key);
434 }
435
436 void archive (wchar value, string key, size_t id)
437 {
438 archivePrimitive (value, key);
439 }
440
441 private void archivePrimitive (T) (T value, string key)
442 {
443 lastElement.element(toDataType(T.stringof), toDataType(value))
444 .attribute(Attributes.keyAttribute, toDataType(key));
445 }
446
447 private void addArchivedArray (doc.Node parent, doc.Node lastElement, size_t id, string key, size_t elementSize, )
448 {
449 arraysToBeArchived[Array(value)] = ArrayNode(parent, lastElement, id, key);
813 } 450 }
814 } 451 }