YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

Squirrel serialization
Ultimate
#1 Posted : Thursday, July 24, 2014 3:33:11 PM(UTC)
Rank: Newbie

Groups: Registered
Joined: 1/14/2014(UTC)
Posts: 6
Location: france

Thanks: 0 times
Was thanked: 2 time(s) in 1 post(s)
Hi, what do you think of this implementation :
Code:
function print_r (mArray){
    if(typeof mArray == "array" || typeof mArray == "table")
        print(_print_r(mArray));
    else if(mArray == null)
        print("null\n");
    else
        print(mArray.tostring()+"\n");
}
function indent(str){
    local arr = ::split(str,"\n");
    local res = "";
    foreach(val in arr)
    {
        res += "\t"+val+"\n";
    }
    return res;   
}

function _print_r(mArray){
    local res = "";   
    foreach(key,val in mArray)
    {
        if(typeof val == "array" && val.len() != 0)
            res +=(key+" : array("+val.len()+")\n"+indent(_print_r(val))+" \n");
        else if(typeof val == "array")
            res +=(key+" : array(0)\n");
        else if(typeof val == "table" && val.len() != 0)
            res +=(key+" : table("+val.len()+")\n"+indent(_print_r(val))+" \n");
        else if(typeof val == "table")
            res +=(key+" : table(0)\n");
        else
            res += (key+" : "+val+" \n");
    }
    return res;   
}



class Serializor {
    static isUnserializing = {};
    static singleton = null;
    static types = {
        i = function(data,register = null){return data.tointeger()},
        s = function(data,register = null){return data},
        f = function(data,register = null){return data.tofloat()},
        t = function(data,register = null){return Serializor.unserializeTable(data,register);},
        a = function(data,register = null){return Serializor.unserializeArray(data,register);},
        b = function(data,register = null){return data == "1"},
        n = function(data,register = null){return null},
        c = function(data,register = null){
            local i= 0;
            if(register == null){
                register = [];
            }
            local currentSize = 0;
            while(i < data.len()){
                if(data[i] > '9' || data[i] < '0' ){
                    currentSize = data.slice(0,i).tointeger()+i;
                    local classType = data.slice(i,currentSize);
                    if(!(classType in getroottable()))
                        throw "Class "+classType+" not found in rootTable";
                    return getroottable()[classType].unserialize(data.slice(currentSize),register);
                }
                i++;
            }
        },
    }
   
    constructor(){
        if(Serializor.singleton == null)
            Serializor.rawset("singleton",this);
        references = {};
    }
   
    function getSingleton(){
        if(Serializor.singleton == null)
            Serializor.singleton = Serializor();
        return Serializor.singleton;
    }
    function serialize(item){
        local reg = [];
        local res = Serializor.serializeType(item,reg);
        if(reg.len() > 0)
            reg[0] = null;
        return serializeType([res,reg],null);
    }
   
    function unserialize(data){
        local arr = Serializor.unserializeType(data);
        if(typeof arr != "array")
            return arr;
        if(arr.len() == 1)
            arr.push(null);
        return Serializor.unserializeType(arr[0],arr[1]);
    }
   
    function serializeType(item,register = null){
        if(typeof item == "string")
            return item.len().tostring()+"s"+item;
        if(typeof item == "integer"){
            local temp = item.tostring();
            return temp.len().tostring()+"i"+temp;
        }
        if(typeof item == "float"){
            local temp = item.tostring();
            return temp.len().tostring()+"f"+temp;
        }
        if(typeof item == "table"){
            local temp = serializeTable(item,register);
            return temp.len().tostring()+"t"+temp;
        }
        if(typeof item == "array"){
            local temp = serializeArray(item,register);
            return temp.len().tostring()+"a"+temp;
        }
        if(typeof item == "bool"){
            local temp = item?"1":"0";
            return temp.len().tostring()+"b"+temp;
        }
        if(typeof item == "null"){
            return "0n";
        }
        if("serialize" in item){
            if(typeof register == "array" && register.len() == 0)
                register.push({});
            local type = typeof item;
            local temp = type.len().tointeger()+type+item.serialize(register);
            return temp.len().tostring()+"c"+temp;
           
        }
    }
    function serializeArray(data,register = null){
        local temp = "";
        foreach(val in data )
        {
            temp += serializeType(val,register);
        }
        return temp;
    }
    function serializeTable(data,register = null){
        local temp = "";
        foreach(key,val in data )
        {
            temp += serializeType(key,register);
            temp += serializeType(val,register);
        }
        return temp;
    }
   
   
    function unserializeType(data,register = null){
        local i = 0;
        if(typeof data != "string")
            throw "Error data type give to unserializeType must be string, "+typeof data +" given !"
        while(i < data.len()){
            if(data[i] > '9' || data[i] < '0' )
            {
                return types[data[i].tochar()](data.slice(i+1),register);
            }
            i++;
        }
    }
       
