Last active
December 18, 2015 14:19
-
-
Save daschl/5796263 to your computer and use it in GitHub Desktop.
MessagePack Library, Modified for Couchbase View inclusion.
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
/*!{id:msgpack.js,ver:1.05,license:"MIT",author:"uupaa.js@gmail.com"}*/ | |
/* Modified by @daschl and @avsej to strip out whats not needed */ | |
// === msgpack === | |
// MessagePack -> http://msgpack.sourceforge.net/ | |
var msgunpack = (function () { | |
var _bin2num = {}, // BinaryStringToNumber { "\00": 0, ... "\ff": 255 } | |
_num2bin = {}, // NumberToBinaryString { 0: "\00", ... 255: "\ff" } | |
_buf = [], // decode buffer | |
_idx = 0, // decode buffer[index] | |
_toString = String.fromCharCode; // CharCode/ByteArray to String | |
// @param BinaryString/ByteArray: | |
// @return Mix/undefined: | |
// undefined is error return | |
// [1][String to mix] msgpack.unpack("...") -> {} | |
// [2][ByteArray to mix] msgpack.unpack([...]) -> {} | |
function unpack(data) { | |
_buf = typeof data === "string" ? toByteArray(data) : data; | |
_idx = -1; | |
return decode(); // mix or undefined | |
} | |
// @return Mix: | |
function decode() { | |
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; | |
} | |
// @param ByteArray | |
// @return String | |
// http://d.hatena.ne.jp/uupaa/20101128 | |
function byteArrayToByteString(byteArray) { | |
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(""); | |
} | |
// @param BinaryString: "\00\01" | |
// @return ByteArray: [0x00, 0x01] | |
function toByteArray(data) { | |
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; | |
} | |
return unpack; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment