comparison orange/serialization/archives/XMLArchive.d @ 22:963b756ed579

Resolved merge conflicts.
author Jacob Carlborg <doob@me.com>
date Mon, 04 Oct 2010 20:42:45 +0200
parents 8ab9588b92bf 51f05fd6a626
children 55f0a9d5df8d
comparison
equal deleted inserted replaced
19:8ab9588b92bf 22:963b756ed579
38 static const DataType referenceTag = "reference"; 38 static const DataType referenceTag = "reference";
39 static const DataType pointerTag = "pointer"; 39 static const DataType pointerTag = "pointer";
40 static const DataType associativeArrayTag = "associativeArray"; 40 static const DataType associativeArrayTag = "associativeArray";
41 static const DataType typedefTag = "typedef"; 41 static const DataType typedefTag = "typedef";
42 static const DataType nullTag = "null"; 42 static const DataType nullTag = "null";
43 static const DataType enumTag = "enum"; 43 static const DataType enumTag = "enum";
44 static const DataType sliceTag = "slice";
44 } 45 }
45 46
46 private struct Attributes 47 private struct Attributes
47 { 48 {
48 static const DataType typeAttribute = "type"; 49 static const DataType typeAttribute = "type";
51 static const DataType keyAttribute = "key"; 52 static const DataType keyAttribute = "key";
52 static const DataType runtimeTypeAttribute = "runtimeType"; 53 static const DataType runtimeTypeAttribute = "runtimeType";
53 static const DataType idAttribute = "id"; 54 static const DataType idAttribute = "id";
54 static const DataType keyTypeAttribute = "keyType"; 55 static const DataType keyTypeAttribute = "keyType";
55 static const DataType valueTypeAttribute = "valueType"; 56 static const DataType valueTypeAttribute = "valueType";
57 static const DataType offsetAttribute = "offset";
56 } 58 }
57 59
58 private 60 private
59 { 61 {
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
60 DataType archiveType = "org.dsource.orange.xml"; 99 DataType archiveType = "org.dsource.orange.xml";
61 DataType archiveVersion = "0.1"; 100 DataType archiveVersion = "0.1";
62 101
63 XMLDocument!(U) doc; 102 XMLDocument!(U) doc;
64 doc.Node lastElement; 103 doc.Node lastElement;
68 bool hasBegunArchiving; 107 bool hasBegunArchiving;
69 bool hasBegunUnarchiving; 108 bool hasBegunUnarchiving;
70 109
71 DataType[void*] archivedReferences; 110 DataType[void*] archivedReferences;
72 void*[DataType] unarchivedReferences; 111 void*[DataType] unarchivedReferences;
112
113 ArrayNode[Array] arraysToBeArchived;
114 void[][DataType] unarchivedSlices;
73 115
74 size_t idCounter; 116 size_t idCounter;
75 } 117 }
76 118
77 this () 119 this ()
226 .attribute(Attributes.typeAttribute, toDataType(T.stringof)) 268 .attribute(Attributes.typeAttribute, toDataType(T.stringof))
227 .attribute(Attributes.keyAttribute, key); 269 .attribute(Attributes.keyAttribute, key);
228 } 270 }
229 271
230 private void archiveString (T) (T value, DataType key) 272 private void archiveString (T) (T value, DataType key)
231 { 273 {
232 lastElement.element(Tags.stringTag, toDataType(value)) 274 archiveArrayImpl(value, key, Tags.stringTag, toDataType(value));
233 .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfArray!(T).stringof))
234 .attribute(Attributes.keyAttribute, key);
235 } 275 }
236 276
237 private void archiveArray (T) (T value, DataType key) 277 private void archiveArray (T) (T value, DataType key)
238 { 278 {
239 lastElement = lastElement.element(Tags.arrayTag) 279 archiveArrayImpl(value, key, Tags.arrayTag);
240 .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfArray!(T).stringof)) 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))
241 .attribute(Attributes.lengthAttribute, toDataType(value.length)) 294 .attribute(Attributes.lengthAttribute, toDataType(value.length))
242 .attribute(Attributes.keyAttribute, key); 295 .attribute(Attributes.keyAttribute, key)
296 .attribute(Attributes.idAttribute, id);
297
298 arraysToBeArchived[Array(value)] = ArrayNode(parent, lastElement, id, key);
243 } 299 }
244 300
245 private void archiveAssociativeArray (T) (T value, DataType key) 301 private void archiveAssociativeArray (T) (T value, DataType key)
246 { 302 {
247 lastElement = lastElement.element(Tags.associativeArrayTag) 303 lastElement = lastElement.element(Tags.associativeArrayTag)
312 368
313 else static if (isString!(T)) 369 else static if (isString!(T))
314 value = unarchiveString!(T)(key); 370 value = unarchiveString!(T)(key);
315 371
316 else static if (isArray!(T)) 372 else static if (isArray!(T))
317 value = unarchiveArray!(T)(key); 373 value = unarchiveArray!(T)(key, callDelegate);
318 374
319 else static if (isAssociativeArray!(T)) 375 else static if (isAssociativeArray!(T))
320 value = unarchiveAssociativeArray!(T)(key); 376 value = unarchiveAssociativeArray!(T)(key);
321 377
322 else static if (isPrimitive!(T)) 378 else static if (isPrimitive!(T))
360 lastElement = tmp; 416 lastElement = tmp;
361 417
362 auto runtimeType = getValueOfAttribute(Attributes.runtimeTypeAttribute); 418 auto runtimeType = getValueOfAttribute(Attributes.runtimeTypeAttribute);
363 419
364 if (!runtimeType) 420 if (!runtimeType)
365 return T.init; 421 return T.init;
366 422
367 auto name = fromDataType!(string)(runtimeType); 423 auto name = fromDataType!(string)(runtimeType);
368 id = getValueOfAttribute(Attributes.idAttribute); 424 id = getValueOfAttribute(Attributes.idAttribute);
369 425
370 if (!id) 426 if (!id)
371 return T.init; 427 return T.init;
372 428
373 T result; 429 T result = cast(T) newInstance(name);
374
375 /*static if (is(typeof(T._ctor)))
376 {
377 ParameterTupleOf!(typeof(T._ctor)) params;
378 result = factory!(T, typeof(params))(name, params);
379 }
380
381 else*/
382 result = cast(T) newInstance(name);
383 430
384 addUnarchivedReference(result, id); 431 addUnarchivedReference(result, id);
385 432
386 return result; 433 return result;
387 } 434 }
396 return T.init; 443 return T.init;
397 } 444 }
398 445
399 private T unarchiveString (T) (DataType key) 446 private T unarchiveString (T) (DataType key)
400 { 447 {
448 auto slice = unarchiveSlice(key);
449
450 if (auto tmp = getUnarchivedSlice!(T)(slice))
451 return *tmp;
452
401 auto element = getElement(Tags.stringTag, key); 453 auto element = getElement(Tags.stringTag, key);
402 454
403 if (!element.isValid) 455 if (!element.isValid)
404 return T.init; 456 return T.init;
405 457
406 return fromDataType!(T)(element.value); 458 auto value = fromDataType!(T)(element.value);
407 } 459 slice.id = getValueOfAttribute(Attributes.idAttribute, element);
408 460
409 private T unarchiveArray (T) (DataType key) 461 if (!slice.id)
410 { 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
411 T value; 479 T value;
412 480
413 auto element = getElement(Tags.arrayTag, key); 481 auto element = getElement(Tags.arrayTag, key);
414 482
415 if (!element.isValid) 483 if (!element.isValid)
420 488
421 if (!length) 489 if (!length)
422 return T.init; 490 return T.init;
423 491
424 value.length = fromDataType!(size_t)(length); 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);
425 499
426 return value; 500 return value;
427 } 501 }
428 502
429 private T unarchiveAssociativeArray (T) (DataType key) 503 private T unarchiveAssociativeArray (T) (DataType key)
562 else 636 else
563 errorCallback(new ArchiveException(`Could not unarchive the value with the key "` ~ to!(string)(key) ~ `" due to malformed data.`, __FILE__, __LINE__), [tag, Attributes.keyAttribute, key]); 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]);
564 } 638 }
565 639
566 return doc.Node.invalid; 640 return doc.Node.invalid;
567 } 641 }
568 } 642 }
569 643
570 private DataType getValueOfAttribute (DataType attribute) 644 private DataType getValueOfAttribute (DataType attribute, doc.Node element = doc.Node.invalid)
571 { 645 {
572 auto set = lastElement.query.attribute(attribute); 646 if (!element.isValid) element = lastElement;
647
648 auto set = element.query.attribute(attribute);
573 649
574 if (set.nodes.length == 1) 650 if (set.nodes.length == 1)
575 return set.nodes[0].value; 651 return set.nodes[0].value;
576 652
577 else 653 else
583 659
584 else 660 else
585 errorCallback(new ArchiveException(`Could not unarchive the value of the attribute "` ~ to!(string)(attribute) ~ `" due to malformed data.`, __FILE__, __LINE__), [attribute]); 661 errorCallback(new ArchiveException(`Could not unarchive the value of the attribute "` ~ to!(string)(attribute) ~ `" due to malformed data.`, __FILE__, __LINE__), [attribute]);
586 } 662 }
587 } 663 }
588 664
589 return null; 665 return null;
590 } 666 }
591 667
592 private void addArchivedReference (T) (T value, DataType id) 668 private void addArchivedReference (T) (T value, DataType id)
593 { 669 {
594 static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`)); 670 static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`));
599 private void addUnarchivedReference (T) (T value, DataType id) 675 private void addUnarchivedReference (T) (T value, DataType id)
600 { 676 {
601 static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`)); 677 static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`));
602 678
603 unarchivedReferences[id] = cast(void*) value; 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;
604 } 687 }
605 688
606 private DataType getArchivedReference (T) (T value) 689 private DataType getArchivedReference (T) (T value)
607 { 690 {
608 if (auto tmp = cast(void*) value in archivedReferences) 691 if (auto tmp = cast(void*) value in archivedReferences)
614 private T* getUnarchivedReference (T) (DataType id) 697 private T* getUnarchivedReference (T) (DataType id)
615 { 698 {
616 if (auto reference = id in unarchivedReferences) 699 if (auto reference = id in unarchivedReferences)
617 return cast(T*) reference; 700 return cast(T*) reference;
618 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
619 return null; 710 return null;
620 } 711 }
621 712
622 private DataType nextId () 713 private DataType nextId ()
623 { 714 {
637 if (element.isValid) 728 if (element.isValid)
638 return element.value; 729 return element.value;
639 730
640 return cast(DataType) null; 731 return cast(DataType) null;
641 } 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 }
642 748
643 private struct AssociativeArrayVisitor (Key, Value) 749 private struct AssociativeArrayVisitor (Key, Value)
644 { 750 {
645 private XMLArchive archive; 751 private XMLArchive archive;
646 752
675 } 781 }
676 782
677 return result; 783 return result;
678 } 784 }
679 } 785 }
786
787 public void postProcess ()
788 {
789 bool foundSlice = true;
790
791 foreach (slice, sliceNode ; arraysToBeArchived)
792 {
793 foreach (array, arrayNode ; arraysToBeArchived)
794 {
795 if (slice.isSliceOf(array) && slice != array)
796 {
797 sliceNode.parent.element(Tags.sliceTag, arrayNode.id)
798 .attribute(Attributes.keyAttribute, sliceNode.key)
799 .attribute(Attributes.offsetAttribute, toDataType((slice.ptr - array.ptr) / slice.elementSize))
800 .attribute(Attributes.lengthAttribute, toDataType(slice.length));
801
802 foundSlice = true;
803 break;
804 }
805
806 else
807 foundSlice = false;
808 }
809
810 if (!foundSlice)
811 sliceNode.parent.attach(sliceNode.node);
812 }
813 }
680 } 814 }