Mercurial > projects > orange
annotate orange/serialization/archives/XMLArchive.d @ 18:3d42ea434d46
Added an error callback. Fixes #3 and #4.
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Thu, 12 Aug 2010 23:24:51 +0200 |
parents | 27c5b6c5425f |
children | 8ab9588b92bf 9a575087b961 |
rev | line source |
---|---|
0 | 1 /** |
2 * Copyright: Copyright (c) 2010 Jacob Carlborg. | |
3 * Authors: Jacob Carlborg | |
4 * Version: Initial created: Jan 26, 2010 | |
5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) | |
6 */ | |
7 module orange.serialization.archives.XMLArchive; | |
8 | |
9 version (Tango) | |
10 import tango.util.Convert : to; | |
11 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
12 else |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
13 import std.conv; |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
14 |
0 | 15 import orange.serialization.archives._; |
16 import orange.util._; | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
17 import orange.xml.XMLDocument; |
0 | 18 |
19 private enum ArchiveMode | |
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 | |
30 { | |
31 static const DataType structTag = "struct"; | |
32 static const DataType dataTag = "data"; | |
33 static const DataType archiveTag = "archive"; | |
34 static const DataType arrayTag = "array"; | |
35 static const DataType objectTag = "object"; | |
36 static const DataType baseTag = "base"; | |
37 static const DataType stringTag = "string"; | |
38 static const DataType referenceTag = "reference"; | |
39 static const DataType pointerTag = "pointer"; | |
40 static const DataType associativeArrayTag = "associativeArray"; | |
41 static const DataType typedefTag = "typedef"; | |
42 static const DataType nullTag = "null"; | |
43 static const DataType enumTag = "enum"; | |
44 } | |
45 | |
46 private struct Attributes | |
47 { | |
48 static const DataType typeAttribute = "type"; | |
49 static const DataType versionAttribute = "version"; | |
50 static const DataType lengthAttribute = "length"; | |
51 static const DataType keyAttribute = "key"; | |
52 static const DataType runtimeTypeAttribute = "runtimeType"; | |
53 static const DataType idAttribute = "id"; | |
54 static const DataType keyTypeAttribute = "keyType"; | |
55 static const DataType valueTypeAttribute = "valueType"; | |
56 } | |
57 | |
58 private | |
59 { | |
60 DataType archiveType = "org.dsource.orange.xml"; | |
61 DataType archiveVersion = "0.1"; | |
62 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
63 XMLDocument!(U) doc; |
0 | 64 doc.Node lastElement; |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
65 //DocPrinter!(U) printer; |
0 | 66 doc.Node lastElementSaved; |
67 | |
68 bool hasBegunArchiving; | |
69 bool hasBegunUnarchiving; | |
70 | |
71 DataType[void*] archivedReferences; | |
72 void*[DataType] unarchivedReferences; | |
73 | |
74 size_t idCounter; | |
75 } | |
76 | |
77 this () | |
78 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
79 doc = new XMLDocument!(U); |
0 | 80 } |
81 | |
82 public void beginArchiving () | |
83 { | |
84 if (!hasBegunArchiving) | |
85 { | |
86 doc.header; | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
87 lastElement = doc.tree.element(Tags.archiveTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
88 .attribute(Attributes.typeAttribute, archiveType) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
89 .attribute(Attributes.versionAttribute, archiveVersion); |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
90 lastElement = lastElement.element(Tags.dataTag); |
0 | 91 |
92 hasBegunArchiving = true; | |
93 } | |
94 } | |
95 | |
96 public void beginUnarchiving (DataType data) | |
97 { | |
98 if (!hasBegunUnarchiving) | |
99 { | |
100 doc.parse(data); | |
101 hasBegunUnarchiving = true; | |
102 | |
103 auto set = doc.query[Tags.archiveTag][Tags.dataTag]; | |
104 | |
105 if (set.nodes.length == 1) | |
106 lastElement = set.nodes[0]; | |
107 | |
108 else | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
109 { |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
110 if (errorCallback) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
111 { |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
112 if (set.nodes.length == 0) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
113 errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `The "` ~ to!(string)(Tags.dataTag) ~ `" tag could not be found.`, __FILE__, __LINE__), [Tags.dataTag]); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
114 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
115 else |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
116 errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `There were more than one "` ~ to!(string)(Tags.dataTag) ~ `" tag.`, __FILE__, __LINE__), [Tags.dataTag]); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
117 } |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
118 } |
0 | 119 } |
120 } | |
121 | |
122 public DataType data () | |
123 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
124 /*if (!printer) |
0 | 125 printer = new DocPrinter!(U); |
126 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
127 return printer.print(doc);*/ |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
128 |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
129 return doc.toString(); |
0 | 130 } |
131 | |
132 public void reset () | |
133 { | |
134 hasBegunArchiving = false; | |
135 hasBegunUnarchiving = false; | |
136 idCounter = 0; | |
137 doc.reset; | |
138 } | |
139 | |
140 private void begin () | |
141 { | |
142 lastElementSaved = lastElement; | |
143 } | |
144 | |
145 private void end () | |
146 { | |
147 lastElement = lastElementSaved; | |
148 } | |
149 | |
150 public void archive (T) (T value, DataType key, void delegate () dg = null) | |
151 { | |
152 if (!hasBegunArchiving) | |
153 beginArchiving(); | |
154 | |
155 restore(lastElement) in { | |
156 bool callDelegate = true; | |
157 | |
158 static if (isTypeDef!(T)) | |
159 archiveTypeDef(value, key); | |
160 | |
161 else static if (isObject!(T)) | |
162 archiveObject(value, key, callDelegate); | |
163 | |
164 else static if (isStruct!(T)) | |
165 archiveStruct(value, key); | |
166 | |
167 else static if (isString!(T)) | |
168 archiveString(value, key); | |
169 | |
170 else static if (isArray!(T)) | |
171 archiveArray(value, key); | |
172 | |
173 else static if (isAssociativeArray!(T)) | |
174 archiveAssociativeArray(value, key); | |
175 | |
176 else static if (isPrimitive!(T)) | |
177 archivePrimitive(value, key); | |
178 | |
179 else static if (isPointer!(T)) | |
180 archivePointer(value, key, callDelegate); | |
181 | |
182 else static if (isEnum!(T)) | |
183 archiveEnum(value, key); | |
184 | |
185 else | |
186 static assert(false, format!(`The type "`, T, `" cannot be archived.`)); | |
187 | |
188 if (callDelegate && dg) | |
189 dg(); | |
190 }; | |
191 } | |
192 | |
193 private void archiveObject (T) (T value, DataType key, ref bool callDelegate) | |
194 { | |
195 if (!value) | |
196 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
197 lastElement.element(Tags.nullTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
198 .attribute(Attributes.typeAttribute, toDataType(T.stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
199 .attribute(Attributes.keyAttribute, key); |
0 | 200 callDelegate = false; |
201 } | |
202 | |
203 else if (auto reference = getArchivedReference(value)) | |
204 { | |
205 archiveReference(key, reference); | |
206 callDelegate = false; | |
207 } | |
208 | |
209 else | |
210 { | |
211 DataType id = nextId; | |
212 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
213 lastElement = lastElement.element(Tags.objectTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
214 .attribute(Attributes.runtimeTypeAttribute, toDataType(value.classinfo.name)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
215 .attribute(Attributes.typeAttribute, toDataType(T.stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
216 .attribute(Attributes.keyAttribute, key) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
217 .attribute(Attributes.idAttribute, id); |
0 | 218 |
219 addArchivedReference(value, id); | |
220 } | |
221 } | |
222 | |
223 private void archiveStruct (T) (T value, DataType key) | |
224 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
225 lastElement = lastElement.element(Tags.structTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
226 .attribute(Attributes.typeAttribute, toDataType(T.stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
227 .attribute(Attributes.keyAttribute, key); |
0 | 228 } |
229 | |
230 private void archiveString (T) (T value, DataType key) | |
231 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
232 lastElement.element(Tags.stringTag, toDataType(value)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
233 .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfArray!(T).stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
234 .attribute(Attributes.keyAttribute, key); |
0 | 235 } |
236 | |
237 private void archiveArray (T) (T value, DataType key) | |
238 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
239 lastElement = lastElement.element(Tags.arrayTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
240 .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfArray!(T).stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
241 .attribute(Attributes.lengthAttribute, toDataType(value.length)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
242 .attribute(Attributes.keyAttribute, key); |
0 | 243 } |
244 | |
245 private void archiveAssociativeArray (T) (T value, DataType key) | |
246 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
247 lastElement = lastElement.element(Tags.associativeArrayTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
248 .attribute(Attributes.keyTypeAttribute, toDataType(KeyTypeOfAssociativeArray!(T).stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
249 .attribute(Attributes.valueTypeAttribute, toDataType(ValueTypeOfAssociativeArray!(T).stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
250 .attribute(Attributes.lengthAttribute, toDataType(value.length)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
251 .attribute(Attributes.keyAttribute, key); |
0 | 252 } |
253 | |
254 private void archivePointer (T) (T value, DataType key, ref bool callDelegate) | |
255 { | |
256 if (auto reference = getArchivedReference(value)) | |
257 { | |
258 archiveReference(key, reference); | |
259 callDelegate = false; | |
260 } | |
261 | |
262 else | |
263 { | |
264 DataType id = nextId; | |
265 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
266 lastElement = lastElement.element(Tags.pointerTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
267 .attribute(Attributes.keyAttribute, key) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
268 .attribute(Attributes.idAttribute, id); |
0 | 269 |
270 addArchivedReference(value, id); | |
271 } | |
272 } | |
273 | |
274 private void archiveEnum (T) (T value, DataType key) | |
275 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
276 lastElement.element(Tags.enumTag, toDataType(value)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
277 .attribute(Attributes.typeAttribute, toDataType(T.stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
278 .attribute(Attributes.keyAttribute, key); |
0 | 279 } |
280 | |
281 private void archivePrimitive (T) (T value, DataType key) | |
282 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
283 lastElement.element(toDataType(T.stringof), toDataType(value)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
284 .attribute(Attributes.keyAttribute, key); |
0 | 285 } |
286 | |
287 private void archiveTypeDef (T) (T value, DataType key) | |
288 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
289 lastElement = lastElement.element(Tags.typedefTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
290 .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfTypeDef!(T).stringof)); |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
291 .attribute(Attributes.key, key); |
0 | 292 } |
293 | |
294 public T unarchive (T) (DataType key, T delegate (T) dg = null) | |
295 { | |
296 if (!hasBegunUnarchiving) | |
297 beginUnarchiving(data); | |
298 | |
299 return restore!(T)(lastElement) in { | |
300 T value; | |
301 | |
302 bool callDelegate = true; | |
303 | |
304 static if (isTypeDef!(T)) | |
305 value = unarchiveTypeDef!(T)(key); | |
306 | |
307 else static if (isObject!(T)) | |
308 value = unarchiveObject!(T)(key, callDelegate); | |
309 | |
310 else static if (isStruct!(T)) | |
311 value = unarchiveStruct!(T)(key); | |
312 | |
313 else static if (isString!(T)) | |
314 value = unarchiveString!(T)(key); | |
315 | |
316 else static if (isArray!(T)) | |
317 value = unarchiveArray!(T)(key); | |
318 | |
319 else static if (isAssociativeArray!(T)) | |
320 value = unarchiveAssociativeArray!(T)(key); | |
321 | |
322 else static if (isPrimitive!(T)) | |
323 value = unarchivePrimitive!(T)(key); | |
324 | |
325 else static if (isPointer!(T)) | |
326 value = unarchivePointer!(T)(key, callDelegate); | |
327 | |
328 else static if (isEnum!(T)) | |
329 value = unarchiveEnum!(T)(key); | |
330 | |
331 else | |
332 static assert(false, format!(`The type "`, T, `" cannot be unarchived.`)); | |
333 | |
334 if (callDelegate && dg) | |
335 return dg(value); | |
336 | |
337 return value; | |
338 }; | |
339 } | |
340 | |
341 private T unarchiveObject (T) (DataType key, ref bool callDelegate) | |
342 { | |
343 DataType id = unarchiveReference(key); | |
344 | |
345 if (auto reference = getUnarchivedReference!(T)(id)) | |
346 { | |
347 callDelegate = false; | |
348 return *reference; | |
349 } | |
350 | |
351 auto tmp = getElement(Tags.objectTag, key, Attributes.keyAttribute, false); | |
11
27c5b6c5425f
Deserialization now works as well using D2. Compiles again with D1 and Tango. Cleaned up orange.util.io a bit.
Jacob Carlborg <doob@me.com>
parents:
10
diff
changeset
|
352 |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
353 if (!tmp.isValid) |
0 | 354 { |
355 lastElement = getElement(Tags.nullTag, key); | |
356 callDelegate = false; | |
357 return null; | |
358 } | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
359 |
0 | 360 lastElement = tmp; |
361 | |
362 auto runtimeType = getValueOfAttribute(Attributes.runtimeTypeAttribute); | |
363 auto name = fromDataType!(string)(runtimeType); | |
364 id = getValueOfAttribute(Attributes.idAttribute); | |
365 | |
366 T result; | |
367 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
368 /*static if (is(typeof(T._ctor))) |
0 | 369 { |
370 ParameterTupleOf!(typeof(T._ctor)) params; | |
371 result = factory!(T, typeof(params))(name, params); | |
372 } | |
373 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
374 else*/ |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
375 result = cast(T) newInstance(name); |
0 | 376 |
377 addUnarchivedReference(result, id); | |
378 | |
379 return result; | |
380 } | |
381 | |
382 private T unarchiveStruct (T) (DataType key) | |
383 { | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
384 auto element = getElement(Tags.structTag, key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
385 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
386 if (element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
387 lastElement = element; |
0 | 388 |
389 return T.init; | |
390 } | |
391 | |
392 private T unarchiveString (T) (DataType key) | |
393 { | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
394 auto element = getElement(Tags.stringTag, key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
395 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
396 if (!element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
397 return T.init; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
398 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
399 return fromDataType!(T)(element.value); |
0 | 400 } |
401 | |
402 private T unarchiveArray (T) (DataType key) | |
403 { | |
404 T value; | |
405 | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
406 auto element = getElement(Tags.arrayTag, key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
407 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
408 if (!element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
409 return T.init; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
410 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
411 lastElement = element; |
0 | 412 auto length = getValueOfAttribute(Attributes.lengthAttribute); |
413 value.length = fromDataType!(size_t)(length); | |
414 | |
415 return value; | |
416 } | |
417 | |
418 private T unarchiveAssociativeArray (T) (DataType key) | |
419 { | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
420 auto element = getElement(Tags.associativeArrayTag, key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
421 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
422 if (element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
423 lastElement = element; |
0 | 424 |
425 return T.init; | |
426 } | |
427 | |
428 private T unarchivePointer (T) (DataType key, ref bool callDelegate) | |
429 { | |
430 DataType id = unarchiveReference(key); | |
431 | |
432 if (auto reference = getUnarchivedReference!(T)(id)) | |
433 { | |
434 callDelegate = false; | |
435 return *reference; | |
436 } | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
437 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
438 auto element = getElement(Tags.pointerTag, key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
439 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
440 if (!element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
441 return T.init; |
0 | 442 |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
443 lastElement = element; |
0 | 444 id = getValueOfAttribute(Attributes.idAttribute); |
445 | |
446 T result = new BaseTypeOfPointer!(T); | |
447 | |
448 addUnarchivedReference(result, id); | |
449 | |
450 return result; | |
451 } | |
452 | |
453 private T unarchiveEnum (T) (DataType key) | |
454 { | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
455 auto element = getElement(Tags.enumTag, key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
456 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
457 if (!element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
458 return T.init; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
459 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
460 return fromDataType!(T)(element.value); |
0 | 461 } |
462 | |
463 private T unarchivePrimitive (T) (DataType key) | |
464 { | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
465 auto element = getElement(toDataType(T.stringof), key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
466 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
467 if (!element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
468 return T.init; |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
469 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
470 return fromDataType!(T)(element.value); |
0 | 471 } |
472 | |
473 private T unarchiveTypeDef (T) (DataType key) | |
474 { | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
475 auto element = getElement(Tags.typedefTag, key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
476 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
477 if (element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
478 lastElement = element; |
0 | 479 |
480 return T.init; | |
481 } | |
482 | |
483 public AssociativeArrayVisitor!(KeyTypeOfAssociativeArray!(T), ValueTypeOfAssociativeArray!(T)) unarchiveAssociativeArrayVisitor (T) () | |
484 { | |
485 return AssociativeArrayVisitor!(KeyTypeOfAssociativeArray!(T), ValueTypeOfAssociativeArray!(T))(this); | |
486 } | |
487 | |
488 public void archiveBaseClass (T : Object) (DataType key) | |
489 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
490 lastElement = lastElement.element(Tags.baseTag) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
491 .attribute(Attributes.typeAttribute, toDataType(T.stringof)) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
492 .attribute(Attributes.keyAttribute, key); |
0 | 493 } |
494 | |
495 public void unarchiveBaseClass (T : Object) (DataType key) | |
496 { | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
497 auto element = getElement(Tags.baseTag, key); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
498 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
499 if (element.isValid) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
500 lastElement = element; |
0 | 501 } |
502 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
503 version (Tango) |
0 | 504 { |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
505 template errorMessage (ArchiveMode mode = ArchiveMode.archiving) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
506 { |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
507 static if (mode == ArchiveMode.archiving) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
508 const errorMessage = "Could not continue archiving due to unrecognized data format: "; |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
509 |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
510 else static if (mode == ArchiveMode.unarchiving) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
511 const errorMessage = "Could not continue unarchiving due to unrecognized data format: "; |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
512 } |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
513 } |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
514 |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
515 else |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
516 { |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
517 mixin( |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
518 `template errorMessage (ArchiveMode mode = ArchiveMode.archiving) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
519 { |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
520 static if (mode == ArchiveMode.archiving) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
521 enum errorMessage = "Could not continue archiving due to unrecognized data format: "; |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
522 |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
523 else static if (mode == ArchiveMode.unarchiving) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
524 enum errorMessage = "Could not continue unarchiving due to unrecognized data format: "; |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
525 }` |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
526 ); |
0 | 527 } |
528 | |
529 private doc.Node getElement (DataType tag, DataType key, DataType attribute = Attributes.keyAttribute, bool throwOnError = true) | |
11
27c5b6c5425f
Deserialization now works as well using D2. Compiles again with D1 and Tango. Cleaned up orange.util.io a bit.
Jacob Carlborg <doob@me.com>
parents:
10
diff
changeset
|
530 { |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
531 auto set = lastElement.query[tag].attribute((doc.Node node) { |
0 | 532 if (node.name == attribute && node.value == key) |
533 return true; | |
534 | |
535 return false; | |
536 }); | |
537 | |
538 if (set.nodes.length == 1) | |
539 return set.nodes[0].parent; | |
540 | |
541 else | |
542 { | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
543 if (throwOnError && errorCallback) |
0 | 544 { |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
545 if (set.nodes.length == 0) |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
546 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]); |
0 | 547 |
548 else | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
549 errorCallback(new ArchiveException(`Could not unarchive the value with the key "` ~ to!(string)(key) ~ `" due to malformed data.`, __FILE__, __LINE__), [tag, Attributes.keyAttribute, key]); |
0 | 550 } |
11
27c5b6c5425f
Deserialization now works as well using D2. Compiles again with D1 and Tango. Cleaned up orange.util.io a bit.
Jacob Carlborg <doob@me.com>
parents:
10
diff
changeset
|
551 |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
552 return doc.Node.invalid; |
0 | 553 } |
554 } | |
555 | |
556 private DataType getValueOfAttribute (DataType attribute) | |
557 { | |
558 auto set = lastElement.query.attribute(attribute); | |
559 | |
560 if (set.nodes.length == 1) | |
561 return set.nodes[0].value; | |
562 | |
563 else | |
18
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
564 { |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
565 if (errorCallback) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
566 { |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
567 if (set.nodes.length == 0) |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
568 errorCallback(new ArchiveException(`Could not find the attribute "` ~ to!(string)(attribute) ~ `".`, __FILE__, __LINE__), [attribute]); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
569 |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
570 else |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
571 errorCallback(new ArchiveException(`Could not unarchive the value of the attribute "` ~ to!(string)(attribute) ~ `" due to malformed data.`, __FILE__, __LINE__), [attribute]); |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
572 } |
3d42ea434d46
Added an error callback. Fixes #3 and #4.
Jacob Carlborg <doob@me.com>
parents:
11
diff
changeset
|
573 } |
0 | 574 } |
575 | |
576 private void addArchivedReference (T) (T value, DataType id) | |
577 { | |
578 static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`)); | |
579 | |
580 archivedReferences[cast(void*) value] = id; | |
581 } | |
582 | |
583 private void addUnarchivedReference (T) (T value, DataType id) | |
584 { | |
585 static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`)); | |
586 | |
587 unarchivedReferences[id] = cast(void*) value; | |
588 } | |
589 | |
590 private DataType getArchivedReference (T) (T value) | |
591 { | |
592 if (auto tmp = cast(void*) value in archivedReferences) | |
593 return *tmp; | |
594 | |
595 return null; | |
596 } | |
597 | |
598 private T* getUnarchivedReference (T) (DataType id) | |
599 { | |
600 if (auto reference = id in unarchivedReferences) | |
601 return cast(T*) reference; | |
602 | |
603 return null; | |
604 } | |
605 | |
606 private DataType nextId () | |
607 { | |
608 return toDataType(idCounter++); | |
609 } | |
610 | |
611 private void archiveReference (DataType key, DataType id) | |
612 { | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
613 lastElement.element(Tags.referenceTag, id) |
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
614 .attribute(Attributes.keyAttribute, key); |
0 | 615 } |
616 | |
617 private DataType unarchiveReference (DataType key) | |
618 { | |
619 auto element = getElement(Tags.referenceTag, key, Attributes.keyAttribute, false); | |
620 | |
9
99c52d46822a
Serialization works now with D2, deserialization still doesn't work
Jacob Carlborg <doob@me.com>
parents:
6
diff
changeset
|
621 if (element.isValid) |
0 | 622 return element.value; |
623 | |
624 return cast(DataType) null; | |
625 } | |
626 | |
6 | 627 private struct AssociativeArrayVisitor (Key, Value) |
0 | 628 { |
629 private XMLArchive archive; | |
630 | |
631 static AssociativeArrayVisitor opCall (XMLArchive archive) | |
632 { | |
633 AssociativeArrayVisitor aai; | |
634 aai.archive = archive; | |
635 | |
636 return aai; | |
637 } | |
638 | |
639 int opApply(int delegate(ref Key, ref Value) dg) | |
640 { | |
641 int result; | |
642 | |
643 foreach (node ; archive.lastElement.children) | |
644 { | |
645 restore(archive.lastElement) in { | |
646 archive.lastElement = node; | |
647 | |
648 if (node.attributes.exist) | |
649 { | |
650 Key key = to!(Key)(archive.getValueOfAttribute(Attributes.keyAttribute)); | |
651 Value value = to!(Value)(node.value); | |
652 | |
653 result = dg(key, value); | |
654 } | |
655 }; | |
656 | |
657 if (result) | |
658 break; | |
659 } | |
660 | |
661 return result; | |
662 } | |
663 } | |
664 } |