Subj : Re: object serialization To : netscape.public.mozilla.jseng From : Daniel Fournier Date : Fri Mar 26 2004 07:43 am Jens Thiele wrote: > a first hack to get serialization working in "pure" javascript > - intended for "pure" javascript objects) > - keeping the prototype (__proto__ field) right > - keep graph relationships > the hash function is shit - is there any way to get a hashvalue for > an object (perhaps based on its pointer/reference)? > > karme > > > // a first object serializer hack > // based on code from Daniel Fournier ( thanks!) > > // todo this is shit > function hashfunc(obj,key,depth) { > /* if (!key) key=''; > if (!depth) depth=0; > var i,t; > for (i in obj) { > key+=i; > t=typeof(obj[i]); > key+=t.substring(0,1); > if (t == 'string') key+=obj[i].substring(0,3); > if (t == 'number') key+=obj[i]; > else if ((depth<3)&&(t == 'object')) key+=hashfunc(obj[i],key,depth+1); > if (key.length>60) return key; > } > return key;*/ > return obj.toSource(); > } > > function emptyproto(p) { > for (a in p) return false; > return true; > } > > function Serializer() {}; > > // enter new scope > Serializer.prototype._push=function(v){ > this.scope.push(v); > this.fqscope+=v; > } > // leave scope > Serializer.prototype._pop=function(){ > this.scope.pop(); > var r=''; > for (var i=0;i r+=this.scope[i]; > } > this.fqscope=r; > } > > // this object has been serialized > Serializer.prototype._serialized=function(obj){ > var key=hashfunc(obj); > var slot=this._hash[key]; > if (!slot) slot=this._hash[key]=[]; > slot.push({o:obj,s:this.fqscope}); > } > // is this object already serialized? > Serializer.prototype._getSerialized=function(obj){ > var key=hashfunc(obj); > var slot=this._hash[key]; > if (!slot) return false; > for (var i=0;i if (slot[i].o==obj) { > return slot[i].s; > } > } > return false; > } > > Serializer.prototype.serialize=function(object, id){ > if (!object) throw "object required"; > if (!id) throw "id required"; > this.scope=[]; > this.fqscope=''; > this._push(id); > this.append=""; > this._hash=[]; > var res=id + "=" + this._serialize(object)+";\n"+this.append; > > // debug hashfunc > /* var key,slot,c,ctotal=0; > for (key in this._hash) { > c=-1; > for (slot in this._hash[key]) c++; > ctotal+=c; > print ("key: "+key+" collisions:"+c); > } > print ("total collisions:"+ctotal); > */ > return res; > } > > Serializer.prototype._serialize=function(object){ > var ot=typeof(object); > if (ot == 'string') { > this._pop(); > return "'" + object + "'"; > } > if (ot == 'function') { > this._serialized(object); > this._pop(); > return object.toString(); > } > if (ot != 'object') { > // numbers, booleans > this._pop(); > return object; > } > > // i don't need to serialize dates > // if (object instanceof Date) { > // this._serialized(object); > // this._pop(); > // return object.toSource(); > // } > > this._serialized(object); > > var closeSymbol, objectString = '', stored = ''; > if (object instanceof Array) { > // array > closeSymbol = ']'; > objectString += '['; > var c=0; > for (var k in object) { > if ((stored=this._getSerialized(object[k]))) > this.append+=this.fqscope+"["+k+"]="+stored+";\n"; > else{ > if (c>0) objectString+=','; > c++; > this._push("["+k+"]"); > objectString += this._serialize(object[k]); > } > } > } else { > // object > closeSymbol = '}'; > objectString += '{'; > var c=0; > for (var k in object) { > // test if this member comes from our prototype > if (object.__proto__[k]!=object[k]) { > if ((stored=this._getSerialized(object[k]))) > this.append+=this.fqscope+"."+k+"="+stored+";\n"; > else{ > if (c>0) objectString+=','; > c++; > this._push("."+k); > objectString += k + ':' + this._serialize(object[k]); > } > } > } > // serialize prototype > if ((object.__proto__)&&(!emptyproto(object.__proto__))) { > if ((stored=this._getSerialized(object.__proto__))) > this.append+=this.fqscope+".__proto__="+stored+";\n"; > else{ > if (c>0) objectString+=','; > c++; > this._push(".__proto__"); > objectString += "__proto__" + ':' + this._serialize(object.__proto__); > } > } > } > objectString += closeSymbol; > this._pop(); > return objectString; > } > > // graph test > foo={a:4}; > graph={x:foo, y:foo}; > eval(new Serializer().serialize(graph, 'graph2')); > graph2.x.a=77; > // should print 77 > print((graph2.y.a==77) ? "Test passed" : "Test failed"); > Hi Jens, Sorry, but I have not enough time today to look carefuly at your code. However, about the hash function, I can help: There is a MD5 hashing class within Mozlib library, part of my JS Console extension (). Find it in the "chrome://mozlib/content/lib/js/digest/" directory (after installing JS Console, of course). You need only 2 files: generator.js and md5.js. You could use the DIGEST_MD5Generator class to hash your objects, based on a unique field value, for instance using the Date function. For instance: var object = {id:new Date}; //add your properties as you wish var hashvalue = (new DIGEST_MD5Generator()).getHex(object.id); Will it fit? Daniel .