Changeset 586

Show
Ignore:
Timestamp:
05/28/09 01:06:24 (3 years ago)
Author:
BCS
Message:

Added repeated object support
a few bug fixes (I think) and some cleanup

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Serial/Demarshal.d

    r585 r586  
    1414    if(str == "") throw new Exception("Unexpected end of Source"); 
    1515 
     16    char c; 
    1617    // eat whitespace. 
    17     outter: for(;;) switch(source.Peek()) 
     18    outter: for(;;) switch(c = source.Peek()) 
    1819        { 
    19         case ' ', '\n', '\r', '\v', '\t': break; 
     20        case ' ', '\n', '\r', '\v', '\t': source.Pick(c); break; 
    2021        default: break outter; 
    2122        } 
     
    3536} 
    3637 
    37  
    38 T demarshal(T)(Source!(char) source) 
     38struct OutMap 
    3939{ 
    40     static if(is(T == byte) ||  is(T == ubyte) ||   is(T == short) ||   is(T == ushort) || 
    41             is(T == int) ||     is(T == uint) ||    is(T == long) ||    is(T == ulong) || 
    42             is(T == float) ||   is(T == double) ||  is(T == real)) 
     40    void*[uint] map; 
     41    bool Hold(uint sn, void* ptr) 
    4342    { 
    44         auto ret = DemarshalNative!(T)(source); 
    45         //writef("%s (%s)\n", ret, T.stringof); 
    46         return ret; 
     43        if(sn in map) return false; 
     44        map[sn] = ptr; 
     45        return true; 
     46         
    4747    } 
    48     else static if(is(T == struct)
     48    bool Get(uint sn, ref void* ptr
    4949    { 
    50         static assert(is(typeof(T.DemarshalMe(source))), T.stringof~" doesn't define DemarshalMe"); 
    51         return T.DemarshalMe(source); 
     50        if(auto pptr = sn in map) 
     51        { 
     52            ptr = *pptr; 
     53            return true; 
     54        } 
     55        return false; 
    5256    } 
    53     else static if(is(T == class)) 
    54     { 
    55         static assert(is(typeof(T.DemarshalMe(source))), T.stringof~" doesn't define DemarshalMe"); 
    56         return T.DemarshalMe(source); 
    57     } 
    58     else static if(is(T == interface)) 
    59     { 
    60         static assert(false,"Can't Marshal type "~T.stringof~", interfaces don't work yet"); 
    61     } 
    62     else  
    63         static assert(false); 
    6457} 
    6558 
    6659template DemarshalMixin() 
    6760{ 
    68     static utill.Usefull!(typeof(this)).BaseType DemarshalMe(Source!(char) source) 
     61    static utill.Usefull!(typeof(this)).BaseType Deserialize(Source!(char) source) 
     62    { 
     63        mixin utill.Usefull!(typeof(this)); 
     64        static const char[] name = "root"; 
     65 
     66        OutMap map; 
     67        BaseType ret; 
     68        D!(name, BaseType, CyclicType)(source,ret,map); 
     69        return ret; 
     70    } 
     71     
     72    // Entry point for hierarchy recursion 
     73    static utill.Usefull!(typeof(this)).BaseType DemarshalMe(Source!(char) source, ref OutMap map) 
    6974    { 
    7075        mixin utill.Usefull!(typeof(this)); 
     
    7580            ret = new BaseType(); 
    7681     
    77         DoIt!(BaseType)(ret, source); 
     82        DoIt!(BaseType)(ret, source, map); 
    7883        return ret; 
    7984    } 
    80      
    81     static void DoIt(ref utill.Usefull!(typeof(this)).BaseType ret, Source!(char) source) 
     85 
     86    // Shell for base class recursion  
     87    private static void DoIt(ref utill.Usefull!(typeof(this)).BaseType ret, Source!(char) source, ref OutMap map) 
    8288    { 
    8389        mixin utill.Usefull!(typeof(this)); 
     90 
    8491        static if(is(BaseType == class)) 
    8592        { 
     
    9097                { 
    9198                    Super sret = ret; 
    92                     Super.DoIt(sret, source); 
     99                    Super.DoIt(sret, source, map); 
    93100                } 
    94101            } 
    95102        } 
    96103     
    97         foreach(i,_;ret.tupleof) 
     104        foreach(i,v;ret.tupleof) 
    98105        { 
    99106            static const name = TrimType(BaseType.tupleof[i].stringof); 
    100             static if(is(typeof(_) == class)) 
    101             { 
    102                 //writef(" is class (%s)\n", "<"~name~">NULL</"~name~">"); 
    103                 if(source.Pick("<"~name~">NULL</"~name~">")) 
    104                 { 
    105                     //writef(" is null\n"); 
    106                     _ = null; 
    107                 } 
    108                 else 
    109                 { 
    110                     source.Pick("<"~name~" type=\""); 
    111                     char[] type = XML.ReadContentXML!('\"')(source); 
    112                     source.Pick("\">"); 
    113                     if(auto fact = type in .Serialize.Factories) 
    114                     { 
    115                         (ret.tupleof)[i] = cast(typeof(BaseType.tupleof[i]))(*fact)(source); 
    116                         assert((ret.tupleof)[i] !is null, "Invvalid type returned by "~type~", expected " ~typeof(BaseType.tupleof[i]).stringof); 
    117                          
    118                     } 
    119                     else 
    120                         assert(false, "Unknown derived type "~type); 
    121                     source.Pick("</"~name~">"); 
    122                 } 
    123             } 
    124             else 
    125             { 
    126                 //writef(" is !class (%s)\n", typeof(_).stringof); 
    127                 source.Pick("<"~name~">"); 
    128                 (ret.tupleof)[i] = demarshal!(typeof(BaseType.tupleof[i]))(source); 
    129                 source.Pick("</"~name~">"); 
    130             } 
     107            D!(name, typeof(v), CyclicType)(source,(ret.tupleof)[i], map); 
    131108        } 
    132109    } 
    133110} 
     111 
     112void D(char[] name, V, bool cycle)(Source!(char) source, ref V v, ref OutMap map) 
     113{ 
     114    static if(is(V == class)) 
     115    { 
     116        if(source.Pick("<"~name~">NULL</"~name~">",false)) 
     117        { 
     118            v = null; 
     119        } 
     120        else 
     121        { 
     122            source.Pick("<"~name); 
     123 
     124            static if(cycle) 
     125            { 
     126                source.Pick(" ID=\""); 
     127                char[] ids = XML.ReadContentXML!('\"')(source); 
     128                source.Pick("\""); 
     129 
     130                uint id = toUint(ids); 
     131                void* vp; 
     132                if(source.Pick("/>",false)) 
     133                { 
     134                    if(!map.Get(id, vp)) throw new Error("Back ref not found: "~ids); 
     135                    v = cast(typeof(v))vp; 
     136                    return; 
     137                } 
     138            } 
     139             
     140 
     141            source.Pick(" type=\""); 
     142            char[] type = XML.ReadContentXML!('\"')(source); 
     143            source.Pick("\">"); 
     144            if(auto fact = type in .Serialize.Factories) 
     145            { 
     146                v = cast(V)(*fact)(source,map); 
     147                assert(v !is null, "Invalid type returned by "~type~", expected " ~V.stringof); 
     148            } 
     149            else 
     150                throw new Error("Unknown derived type "~type); 
     151 
     152            source.Pick("</"~name~">"); 
     153 
     154            static if(cycle) map.Hold(id,cast(void*)v); 
     155        } 
     156    } 
     157    else static if(is(V == struct) || (is(V S == S*) && is(S==struct))) 
     158    { 
     159        source.Pick("<"~name~">"); 
     160        v = V.DemarshalMe(source, map); 
     161        source.Pick("</"~name~">"); 
     162    } 
     163    else 
     164    { 
     165        source.Pick("<"~name~">"); 
     166        v = DemarshalNative!(V)(source); 
     167        source.Pick("</"~name~">"); 
     168    } 
     169 
     170} 
  • trunk/Serial/Marshal.d

    r585 r586  
    1414void MarshalNative(T)(Sink!(char) sink, T t) 
    1515{ 
    16     sink.Dump(std.string.format("%s", t)); 
     16    static if(is(T == int) || is(T == uint) || is(T == long) 
     17            || is(T == ulong) || is(T == short) ||is(T == ushort) 
     18            || is(T == byte) || is(T == ubyte) || is(T == float) 
     19            || is(T == double) || is(T == real)) 
     20        sink.Dump(std.string.format("%s", t)); 
     21    else static assert(false, "Don't known how to Marshal "~T.stringof); 
    1722} 
    1823 
    19 void marshal(S,T)(S sink, T t) 
     24struct InMap 
    2025{ 
    21     static assert(is(S : Sink!(char))); 
    22  
    23     static if(is(T == byte) ||  is(T == ubyte) ||   is(T == short) ||   is(T == ushort) || 
    24             is(T == int) ||     is(T == uint) ||    is(T == long) ||    is(T == ulong) || 
    25             is(T == float) ||   is(T == double) ||  is(T == real)) 
    26             MarshalNative!(T)(sink,t); 
    27     else static if(is(T == struct)) 
     26    uint at = 0; 
     27    uint[void*] map; 
     28     
     29    bool Hold(void* ptr, ref uint sn) 
    2830    { 
    29         static assert(is(typeof(T.MarshalMe(sink))), T.stringof~" doesn't define MarshalMe"); 
    30         t.MarshalMe(sink); 
     31        if(auto snp = ptr in map) 
     32        { 
     33            sn = *snp; 
     34            return true; 
     35        } 
     36        else 
     37        { 
     38            sn = at; 
     39            at++; 
     40            map[ptr] = sn; 
     41            return false; 
     42        } 
    3143    } 
    32     else static if(is(T == class)) 
    33     { 
    34         static assert(is(typeof(T.MarshalMe(sink))), T.stringof~" doesn't define MarshalMe"); 
    35         assert(t !is null); 
    36         t.MarshalMe(sink); 
    37     } 
    38     else static if(is(T == interface)) 
    39         static assert(false,"Can't Marshal type "~T.stringof~", interfaces don't work yet"); 
    40     else  
    41         static assert(false); 
    4244} 
    43  
    4445 
    4546template MarshalMixin() 
    4647{ 
    47     void MarshalMe(Sink!(char) sink) 
     48    void Serialize(Sink!(char) sink) 
    4849    { 
     50        InMap map; 
     51        static const char[] name = "root"; 
     52        M!(name,typeof(this),CyclicType)(sink,this,map); 
     53    } 
     54 
     55    void MarshalMe(Sink!(char) sink, ref InMap map) 
     56    { 
     57        //writef("Doing %s\n", typeof(this).stringof); 
    4958        mixin utill.Usefull!(typeof(this)); 
    5059 
    51         static if(is(typeof(super.MarshalMe(sink)))) 
    52                 super.MarshalMe(sink); 
     60        static if(is(typeof(this) == class)) 
     61        { 
     62            static if(is(typeof(super.MarshalMe(sink,map)))) 
     63                super.MarshalMe(sink,map); 
     64        } 
    5365 
    54         foreach(i,_;this.tupleof) 
     66        foreach(i,v;this.tupleof) 
    5567        { 
    5668            static const name = TrimType(BaseType.tupleof[i].stringof); 
    57              
    58             static if(is(typeof(_) == class)) 
     69            M!(name,typeof(v),CyclicType)(sink,v,map); 
     70        } 
     71    } 
     72
     73 
     74void M(char[] name, V, bool cycle)(Sink!(char)sink, V v, ref InMap map) 
     75
     76    static if(is(typeof(v) == class)) 
     77    { 
     78        if(v is null) 
     79        { 
     80            sink.Dump("<"~name~">NULL</"~name~">"); 
     81        } 
     82        else 
     83        { 
     84            sink.Dump("<"~name); 
     85            static if(cycle) 
    5986            { 
    60                 if((this.tupleof)[i] is null) 
     87                uint id; 
     88                if(map.Hold(cast(void*)v,id)) 
    6189                { 
    62                     sink.Dump("<"~name~">NULL</"~name~">"); 
     90                    sink.Dump(std.string.format(" ID=\"%s\"/>", id)); 
     91                    return; 
    6392                } 
    6493                else 
    6594                { 
    66                     sink.Dump("<"~name~" type=\""); 
    67                     XML.WriteContentXML(sink,_.Tag()); 
    68                     sink.Dump("\">"); 
    69                     marshal(sink, (this.tupleof)[i]); 
    70                     sink.Dump("</"~name~">"); 
     95                    sink.Dump(std.string.format(" ID=\"%s\"", id)); 
    7196                } 
    7297            } 
    73             else 
    74             { 
    75                 sink.Dump("<"~name~">"); 
    76                 marshal(sink, (this.tupleof)[i]); 
    77                 sink.Dump("</"~name~">"); 
    78             } 
     98            sink.Dump(" type=\""); 
     99            XML.WriteContentXML(sink,v.TypeTag()); 
     100            sink.Dump("\">"); 
     101            v.MarshalMe(sink,map); 
     102            sink.Dump("</"~name~">"); 
    79103        } 
    80104    } 
     105    else static if(is(utill.Usefull!(V).BaseType == struct)) 
     106    { 
     107        sink.Dump("<"~name~">"); 
     108        v.MarshalMe(sink,map); 
     109        sink.Dump("</"~name~">"); 
     110    } 
     111    else 
     112    { 
     113        sink.Dump("<"~name~">"); 
     114        MarshalNative!(typeof(v))(sink,v); 
     115        sink.Dump("</"~name~">"); 
     116    } 
    81117} 
  • trunk/Serial/Serialize.d

    r585 r586  
    22 
    33import utill; 
    4 public import Interface; 
    54import XML; 
    65 
    7 alias Object function(Source!(char) source) Factory; 
    8 Factory[char[]] Factories; 
     6public import Interface; 
     7public import Marshal; 
     8public import Demarshal; 
     9public import Common; 
    910 
    1011/** 
     
    1516template Serializable() 
    1617{ 
     18    const bool CyclicType = false; 
     19 
    1720    mixin MarshalMixin!(); 
    1821    mixin DemarshalMixin!(); 
     22    mixin CommonMixin!(); 
     23} 
    1924 
    20     static if(is(typeof(this) == class)) 
    21     { 
    22         static char[] sTag() { return typeof(this).stringof; } 
    23          
    24         char[] Tag() { return sTag(); } 
    25          
    26         static this() 
    27         { 
    28             Factories[sTag()] = function Object(Source!(char) source) 
    29             { 
    30                 return DemarshalMe(source); 
    31             }; 
    32         } 
    33     } 
     25/** 
     26 * Mixin template that attempt to "do the right" thing for general cases 
     27 * Handels repeated instances of the same object (hard links) 
     28 *   
     29 * Authors: Benjamin 
     30 */ 
     31template SerializableRecuring() 
     32
     33    const bool CyclicType = true; 
    3434 
     35    mixin MarshalMixin!(); 
     36    mixin DemarshalMixin!(); 
     37    mixin CommonMixin!(); 
    3538} 
  • trunk/Serial/test1.d

    r585 r586  
    44import std.string; 
    55 
    6 import Marshal; 
    7 import Demarshal; 
    86import Serialize; 
    97import StringSourceSink; 
     
    119class CS 
    1210{ 
    13     mixin Serializable!(); 
     11    mixin SerializableRecuring!(); 
    1412 
    1513    int i = 5;  float j = 3.1415926; 
     
    2321class DS : CS 
    2422{ 
    25     mixin Serializable!(); 
     23    mixin SerializableRecuring!(); 
    2624 
    2725    real f = 2.717; 
     
    4442} 
    4543 
     44struct SC 
     45{ 
     46    mixin SerializableRecuring!(); 
     47    CS a; 
     48    CS b; 
     49    char[] toString() { return format("<%s,%s>", this.tupleof); } 
     50} 
     51 
    4652void main() 
    4753{ 
    4854    SS ss = SS(42, 2.717, null); 
     55    SC sc; 
    4956    Si c; 
    5057 
    51     ss.cs = null; 
    52     c = new Si();  marshal(c,ss);  writef("%s\n\t%s\n", c.get, SS.DemarshalMe(new So(c.get))); 
     58    ss.cs = null;      c = new Si(); 
     59    ss.Serialize(c);   writef("%s\n\t%s\n", c.get, SS.Deserialize(new So(c.get))); 
    5360     
    54     ss.cs = new CS(1); 
    55     c = new Si();   marshal(c,ss);  writef("%s\n\t%s\n", c.get, SS.DemarshalMe(new So(c.get))); 
     61    ss.cs = new CS(1);  c = new Si(); 
     62    ss.Serialize(c);    writef("%s\n\t%s\n", c.get, SS.Deserialize(new So(c.get))); 
     63     
     64    ss.cs = new DS(1);  c = new Si(); 
     65    ss.Serialize(c);    writef("%s\n\t%s\n", c.get, SS.Deserialize(new So(c.get))); 
    5666 
    57     ss.cs = new DS(1); 
    58     c = new Si();   marshal(c,ss);  writef("%s\n\t%s\n", c.get, SS.DemarshalMe(new So(c.get))); 
     67    c = new Si();    
     68    (new DS(1)).Serialize(c);   writef("%s\n\t%s\n", c.get, CS.Deserialize(new So(c.get))); 
     69                 
     70     
     71    sc.a = new CS(1);   sc.b = new CS(1);   c = new Si();   sc.Serialize(c); 
     72    auto same = SC.Deserialize(new So(c.get)); 
     73    writef("%s\n\t%s\n", c.get, same); 
     74    assert(same.a !is same.b); 
     75     
     76    sc.b = sc.a;    c = new Si();   sc.Serialize(c); 
     77    auto dif = SC.Deserialize(new So(c.get)); 
     78    writef("%s\n\t%s\n", c.get, dif); 
     79    assert(dif.a is dif.b); 
    5980} 
  • trunk/Serial/utill.d

    r585 r586  
    1111    else static if(is(T == class)) 
    1212        alias T BaseType; 
    13     else 
    14         static assert(false, T.stringof); 
    1513}