Mercurial > projects > orange
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) |