serialize.js (8114B)
1 function serialize(mixed_value) { 2 // discuss at: http://phpjs.org/functions/serialize/ 3 // original by: Arpad Ray (mailto:arpad@php.net) 4 // improved by: Dino 5 // improved by: Le Torbi (http://www.letorbi.de/) 6 // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net/) 7 // bugfixed by: Andrej Pavlovic 8 // bugfixed by: Garagoth 9 // bugfixed by: Russell Walker (http://www.nbill.co.uk/) 10 // bugfixed by: Jamie Beck (http://www.terabit.ca/) 11 // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net/) 12 // bugfixed by: Ben (http://benblume.co.uk/) 13 // input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html) 14 // input by: Martin (http://www.erlenwiese.de/) 15 // note: We feel the main purpose of this function should be to ease the transport of data between php & js 16 // note: Aiming for PHP-compatibility, we have to translate objects to arrays 17 // example 1: serialize(['Kevin', 'van', 'Zonneveld']); 18 // returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}' 19 // example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'}); 20 // returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}' 21 22 var val, key, okey, 23 ktype = '', 24 vals = '', 25 count = 0, 26 _utf8Size = function(str) { 27 var size = 0, 28 i = 0, 29 l = str.length, 30 code = ''; 31 for (i = 0; i < l; i++) { 32 code = str.charCodeAt(i); 33 if (code < 0x0080) { 34 size += 1; 35 } else if (code < 0x0800) { 36 size += 2; 37 } else { 38 size += 3; 39 } 40 } 41 return size; 42 }; 43 _getType = function(inp) { 44 var match, key, cons, types, type = typeof inp; 45 46 if (type === 'object' && !inp) { 47 return 'null'; 48 } 49 if (type === 'object') { 50 if (!inp.constructor) { 51 return 'object'; 52 } 53 cons = inp.constructor.toString(); 54 match = cons.match(/(\w+)\(/); 55 if (match) { 56 cons = match[1].toLowerCase(); 57 } 58 types = ['boolean', 'number', 'string', 'array']; 59 for (key in types) { 60 if (cons == types[key]) { 61 type = types[key]; 62 break; 63 } 64 } 65 } 66 return type; 67 }; 68 type = _getType(mixed_value); 69 70 switch (type) { 71 case 'function': 72 val = ''; 73 break; 74 case 'boolean': 75 val = 'b:' + (mixed_value ? '1' : '0'); 76 break; 77 case 'number': 78 val = (Math.round(mixed_value) == mixed_value ? 'i' : 'd') + ':' + mixed_value; 79 break; 80 case 'string': 81 val = 's:' + _utf8Size(mixed_value) + ':"' + mixed_value + '"'; 82 break; 83 case 'array': 84 case 'object': 85 val = 'a'; 86 /* 87 if (type === 'object') { 88 var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/); 89 if (objname == undefined) { 90 return; 91 } 92 objname[1] = this.serialize(objname[1]); 93 val = 'O' + objname[1].substring(1, objname[1].length - 1); 94 } 95 */ 96 97 for (key in mixed_value) { 98 if (mixed_value.hasOwnProperty(key)) { 99 ktype = _getType(mixed_value[key]); 100 if (ktype === 'function') { 101 continue; 102 } 103 104 105 okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key); 106 vals += this.serialize(okey) + this.serialize(mixed_value[key]); 107 count++; 108 } 109 } 110 val += ':' + count + ':{' + vals + '}'; 111 break; 112 case 'undefined': 113 // Fall-through 114 default: 115 // if the JS object has a property which contains a null value, the string cannot be unserialized by PHP 116 val = 'N'; 117 break; 118 } 119 if (type !== 'object' && type !== 'array') { 120 if ( type == 'string' && val.indexOf('}') != -1 ) { 121 } else { 122 val += ';'; 123 } 124 } 125 return val; 126 } 127 128 129 function unserialize(data) { 130 // discuss at: http://phpjs.org/functions/unserialize/ 131 // original by: Arpad Ray (mailto:arpad@php.net) 132 // improved by: Pedro Tainha (http://www.pedrotainha.com) 133 // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 134 // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 135 // improved by: Chris 136 // improved by: James 137 // improved by: Le Torbi 138 // improved by: Eli Skeggs 139 // bugfixed by: dptr1988 140 // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 141 // bugfixed by: Brett Zamir (http://brett-zamir.me) 142 // revised by: d3x 143 // input by: Brett Zamir (http://brett-zamir.me) 144 // input by: Martin (http://www.erlenwiese.de/) 145 // input by: kilops 146 // input by: Jaroslaw Czarniak 147 // note: We feel the main purpose of this function should be to ease the transport of data between php & js 148 // note: Aiming for PHP-compatibility, we have to translate objects to arrays 149 // example 1: unserialize('a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}'); 150 // returns 1: ['Kevin', 'van', 'Zonneveld'] 151 // example 2: unserialize('a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}'); 152 // returns 2: {firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'} 153 154 var that = this, 155 utf8Overhead = function(chr) { 156 // http://phpjs.org/functions/unserialize:571#comment_95906 157 var code = chr.charCodeAt(0); 158 if (code < 0x0080) { 159 return 0; 160 } 161 if (code < 0x0800) { 162 return 1; 163 } 164 return 2; 165 }; 166 error = function(type, msg, filename, line) { 167 throw new that.window[type](msg, filename, line); 168 }; 169 read_until = function(data, offset, stopchr) { 170 var i = 2, 171 buf = [], 172 chr = data.slice(offset, offset + 1); 173 174 while (chr != stopchr) { 175 if ((i + offset) > data.length) { 176 error('Error', 'Invalid'); 177 } 178 buf.push(chr); 179 chr = data.slice(offset + (i - 1), offset + i); 180 i += 1; 181 } 182 return [buf.length, buf.join('')]; 183 }; 184 read_chrs = function(data, offset, length) { 185 var i, chr, buf; 186 187 buf = []; 188 for (i = 0; i < length; i++) { 189 chr = data.slice(offset + (i - 1), offset + i); 190 buf.push(chr); 191 length -= utf8Overhead(chr); 192 } 193 return [buf.length, buf.join('')]; 194 }; 195 _unserialize = function(data, offset) { 196 var dtype, dataoffset, keyandchrs, keys, contig, 197 length, array, readdata, readData, ccount, 198 stringlength, i, key, kprops, kchrs, vprops, 199 vchrs, value, chrs = 0, 200 typeconvert = function(x) { 201 return x; 202 }; 203 204 if (!offset) { 205 offset = 0; 206 } 207 dtype = (data.slice(offset, offset + 1)) 208 .toLowerCase(); 209 210 dataoffset = offset + 2; 211 212 switch (dtype) { 213 case 'i': 214 typeconvert = function(x) { 215 return parseInt(x, 10); 216 }; 217 readData = read_until(data, dataoffset, ';'); 218 chrs = readData[0]; 219 readdata = readData[1]; 220 dataoffset += chrs + 1; 221 break; 222 case 'b': 223 typeconvert = function(x) { 224 return parseInt(x, 10) !== 0; 225 }; 226 readData = read_until(data, dataoffset, ';'); 227 chrs = readData[0]; 228 readdata = readData[1]; 229 dataoffset += chrs + 1; 230 break; 231 case 'd': 232 typeconvert = function(x) { 233 return parseFloat(x); 234 }; 235 readData = read_until(data, dataoffset, ';'); 236 chrs = readData[0]; 237 readdata = readData[1]; 238 dataoffset += chrs + 1; 239 break; 240 case 'n': 241 readdata = null; 242 break; 243 case 's': 244 ccount = read_until(data, dataoffset, ':'); 245 chrs = ccount[0]; 246 stringlength = ccount[1]; 247 dataoffset += chrs + 2; 248 249 readData = read_chrs(data, dataoffset + 1, parseInt(stringlength, 10)); 250 chrs = readData[0]; 251 readdata = readData[1]; 252 dataoffset += chrs + 2; 253 if (chrs != parseInt(stringlength, 10) && chrs != readdata.length) { 254 error('SyntaxError', 'String length mismatch'); 255 } 256 break; 257 case 'a': 258 readdata = {}; 259 260 keyandchrs = read_until(data, dataoffset, ':'); 261 chrs = keyandchrs[0]; 262 keys = keyandchrs[1]; 263 dataoffset += chrs + 2; 264 265 length = parseInt(keys, 10); 266 contig = true; 267 268 for (i = 0; i < length; i++) { 269 kprops = _unserialize(data, dataoffset); 270 kchrs = kprops[1]; 271 key = kprops[2]; 272 dataoffset += kchrs; 273 274 vprops = _unserialize(data, dataoffset); 275 vchrs = vprops[1]; 276 value = vprops[2]; 277 dataoffset += vchrs; 278 279 if (key !== i) 280 contig = false; 281 282 readdata[key] = value; 283 } 284 285 if (contig) { 286 array = new Array(length); 287 for (i = 0; i < length; i++) 288 array[i] = readdata[i]; 289 readdata = array; 290 } 291 292 dataoffset += 1; 293 break; 294 default: 295 error('SyntaxError', 'Unknown / Unhandled data type(s): ' + dtype); 296 break; 297 } 298 return [dtype, dataoffset - offset, typeconvert(readdata)]; 299 }; 300 301 return _unserialize((data + ''), 0)[2]; 302 }