    function unserializeArray(data,register){
        local theArray = [];
        local i = 0;
        local currentSize = 0;
        local beginCurrentIdx = 0;
        while(i < data.len()){
            if(data[i] > '9' || data[i] < '0' )
            {
                currentSize = data.slice(beginCurrentIdx,i).tointeger()+i+1;
                theArray.push((types[data[i].tochar()](data.slice(i+1,currentSize),register)));
                i = currentSize;
                beginCurrentIdx = i;
            }
            i++;
        }
        return theArray;
    }
    function unserializeTable(data,register = null){
        local theTable = {};
        local i = 0;
        local currentSize = 0;
        local beginCurrentIdx = 0;
        local key = null;
        while(i < data.len()){
            if(data[i] > '9' || data[i] < '0' )
            {
                currentSize = data.slice(beginCurrentIdx,i).tointeger()+i+1;
                if(key == null)
                    key = types[data[i].tochar()](data.slice(i+1,currentSize),register);
                else{
                    theTable[key] <- (types[data[i].tochar()](data.slice(i+1,currentSize),register));
                    key = null;
                }
                i = currentSize;
                beginCurrentIdx = i;
            }
            i++;
        }
        return theTable;
    }
   
   
   
    references = null;
}
class __ClassName {
    constructor(){
    }

    function _typeof(){
        if(this.__className != null)
            return this.__className;
        foreach(classObjName,classObj in ::getroottable())
        {
            if(classObj == this.getclass())
            {
                this.getclass().rawnewmember("__className",classObjName,"__className",true);
                return classObjName;
            }
        }
    }
    static __className = null;
}
class Serializable extends __ClassName
{
    constructor(){
        base.constructor();
        _serializeByCopy = false;
        if(this in ::Serializor.isUnserializing)
            return ;
    }
   
    _serializeByCopy = null;
   
    function unserialize(data,register){
        local tempData = data;
        if(data.slice(0,3) == "REF"){
            tempData = register[data.slice(3).tointeger()];
            if(typeof tempData != "string"){
                return tempData;
            }
        }
        tempData = Serializor.unserializeType(tempData,register);
       
        local newInstance = this.instance();
       
        if(data.slice(0,3) == "REF"){
            register[data.slice(3).tointeger()] = newInstance;
        }
        Serializor.isUnserializing[newInstance] <- true;
        local params = [];
       
        foreach(val in this.constructor.getinfos()["parameters"]){
            if(val != "this")
                params.push(null);
        }
        newInstance.constructor.pcall(newInstance,params);
        delete Serializor.isUnserializing[newInstance];
       
        foreach(key,val in tempData){
           
            local value = Serializor.unserializeType(val,register);
            newInstance.rawset(key,value);
        }
        return newInstance;
    }
   
    function serialize(register = null){
        if(register != null && register.len() > 0 && this in register[0])
            return "REF"+(register[0][this]).tostring();
        local data = {};
        foreach(key,val in this.getclass()){
            try{
                if(this.getclass().rawget(key) == null || this.getclass().rawget(key) != this.rawget(key)){
                    if(typeof this.rawget(key) != "function"){
                        data[key] <- Serializor.serializeType(this.rawget(key),register);
                    }
                }
            }catch(e){}
        }
        if(_serializeByCopy || register == null)
            return Serializor.serializeType(data,register);
        register[0][this] <- register.len();
        register.push(Serializor.serializeType(data,register));
        return "REF"+(register.len()-1).tostring();
    }
}
class Foo2 extends Serializable{
   
    constructor(val){
        base.constructor();
        print_r("constructor Foo2 "+(this in ::Serializor.isUnserializing).tostring());
        if(this in ::Serializor.isUnserializing)
            return;
            var = val;
    }
    var = null;
}

class Foo extends Serializable{
   
    constructor(val){
        base.constructor();
        print_r("constructor Foo "+(this in ::Serializor.isUnserializing).tostring());
        if(this in ::Serializor.isUnserializing)
            return;
        var = val;
        var2 = ["string",42,Foo2("subVar")];
        var3 = {str="string",arr=var2};
    }
    function aFunc(){
       
    }
    var = null;
    var2 = null;
    var3 = null;
}


local foo = Foo(55);

local data = Serializor.serialize(foo);
local mFoo = Serializor.unserialize(data);


print_r(mFoo.var);
print_r(mFoo.var2);
print_r(mFoo.var3);
print_r(mFoo.var2[2].var);

OUTPUT :
Quote:

constructor Foo false
constructor Foo2 false
constructor Foo true
constructor Foo2 true

198a10s8c3FooREF2181a0n42s39t3svar8s6ssubVar16s_serializeByCopy3s1b0130s126t3svar4s2i554svar347s44t
3sstr6sstring3sarr23a6sstring2i429c4Foo2REF14svar226s23a6sstring2i429c4Foo2REF116s_serializeByCopy3
s1b0

55
0 : string
1 : 42
2 : (instance : 0x0045FC48)
str : string
arr : array(3)
0 : string
1 : 42
2 : (instance : 0x0045FC48)

subVar
fireice
#2 Posted : Friday, August 8, 2014 2:27:05 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 11/14/2011(UTC)
Posts: 33

Thanks: 0 times
Was thanked: 4 time(s) in 4 post(s)
You will get better performance if you export that code to C. Also it is possible to serialize pure squirrel objects from there.
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Clean Slate theme by Jaben Cargman (Tiny Gecko)
Powered by YAF 1.9.4 | YAF © 2003-2010, Yet Another Forum.NET
This page was generated in 0.079 seconds.