mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-26 15:34:57 +01:00
601 lines
14 KiB
JavaScript
601 lines
14 KiB
JavaScript
|
( // Module boilerplate to support browser globals and browserify and AMD.
|
||
|
typeof define === "function" ? function (m) { define("msgpack-js", m); } :
|
||
|
typeof exports === "object" ? function (m) { module.exports = m(); } :
|
||
|
function(m){ this.msgpack = m(); }
|
||
|
)(function () {
|
||
|
"use strict";
|
||
|
|
||
|
var exports = {};
|
||
|
|
||
|
exports.inspect = inspect;
|
||
|
function inspect(buffer) {
|
||
|
if (buffer === undefined) return "undefined";
|
||
|
var view;
|
||
|
var type;
|
||
|
if (buffer instanceof ArrayBuffer) {
|
||
|
type = "ArrayBuffer";
|
||
|
view = new DataView(buffer);
|
||
|
}
|
||
|
else if (buffer instanceof DataView) {
|
||
|
type = "DataView";
|
||
|
view = buffer;
|
||
|
}
|
||
|
if (!view) return JSON.stringify(buffer);
|
||
|
var bytes = [];
|
||
|
for (var i = 0; i < buffer.byteLength; i++) {
|
||
|
if (i > 20) {
|
||
|
bytes.push("...");
|
||
|
break;
|
||
|
}
|
||
|
var byte = view.getUint8(i).toString(16);
|
||
|
if (byte.length === 1) byte = "0" + byte;
|
||
|
bytes.push(byte);
|
||
|
}
|
||
|
return "<" + type + " " + bytes.join(" ") + ">";
|
||
|
}
|
||
|
|
||
|
// Encode string as utf8 into dataview at offset
|
||
|
exports.utf8Write = utf8Write;
|
||
|
function utf8Write(view, offset, string) {
|
||
|
var byteLength = view.byteLength;
|
||
|
for(var i = 0, l = string.length; i < l; i++) {
|
||
|
var codePoint = string.charCodeAt(i);
|
||
|
|
||
|
// One byte of UTF-8
|
||
|
if (codePoint < 0x80) {
|
||
|
view.setUint8(offset++, codePoint >>> 0 & 0x7f | 0x00);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Two bytes of UTF-8
|
||
|
if (codePoint < 0x800) {
|
||
|
view.setUint8(offset++, codePoint >>> 6 & 0x1f | 0xc0);
|
||
|
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Three bytes of UTF-8.
|
||
|
if (codePoint < 0x10000) {
|
||
|
view.setUint8(offset++, codePoint >>> 12 & 0x0f | 0xe0);
|
||
|
view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);
|
||
|
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Four bytes of UTF-8
|
||
|
if (codePoint < 0x110000) {
|
||
|
view.setUint8(offset++, codePoint >>> 18 & 0x07 | 0xf0);
|
||
|
view.setUint8(offset++, codePoint >>> 12 & 0x3f | 0x80);
|
||
|
view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);
|
||
|
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
|
||
|
continue;
|
||
|
}
|
||
|
throw new Error("bad codepoint " + codePoint);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exports.utf8Read = utf8Read;
|
||
|
function utf8Read(view, offset, length) {
|
||
|
var string = "";
|
||
|
for (var i = offset, end = offset + length; i < end; i++) {
|
||
|
var byte = view.getUint8(i);
|
||
|
// One byte character
|
||
|
if ((byte & 0x80) === 0x00) {
|
||
|
string += String.fromCharCode(byte);
|
||
|
continue;
|
||
|
}
|
||
|
// Two byte character
|
||
|
if ((byte & 0xe0) === 0xc0) {
|
||
|
string += String.fromCharCode(
|
||
|
((byte & 0x0f) << 6) |
|
||
|
(view.getUint8(++i) & 0x3f)
|
||
|
);
|
||
|
continue;
|
||
|
}
|
||
|
// Three byte character
|
||
|
if ((byte & 0xf0) === 0xe0) {
|
||
|
string += String.fromCharCode(
|
||
|
((byte & 0x0f) << 12) |
|
||
|
((view.getUint8(++i) & 0x3f) << 6) |
|
||
|
((view.getUint8(++i) & 0x3f) << 0)
|
||
|
);
|
||
|
continue;
|
||
|
}
|
||
|
// Four byte character
|
||
|
if ((byte & 0xf8) === 0xf0) {
|
||
|
string += String.fromCharCode(
|
||
|
((byte & 0x07) << 18) |
|
||
|
((view.getUint8(++i) & 0x3f) << 12) |
|
||
|
((view.getUint8(++i) & 0x3f) << 6) |
|
||
|
((view.getUint8(++i) & 0x3f) << 0)
|
||
|
);
|
||
|
continue;
|
||
|
}
|
||
|
throw new Error("Invalid byte " + byte.toString(16));
|
||
|
}
|
||
|
return string;
|
||
|
}
|
||
|
|
||
|
exports.utf8ByteCount = utf8ByteCount;
|
||
|
function utf8ByteCount(string) {
|
||
|
var count = 0;
|
||
|
for(var i = 0, l = string.length; i < l; i++) {
|
||
|
var codePoint = string.charCodeAt(i);
|
||
|
if (codePoint < 0x80) {
|
||
|
count += 1;
|
||
|
continue;
|
||
|
}
|
||
|
if (codePoint < 0x800) {
|
||
|
count += 2;
|
||
|
continue;
|
||
|
}
|
||
|
if (codePoint < 0x10000) {
|
||
|
count += 3;
|
||
|
continue;
|
||
|
}
|
||
|
if (codePoint < 0x110000) {
|
||
|
count += 4;
|
||
|
continue;
|
||
|
}
|
||
|
throw new Error("bad codepoint " + codePoint);
|
||
|
}
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
exports.encode = function (value) {
|
||
|
var buffer = new ArrayBuffer(sizeof(value));
|
||
|
var view = new DataView(buffer);
|
||
|
encode(value, view, 0);
|
||
|
return buffer;
|
||
|
}
|
||
|
|
||
|
exports.decode = decode;
|
||
|
|
||
|
// http://wiki.msgpack.org/display/MSGPACK/Format+specification
|
||
|
// I've extended the protocol to have two new types that were previously reserved.
|
||
|
// buffer 16 11011000 0xd8
|
||
|
// buffer 32 11011001 0xd9
|
||
|
// These work just like raw16 and raw32 except they are node buffers instead of strings.
|
||
|
//
|
||
|
// Also I've added a type for `undefined`
|
||
|
// undefined 11000100 0xc4
|
||
|
|
||
|
function Decoder(view, offset) {
|
||
|
this.offset = offset || 0;
|
||
|
this.view = view;
|
||
|
}
|
||
|
Decoder.prototype.map = function (length) {
|
||
|
var value = {};
|
||
|
for (var i = 0; i < length; i++) {
|
||
|
var key = this.parse();
|
||
|
value[key] = this.parse();
|
||
|
}
|
||
|
return value;
|
||
|
};
|
||
|
Decoder.prototype.buf = function (length) {
|
||
|
var value = new ArrayBuffer(length);
|
||
|
(new Uint8Array(value)).set(new Uint8Array(this.view.buffer, this.offset, length), 0);
|
||
|
this.offset += length;
|
||
|
return value;
|
||
|
};
|
||
|
Decoder.prototype.raw = function (length) {
|
||
|
var value = utf8Read(this.view, this.offset, length);
|
||
|
this.offset += length;
|
||
|
return value;
|
||
|
};
|
||
|
Decoder.prototype.array = function (length) {
|
||
|
var value = new Array(length);
|
||
|
for (var i = 0; i < length; i++) {
|
||
|
value[i] = this.parse();
|
||
|
}
|
||
|
return value;
|
||
|
};
|
||
|
Decoder.prototype.parse = function () {
|
||
|
var type = this.view.getUint8(this.offset);
|
||
|
var value, length;
|
||
|
// FixRaw
|
||
|
if ((type & 0xe0) === 0xa0) {
|
||
|
length = type & 0x1f;
|
||
|
this.offset++;
|
||
|
return this.raw(length);
|
||
|
}
|
||
|
// FixMap
|
||
|
if ((type & 0xf0) === 0x80) {
|
||
|
length = type & 0x0f;
|
||
|
this.offset++;
|
||
|
return this.map(length);
|
||
|
}
|
||
|
// FixArray
|
||
|
if ((type & 0xf0) === 0x90) {
|
||
|
length = type & 0x0f;
|
||
|
this.offset++;
|
||
|
return this.array(length);
|
||
|
}
|
||
|
// Positive FixNum
|
||
|
if ((type & 0x80) === 0x00) {
|
||
|
this.offset++;
|
||
|
return type;
|
||
|
}
|
||
|
// Negative Fixnum
|
||
|
if ((type & 0xe0) === 0xe0) {
|
||
|
value = this.view.getInt8(this.offset);
|
||
|
this.offset++;
|
||
|
return value;
|
||
|
}
|
||
|
switch (type) {
|
||
|
// raw 16
|
||
|
case 0xda:
|
||
|
length = this.view.getUint16(this.offset + 1);
|
||
|
this.offset += 3;
|
||
|
return this.raw(length);
|
||
|
// raw 32
|
||
|
case 0xdb:
|
||
|
length = this.view.getUint32(this.offset + 1);
|
||
|
this.offset += 5;
|
||
|
return this.raw(length);
|
||
|
// nil
|
||
|
case 0xc0:
|
||
|
this.offset++;
|
||
|
return null;
|
||
|
// false
|
||
|
case 0xc2:
|
||
|
this.offset++;
|
||
|
return false;
|
||
|
// true
|
||
|
case 0xc3:
|
||
|
this.offset++;
|
||
|
return true;
|
||
|
// undefined
|
||
|
case 0xc4:
|
||
|
this.offset++;
|
||
|
return undefined;
|
||
|
// uint8
|
||
|
case 0xcc:
|
||
|
value = this.view.getUint8(this.offset + 1);
|
||
|
this.offset += 2;
|
||
|
return value;
|
||
|
// uint 16
|
||
|
case 0xcd:
|
||
|
value = this.view.getUint16(this.offset + 1);
|
||
|
this.offset += 3;
|
||
|
return value;
|
||
|
// uint 32
|
||
|
case 0xce:
|
||
|
value = this.view.getUint32(this.offset + 1);
|
||
|
this.offset += 5;
|
||
|
return value;
|
||
|
// int 8
|
||
|
case 0xd0:
|
||
|
value = this.view.getInt8(this.offset + 1);
|
||
|
this.offset += 2;
|
||
|
return value;
|
||
|
// int 16
|
||
|
case 0xd1:
|
||
|
value = this.view.getInt16(this.offset + 1);
|
||
|
this.offset += 3;
|
||
|
return value;
|
||
|
// int 32
|
||
|
case 0xd2:
|
||
|
value = this.view.getInt32(this.offset + 1);
|
||
|
this.offset += 5;
|
||
|
return value;
|
||
|
// map 16
|
||
|
case 0xde:
|
||
|
length = this.view.getUint16(this.offset + 1);
|
||
|
this.offset += 3;
|
||
|
return this.map(length);
|
||
|
// map 32
|
||
|
case 0xdf:
|
||
|
length = this.view.getUint32(this.offset + 1);
|
||
|
this.offset += 5;
|
||
|
return this.map(length);
|
||
|
// array 16
|
||
|
case 0xdc:
|
||
|
length = this.view.getUint16(this.offset + 1);
|
||
|
this.offset += 3;
|
||
|
return this.array(length);
|
||
|
// array 32
|
||
|
case 0xdd:
|
||
|
length = this.view.getUint32(this.offset + 1);
|
||
|
this.offset += 5;
|
||
|
return this.array(length);
|
||
|
// buffer 16
|
||
|
case 0xd8:
|
||
|
length = this.view.getUint16(this.offset + 1);
|
||
|
this.offset += 3;
|
||
|
return this.buf(length);
|
||
|
// buffer 32
|
||
|
case 0xd9:
|
||
|
length = this.view.getUint32(this.offset + 1);
|
||
|
this.offset += 5;
|
||
|
return this.buf(length);
|
||
|
// float
|
||
|
case 0xca:
|
||
|
value = this.view.getFloat32(this.offset + 1);
|
||
|
this.offset += 5;
|
||
|
return value;
|
||
|
// double
|
||
|
case 0xcb:
|
||
|
value = this.view.getFloat64(this.offset + 1);
|
||
|
this.offset += 9;
|
||
|
return value;
|
||
|
}
|
||
|
throw new Error("Unknown type 0x" + type.toString(16));
|
||
|
};
|
||
|
function decode(buffer) {
|
||
|
var view = new DataView(buffer);
|
||
|
var decoder = new Decoder(view);
|
||
|
var value = decoder.parse();
|
||
|
if (decoder.offset !== buffer.byteLength) throw new Error((buffer.byteLength - decoder.offset) + " trailing bytes");
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
function encode(value, view, offset) {
|
||
|
var type = typeof value;
|
||
|
|
||
|
// Strings Bytes
|
||
|
if (type === "string") {
|
||
|
var length = utf8ByteCount(value);
|
||
|
// fix raw
|
||
|
if (length < 0x20) {
|
||
|
view.setUint8(offset, length | 0xa0);
|
||
|
utf8Write(view, offset + 1, value);
|
||
|
return 1 + length;
|
||
|
}
|
||
|
// raw 16
|
||
|
if (length < 0x10000) {
|
||
|
view.setUint8(offset, 0xda);
|
||
|
view.setUint16(offset + 1, length);
|
||
|
utf8Write(view, offset + 3, value);
|
||
|
return 3 + length;
|
||
|
}
|
||
|
// raw 32
|
||
|
if (length < 0x100000000) {
|
||
|
view.setUint8(offset, 0xdb);
|
||
|
view.setUint32(offset + 1, length);
|
||
|
utf8Write(view, offset + 5, value);
|
||
|
return 5 + length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (value instanceof ArrayBuffer) {
|
||
|
var length = value.byteLength;
|
||
|
// buffer 16
|
||
|
if (length < 0x10000) {
|
||
|
view.setUint8(offset, 0xd8);
|
||
|
view.setUint16(offset + 1, length);
|
||
|
(new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 3);
|
||
|
return 3 + length;
|
||
|
}
|
||
|
// buffer 32
|
||
|
if (length < 0x100000000) {
|
||
|
view.setUint8(offset, 0xd9);
|
||
|
view.setUint32(offset + 1, length);
|
||
|
(new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 5);
|
||
|
return 5 + length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (type === "number") {
|
||
|
// Floating Point
|
||
|
if ((value << 0) !== value) {
|
||
|
view.setUint8(offset, 0xcb);
|
||
|
view.setFloat64(offset + 1, value);
|
||
|
return 9;
|
||
|
}
|
||
|
|
||
|
// Integers
|
||
|
if (value >=0) {
|
||
|
// positive fixnum
|
||
|
if (value < 0x80) {
|
||
|
view.setUint8(offset, value);
|
||
|
return 1;
|
||
|
}
|
||
|
// uint 8
|
||
|
if (value < 0x100) {
|
||
|
view.setUint8(offset, 0xcc);
|
||
|
view.setUint8(offset + 1, value);
|
||
|
return 2;
|
||
|
}
|
||
|
// uint 16
|
||
|
if (value < 0x10000) {
|
||
|
view.setUint8(offset, 0xcd);
|
||
|
view.setUint16(offset + 1, value);
|
||
|
return 3;
|
||
|
}
|
||
|
// uint 32
|
||
|
if (value < 0x100000000) {
|
||
|
view.setUint8(offset, 0xce);
|
||
|
view.setUint32(offset + 1, value);
|
||
|
return 5;
|
||
|
}
|
||
|
throw new Error("Number too big 0x" + value.toString(16));
|
||
|
}
|
||
|
// negative fixnum
|
||
|
if (value >= -0x20) {
|
||
|
view.setInt8(offset, value);
|
||
|
return 1;
|
||
|
}
|
||
|
// int 8
|
||
|
if (value >= -0x80) {
|
||
|
view.setUint8(offset, 0xd0);
|
||
|
view.setInt8(offset + 1, value);
|
||
|
return 2;
|
||
|
}
|
||
|
// int 16
|
||
|
if (value >= -0x8000) {
|
||
|
view.setUint8(offset, 0xd1);
|
||
|
view.setInt16(offset + 1, value);
|
||
|
return 3;
|
||
|
}
|
||
|
// int 32
|
||
|
if (value >= -0x80000000) {
|
||
|
view.setUint8(offset, 0xd2);
|
||
|
view.setInt32(offset + 1, value);
|
||
|
return 5;
|
||
|
}
|
||
|
throw new Error("Number too small -0x" + (-value).toString(16).substr(1));
|
||
|
}
|
||
|
|
||
|
// undefined
|
||
|
if (type === "undefined") {
|
||
|
view.setUint8(offset, 0xc4);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// null
|
||
|
if (value === null) {
|
||
|
view.setUint8(offset, 0xc0);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// Boolean
|
||
|
if (type === "boolean") {
|
||
|
view.setUint8(offset, value ? 0xc3 : 0xc2);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// Container Types
|
||
|
if (type === "object") {
|
||
|
var length, size = 0;
|
||
|
var isArray = Array.isArray(value);
|
||
|
|
||
|
if (isArray) {
|
||
|
length = value.length;
|
||
|
}
|
||
|
else {
|
||
|
var keys = Object.keys(value);
|
||
|
length = keys.length;
|
||
|
}
|
||
|
|
||
|
var size;
|
||
|
if (length < 0x10) {
|
||
|
view.setUint8(offset, length | (isArray ? 0x90 : 0x80));
|
||
|
size = 1;
|
||
|
}
|
||
|
else if (length < 0x10000) {
|
||
|
view.setUint8(offset, isArray ? 0xdc : 0xde);
|
||
|
view.setUint16(offset + 1, length);
|
||
|
size = 3;
|
||
|
}
|
||
|
else if (length < 0x100000000) {
|
||
|
view.setUint8(offset, isArray ? 0xdd : 0xdf);
|
||
|
view.setUint32(offset + 1, length);
|
||
|
size = 5;
|
||
|
}
|
||
|
|
||
|
if (isArray) {
|
||
|
for (var i = 0; i < length; i++) {
|
||
|
size += encode(value[i], view, offset + size);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
for (var i = 0; i < length; i++) {
|
||
|
var key = keys[i];
|
||
|
size += encode(key, view, offset + size);
|
||
|
size += encode(value[key], view, offset + size);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
throw new Error("Unknown type " + type);
|
||
|
}
|
||
|
|
||
|
function sizeof(value) {
|
||
|
var type = typeof value;
|
||
|
|
||
|
// Raw Bytes
|
||
|
if (type === "string") {
|
||
|
var length = utf8ByteCount(value);
|
||
|
if (length < 0x20) {
|
||
|
return 1 + length;
|
||
|
}
|
||
|
if (length < 0x10000) {
|
||
|
return 3 + length;
|
||
|
}
|
||
|
if (length < 0x100000000) {
|
||
|
return 5 + length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (value instanceof ArrayBuffer) {
|
||
|
var length = value.byteLength;
|
||
|
if (length < 0x10000) {
|
||
|
return 3 + length;
|
||
|
}
|
||
|
if (length < 0x100000000) {
|
||
|
return 5 + length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (type === "number") {
|
||
|
// Floating Point
|
||
|
// double
|
||
|
if (value << 0 !== value) return 9;
|
||
|
|
||
|
// Integers
|
||
|
if (value >=0) {
|
||
|
// positive fixnum
|
||
|
if (value < 0x80) return 1;
|
||
|
// uint 8
|
||
|
if (value < 0x100) return 2;
|
||
|
// uint 16
|
||
|
if (value < 0x10000) return 3;
|
||
|
// uint 32
|
||
|
if (value < 0x100000000) return 5;
|
||
|
// uint 64
|
||
|
if (value < 0x10000000000000000) return 9;
|
||
|
throw new Error("Number too big 0x" + value.toString(16));
|
||
|
}
|
||
|
// negative fixnum
|
||
|
if (value >= -0x20) return 1;
|
||
|
// int 8
|
||
|
if (value >= -0x80) return 2;
|
||
|
// int 16
|
||
|
if (value >= -0x8000) return 3;
|
||
|
// int 32
|
||
|
if (value >= -0x80000000) return 5;
|
||
|
// int 64
|
||
|
if (value >= -0x8000000000000000) return 9;
|
||
|
throw new Error("Number too small -0x" + value.toString(16).substr(1));
|
||
|
}
|
||
|
|
||
|
// Boolean, null, undefined
|
||
|
if (type === "boolean" || type === "undefined" || value === null) return 1;
|
||
|
|
||
|
// Container Types
|
||
|
if (type === "object") {
|
||
|
var length, size = 0;
|
||
|
if (Array.isArray(value)) {
|
||
|
length = value.length;
|
||
|
for (var i = 0; i < length; i++) {
|
||
|
size += sizeof(value[i]);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
var keys = Object.keys(value);
|
||
|
length = keys.length;
|
||
|
for (var i = 0; i < length; i++) {
|
||
|
var key = keys[i];
|
||
|
size += sizeof(key) + sizeof(value[key]);
|
||
|
}
|
||
|
}
|
||
|
if (length < 0x10) {
|
||
|
return 1 + size;
|
||
|
}
|
||
|
if (length < 0x10000) {
|
||
|
return 3 + size;
|
||
|
}
|
||
|
if (length < 0x100000000) {
|
||
|
return 5 + size;
|
||
|
}
|
||
|
throw new Error("Array or object too long 0x" + length.toString(16));
|
||
|
}
|
||
|
throw new Error("Unknown type " + type);
|
||
|
}
|
||
|
|
||
|
return exports;
|
||
|
|
||
|
});
|