root/trunk/Serial/Demarshal.d

Revision 591, 4.7 kB (checked in by BCS, 3 years ago)

Added support for 3rd party types and arrays

Line 
1 module Demarshal;
2
3 import std.conv;
4 import std.stdio;
5
6 import Serialize;
7 import utill;
8 import Third;
9 import XML;
10 import State;
11
12
13 T DemarshalNative(T)(Source!(char) source, ref OutMap map)
14 {
15
16     static if(is(T == char[]))
17     {
18         char[] str = ReadContentXML(source);
19         return str;
20     }
21     else static if(is(T B == B[]))
22     {
23         T t;
24         //writef("reading list of "~B.stringof~"\n");
25         if(source.Pick("null",false))
26         {
27             //writef("Found empty\n");
28             t.length = 0;
29         }
30         else
31         {
32             //writef("Found non empty\n");
33             t.length = 16;
34             int at = 0;
35             static if(NativeBaseType!(B))
36             {
37                 do
38                 {
39                     if(at >= t.length) t.length = 2*at;
40                     //writef(".");
41                     t[at++] = DemarshalNative!(B)(source,map);
42                     //writef(".\n");
43                 }while(source.Pick(",",false));
44             }
45             else
46             {
47                 const static char[] tag = NameFromType!(B);
48                 while(source.Peek("<"~tag~">"))
49                 {
50                     if(at >= t.length) t.length = 2*at;
51                     D!(tag,B)(source,t[at],map);
52                     at++;
53                 }
54             }
55             t.length = at;
56         }
57         return t;
58     }
59     else
60     {
61         char[] str = ReadContentXML!("<,")(source);
62         if(str == "") throw new Exception("Unexpected end of Source while looking for '"~T.stringof~"'");
63    
64         static if(is(T == int))         return toInt(str);
65         else static if(is(T == uint))   return toUint(str);
66         else static if(is(T == long))   return toLong(str);
67         else static if(is(T == ulong))  return toUlong(str);
68         else static if(is(T == short))  return toShort(str);
69         else static if(is(T == ushort)) return toUshort(str);
70         else static if(is(T == byte))   return toByte(str);
71         else static if(is(T == ubyte))  return toUbyte(str);
72         else static if(is(T == float))  return toFloat(str);
73         else static if(is(T == double)) return toDouble(str);
74         else static if(is(T == real))   return toReal(str);
75         else static assert(false, "Don't known how to Demarshal "~T.stringof);
76     }
77 }
78
79 template DemarshalMixin()
80 {
81     static utill.Usefull!(typeof(this)).BaseType Deserialize(Source!(char) source)
82     {
83         mixin utill.Usefull!(typeof(this));
84         static const char[] name = "root";
85
86         OutMap map;
87         BaseType ret;
88         D!(name, BaseType)(source,ret,map);
89         return ret;
90     }
91    
92     // Entry point for hierarchy recursion
93     static utill.Usefull!(typeof(this)).BaseType DemarshalMe(Source!(char) source, ref OutMap map)
94     {
95         mixin utill.Usefull!(typeof(this));
96    
97         BaseType ret;
98        
99         static if(is(BaseType == class))
100             ret = new BaseType();
101    
102         DoIt!(BaseType)(ret, source, map);
103         return ret;
104     }
105
106     // Shell for base class recursion
107     private static void DoIt(ref utill.Usefull!(typeof(this)).BaseType ret, Source!(char) source, ref OutMap map)
108     {
109         mixin utill.Usefull!(typeof(this));
110
111         static if(is(BaseType == class))
112         {
113             static if(is(BaseType SuperT == super))
114             {
115                 alias SuperT[0] Super;
116                 static if(!is(Super == Object))
117                 {
118                     Super sret = ret;
119                     Super.DoIt(sret, source, map);
120                 }
121             }
122         }
123    
124         foreach(i,v;ret.tupleof)
125         {
126             static const name = TrimType(BaseType.tupleof[i].stringof);
127             D!(name, typeof(v))(source,(ret.tupleof)[i], map);
128         }
129     }
130 }
131
132 void D(char[] name, V)(Source!(char) source, ref V v, ref OutMap map)
133 {
134     static if(is(typeof(&v.MarshalMe)))
135     {
136         static if(is(V == class))
137         {
138             if(source.Pick("<"~name~">NULL</"~name~">",false))
139             {
140                 v = null;
141             }
142             else
143             {
144                 source.Pick("<"~name);
145    
146                 static if(is(typeof(typeof(v).CyclicType)) && typeof(v).CyclicType)
147                 {
148                     source.Pick(" ID=\"");
149                     char[] ids = XML.ReadContentXML!("\"")(source);
150                     source.Pick("\"");
151    
152                     uint id = toUint(ids);
153                     void* vp;
154                     if(source.Pick("/>",false))
155                     {
156                         if(!map.Get(id, vp)) throw new Error("Back ref not found: "~ids);
157                         v = cast(typeof(v))vp;
158                         return;
159                     }
160                 }
161                
162    
163                 source.Pick(" type=\"");
164                 char[] type = XML.ReadContentXML!("\"")(source);
165                 source.Pick("\">");
166                 if(auto fact = type in .Serialize.Factories)
167                 {
168                     v = cast(V)(*fact)(source,map);
169                     assert(v !is null, "Invalid type returned by "~type~", expected " ~V.stringof);
170                 }
171                 else
172                     throw new Error("Unknown derived type "~type);
173    
174                 source.Pick("</"~name~">");
175    
176                 static if(is(typeof(typeof(v).CyclicType)) && typeof(v).CyclicType)
177                     map.Hold(id,cast(void*)v);
178             }
179         }
180         else static if(is(V == struct))
181         {
182             source.Pick("<"~name~">");
183             v = V.DemarshalMe(source, map);
184             source.Pick("</"~name~">");
185         }
186         else static assert(false, "Internal Error");
187     }
188     else static if(is(V == struct) || is(V == class))
189     {
190         source.Pick("<"~name~">");
191         v = ThirdPartyAccess!(V).demarshial(SourceHandle(&map, source));
192         source.Pick("</"~name~">");
193     }
194     else
195     {
196         source.Pick("<"~name~">");
197         v = DemarshalNative!(V)(source,map);
198         source.Pick("</"~name~">");
199     }
200
201 }
Note: See TracBrowser for help on using the browser.