Last active
December 18, 2015 14:09
-
-
Save daschl/5795581 to your computer and use it in GitHub Desktop.
use this to unpack msgpack in a couchbase map function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Or compressed: | |
var _bin2num={},_num2bin={},_num2b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""),_buf=[],_idx=0,_error=0,_isArray=Array.isArray||function(f){return"[object Array]"===Object.prototype.toString.call(f)},_toString=String.fromCharCode,_MAX_DEPTH=512;function msgpackunpack(f){_buf="string"===typeof f?toByteArray(f):f;_idx=-1;return decode()} | |
function decode(){var f,c,e,a=0,d,g,b=_buf;c=b[++_idx];if(224<=c)return c-256;if(192>c){if(128>c)return c;144>c?(a=c-128,c=128):160>c?(a=c-144,c=144):(a=c-160,c=160)}switch(c){case 192:return null;case 194:return!1;case 195:return!0;case 202:return a=16777216*b[++_idx]+(b[++_idx]<<16)+(b[++_idx]<<8)+b[++_idx],d=a>>23&255,g=a&8388607,!a||2147483648===a?0:255===d?g?NaN:Infinity:(a&2147483648?-1:1)*(g|8388608)*Math.pow(2,d-127-23);case 203:a=16777216*b[++_idx]+(b[++_idx]<<16)+(b[++_idx]<<8)+b[++_idx]; | |
c=a&2147483648;d=a>>20&2047;g=a&1048575;if(!a||2147483648===a)return _idx+=4,0;if(2047===d)return _idx+=4,g?NaN:Infinity;a=16777216*b[++_idx]+(b[++_idx]<<16)+(b[++_idx]<<8)+b[++_idx];return(c?-1:1)*((g|1048576)*Math.pow(2,d-1023-20)+a*Math.pow(2,d-1023-52));case 207:return a=16777216*b[++_idx]+(b[++_idx]<<16)+(b[++_idx]<<8)+b[++_idx],4294967296*a+16777216*b[++_idx]+(b[++_idx]<<16)+(b[++_idx]<<8)+b[++_idx];case 206:a+=16777216*b[++_idx]+(b[++_idx]<<16);case 205:a+=b[++_idx]<<8;case 204:return a+b[++_idx]; | |
case 211:return a=b[++_idx],a&128?-1*(72057594037927936*(a^255)+281474976710656*(b[++_idx]^255)+1099511627776*(b[++_idx]^255)+4294967296*(b[++_idx]^255)+16777216*(b[++_idx]^255)+65536*(b[++_idx]^255)+256*(b[++_idx]^255)+(b[++_idx]^255)+1):72057594037927936*a+281474976710656*b[++_idx]+1099511627776*b[++_idx]+4294967296*b[++_idx]+16777216*b[++_idx]+65536*b[++_idx]+256*b[++_idx]+b[++_idx];case 210:return a=16777216*b[++_idx]+(b[++_idx]<<16)+(b[++_idx]<<8)+b[++_idx],2147483648>a?a:a-4294967296;case 209:return a= | |
(b[++_idx]<<8)+b[++_idx],32768>a?a:a-65536;case 208:return a=b[++_idx],128>a?a:a-256;case 219:a+=16777216*b[++_idx]+(b[++_idx]<<16);case 218:a+=(b[++_idx]<<8)+b[++_idx];case 160:d=[];c=_idx;for(f=c+a;c<f;)e=b[++c],d.push(128>e?e:224>e?(e&31)<<6|b[++c]&63:(e&15)<<12|(b[++c]&63)<<6|b[++c]&63);_idx=c;return 10240>d.length?_toString.apply(null,d):byteArrayToByteString(d);case 223:a+=16777216*b[++_idx]+(b[++_idx]<<16);case 222:a+=(b[++_idx]<<8)+b[++_idx];case 128:for(g={};a--;){f=b[++_idx]-160;d=[];c= | |
_idx;for(f=c+f;c<f;)e=b[++c],d.push(128>e?e:224>e?(e&31)<<6|b[++c]&63:(e&15)<<12|(b[++c]&63)<<6|b[++c]&63);_idx=c;g[_toString.apply(null,d)]=decode()}return g;case 221:a+=16777216*b[++_idx]+(b[++_idx]<<16);case 220:a+=(b[++_idx]<<8)+b[++_idx];case 144:for(d=[];a--;)d.push(decode());return d}}function byteArrayToByteString(f){try{return _toString.apply(this,f)}catch(c){}for(var e=[],a=0,d=f.length,g=_num2bin;a<d;++a)e[a]=g[f[a]];return e.join("")} | |
function toByteArray(f){var c=[],e=_bin2num,a=f.split(""),d=-1,g;g=a.length;for(f=g%8;f--;)++d,c[d]=e[a[d]];for(f=g>>3;f--;)c.push(e[a[++d]],e[a[++d]],e[a[++d]],e[a[++d]],e[a[++d]],e[a[++d]],e[a[++d]],e[a[++d]]);return c}; | |
var _bin2num = {}, // BinaryStringToNumber { "\00": 0, ... "\ff": 255 } | |
_num2bin = {}, // NumberToBinaryString { 0: "\00", ... 255: "\ff" } | |
_num2b64 = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + | |
"abcdefghijklmnopqrstuvwxyz0123456789+/").split(""), | |
_buf = [], // decode buffer | |
_idx = 0, // decode buffer[index] | |
_error = 0, // msgpack.pack() error code. 1 = CYCLIC_REFERENCE_ERROR | |
_isArray = Array.isArray || (function(mix) { | |
return Object.prototype.toString.call(mix) === "[object Array]"; | |
}), | |
_toString = String.fromCharCode, // CharCode/ByteArray to String | |
_MAX_DEPTH = 512; | |
// msgpack.unpack | |
function msgpackunpack(data) { // @param BinaryString/ByteArray: | |
// @return Mix/undefined: | |
// undefined is error return | |
// [1][String to mix] msgpack.unpack("...") -> {} | |
// [2][ByteArray to mix] msgpack.unpack([...]) -> {} | |
_buf = typeof data === "string" ? toByteArray(data) : data; | |
_idx = -1; | |
return decode(); // mix or undefined | |
} | |
// inner - decoder | |
function decode() { // @return Mix: | |
var size, i, iz, c, num = 0, | |
sign, exp, frac, ary, hash, | |
buf = _buf, type = buf[++_idx]; | |
if (type >= 0xe0) { // Negative FixNum (111x xxxx) (-32 ~ -1) | |
return type - 0x100; | |
} | |
if (type < 0xc0) { | |
if (type < 0x80) { // Positive FixNum (0xxx xxxx) (0 ~ 127) | |
return type; | |
} | |
if (type < 0x90) { // FixMap (1000 xxxx) | |
num = type - 0x80; | |
type = 0x80; | |
} else if (type < 0xa0) { // FixArray (1001 xxxx) | |
num = type - 0x90; | |
type = 0x90; | |
} else { // if (type < 0xc0) { // FixRaw (101x xxxx) | |
num = type - 0xa0; | |
type = 0xa0; | |
} | |
} | |
switch (type) { | |
case 0xc0: return null; | |
case 0xc2: return false; | |
case 0xc3: return true; | |
case 0xca: // float | |
num = buf[++_idx] * 0x1000000 + (buf[++_idx] << 16) + | |
(buf[++_idx] << 8) + buf[++_idx]; | |
sign = num & 0x80000000; // 1bit | |
exp = (num >> 23) & 0xff; // 8bits | |
frac = num & 0x7fffff; // 23bits | |
if (!num || num === 0x80000000) { // 0.0 or -0.0 | |
return 0; | |
} | |
if (exp === 0xff) { // NaN or Infinity | |
return frac ? NaN : Infinity; | |
} | |
return (sign ? -1 : 1) * | |
(frac | 0x800000) * Math.pow(2, exp - 127 - 23); // 127: bias | |
case 0xcb: // double | |
num = buf[++_idx] * 0x1000000 + (buf[++_idx] << 16) + | |
(buf[++_idx] << 8) + buf[++_idx]; | |
sign = num & 0x80000000; // 1bit | |
exp = (num >> 20) & 0x7ff; // 11bits | |
frac = num & 0xfffff; // 52bits - 32bits (high word) | |
if (!num || num === 0x80000000) { // 0.0 or -0.0 | |
_idx += 4; | |
return 0; | |
} | |
if (exp === 0x7ff) { // NaN or Infinity | |
_idx += 4; | |
return frac ? NaN : Infinity; | |
} | |
num = buf[++_idx] * 0x1000000 + (buf[++_idx] << 16) + | |
(buf[++_idx] << 8) + buf[++_idx]; | |
return (sign ? -1 : 1) * | |
((frac | 0x100000) * Math.pow(2, exp - 1023 - 20) // 1023: bias | |
+ num * Math.pow(2, exp - 1023 - 52)); | |
// 0xcf: uint64, 0xce: uint32, 0xcd: uint16 | |
case 0xcf: num = buf[++_idx] * 0x1000000 + (buf[++_idx] << 16) + | |
(buf[++_idx] << 8) + buf[++_idx]; | |
return num * 0x100000000 + | |
buf[++_idx] * 0x1000000 + (buf[++_idx] << 16) + | |
(buf[++_idx] << 8) + buf[++_idx]; | |
case 0xce: num += buf[++_idx] * 0x1000000 + (buf[++_idx] << 16); | |
case 0xcd: num += buf[++_idx] << 8; | |
case 0xcc: return num + buf[++_idx]; | |
// 0xd3: int64, 0xd2: int32, 0xd1: int16, 0xd0: int8 | |
case 0xd3: num = buf[++_idx]; | |
if (num & 0x80) { // sign -> avoid overflow | |
return ((num ^ 0xff) * 0x100000000000000 + | |
(buf[++_idx] ^ 0xff) * 0x1000000000000 + | |
(buf[++_idx] ^ 0xff) * 0x10000000000 + | |
(buf[++_idx] ^ 0xff) * 0x100000000 + | |
(buf[++_idx] ^ 0xff) * 0x1000000 + | |
(buf[++_idx] ^ 0xff) * 0x10000 + | |
(buf[++_idx] ^ 0xff) * 0x100 + | |
(buf[++_idx] ^ 0xff) + 1) * -1; | |
} | |
return num * 0x100000000000000 + | |
buf[++_idx] * 0x1000000000000 + | |
buf[++_idx] * 0x10000000000 + | |
buf[++_idx] * 0x100000000 + | |
buf[++_idx] * 0x1000000 + | |
buf[++_idx] * 0x10000 + | |
buf[++_idx] * 0x100 + | |
buf[++_idx]; | |
case 0xd2: num = buf[++_idx] * 0x1000000 + (buf[++_idx] << 16) + | |
(buf[++_idx] << 8) + buf[++_idx]; | |
return num < 0x80000000 ? num : num - 0x100000000; // 0x80000000 * 2 | |
case 0xd1: num = (buf[++_idx] << 8) + buf[++_idx]; | |
return num < 0x8000 ? num : num - 0x10000; // 0x8000 * 2 | |
case 0xd0: num = buf[++_idx]; | |
return num < 0x80 ? num : num - 0x100; // 0x80 * 2 | |
// 0xdb: raw32, 0xda: raw16, 0xa0: raw ( string ) | |
case 0xdb: num += buf[++_idx] * 0x1000000 + (buf[++_idx] << 16); | |
case 0xda: num += (buf[++_idx] << 8) + buf[++_idx]; | |
case 0xa0: // utf8.decode | |
for (ary = [], i = _idx, iz = i + num; i < iz; ) { | |
c = buf[++i]; // lead byte | |
ary.push(c < 0x80 ? c : // ASCII(0x00 ~ 0x7f) | |
c < 0xe0 ? ((c & 0x1f) << 6 | (buf[++i] & 0x3f)) : | |
((c & 0x0f) << 12 | (buf[++i] & 0x3f) << 6 | |
| (buf[++i] & 0x3f))); | |
} | |
_idx = i; | |
return ary.length < 10240 ? _toString.apply(null, ary) | |
: byteArrayToByteString(ary); | |
// 0xdf: map32, 0xde: map16, 0x80: map | |
case 0xdf: num += buf[++_idx] * 0x1000000 + (buf[++_idx] << 16); | |
case 0xde: num += (buf[++_idx] << 8) + buf[++_idx]; | |
case 0x80: hash = {}; | |
while (num--) { | |
// make key/value pair | |
size = buf[++_idx] - 0xa0; | |
for (ary = [], i = _idx, iz = i + size; i < iz; ) { | |
c = buf[++i]; // lead byte | |
ary.push(c < 0x80 ? c : // ASCII(0x00 ~ 0x7f) | |
c < 0xe0 ? ((c & 0x1f) << 6 | (buf[++i] & 0x3f)) : | |
((c & 0x0f) << 12 | (buf[++i] & 0x3f) << 6 | |
| (buf[++i] & 0x3f))); | |
} | |
_idx = i; | |
hash[_toString.apply(null, ary)] = decode(); | |
} | |
return hash; | |
// 0xdd: array32, 0xdc: array16, 0x90: array | |
case 0xdd: num += buf[++_idx] * 0x1000000 + (buf[++_idx] << 16); | |
case 0xdc: num += (buf[++_idx] << 8) + buf[++_idx]; | |
case 0x90: ary = []; | |
while (num--) { | |
ary.push(decode()); | |
} | |
return ary; | |
} | |
return; | |
} | |
// inner - byteArray To ByteString | |
function byteArrayToByteString(byteArray) { // @param ByteArray | |
// @return String | |
// http://d.hatena.ne.jp/uupaa/20101128 | |
try { | |
return _toString.apply(this, byteArray); // toString | |
} catch(err) { | |
; // avoid "Maximum call stack size exceeded" | |
} | |
var rv = [], i = 0, iz = byteArray.length, num2bin = _num2bin; | |
for (; i < iz; ++i) { | |
rv[i] = num2bin[byteArray[i]]; | |
} | |
return rv.join(""); | |
} | |
// inner - BinaryString To ByteArray | |
function toByteArray(data) { // @param BinaryString: "\00\01" | |
// @return ByteArray: [0x00, 0x01] | |
var rv = [], bin2num = _bin2num, remain, | |
ary = data.split(""), | |
i = -1, iz; | |
iz = ary.length; | |
remain = iz % 8; | |
while (remain--) { | |
++i; | |
rv[i] = bin2num[ary[i]]; | |
} | |
remain = iz >> 3; | |
while (remain--) { | |
rv.push(bin2num[ary[++i]], bin2num[ary[++i]], | |
bin2num[ary[++i]], bin2num[ary[++i]], | |
bin2num[ary[++i]], bin2num[ary[++i]], | |
bin2num[ary[++i]], bin2num[ary[++i]]); | |
} | |
return rv; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment