| 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 |
} |
|---|