Skip to content

Instantly share code, notes, and snippets.

@daschl
Last active December 18, 2015 14:09
Show Gist options
  • Save daschl/5795581 to your computer and use it in GitHub Desktop.
Save daschl/5795581 to your computer and use it in GitHub Desktop.
use this to unpack msgpack in a couchbase map function
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