├── .npmignore ├── .gitignore ├── Makefile ├── README.md ├── lib ├── exports.js ├── bufferbuilder.js └── binarypack.js ├── package.json ├── LICENSE ├── Gruntfile.js ├── dist ├── binarypack.min.js └── binarypack.js └── test └── index.html /.npmignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: compress 2 | 3 | compress: 4 | @./node_modules/.bin/grunt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BinaryPack for Javascript browsers 2 | ======== 3 | 4 | BinaryPack is 95% MessagePack. The protocol has been extended to support distinct string and binary types. 5 | 6 | Inspired by: https://github.com/cuzic/MessagePack-JS -------------------------------------------------------------------------------- /lib/exports.js: -------------------------------------------------------------------------------- 1 | var BufferBuilderExports = require('./bufferbuilder'); 2 | 3 | window.BufferBuilder = BufferBuilderExports.BufferBuilder; 4 | window.binaryFeatures = BufferBuilderExports.binaryFeatures; 5 | window.BlobBuilder = BufferBuilderExports.BlobBuilder; 6 | window.BinaryPack = require('./binarypack'); 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-binarypack", 3 | "version": "0.0.9", 4 | "description": "BinaryPack serialization for the web browser", 5 | "homepage": "https://github.com/binaryjs/js-binarypack", 6 | "main": "./lib/binarypack.js", 7 | "scripts": { 8 | "prepublish": "./node_modules/.bin/grunt", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git://github.com/binaryjs/js-binarypack.git" 14 | }, 15 | "author": "Eric Zhang", 16 | "devDependencies": { 17 | "grunt": "^0.4.5", 18 | "grunt-browserify": "^3.0.1", 19 | "grunt-cli": "^0.1.13", 20 | "grunt-contrib-concat": "^0.5.0", 21 | "grunt-contrib-uglify": "^0.5.1", 22 | "uglifyjs": "^2.3.6" 23 | }, 24 | "license": "BSD" 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Eric Zhang, http://binaryjs.com 2 | 3 | (The MIT License) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.initConfig({ 3 | pkg: grunt.file.readJSON('package.json'), 4 | 5 | browserify: { 6 | dev: { 7 | options: { 8 | prepend: ['/*! binarypack.js build:<%= pkg.version %>, development. '+ 9 | 'Copyright(c) 2012 Eric Zhang MIT Licensed */'] 10 | }, 11 | src: ['lib/exports.js'], 12 | dest: 'dist/binarypack.js' 13 | } 14 | }, 15 | 16 | uglify: { 17 | prod: { 18 | options: { 19 | mangle: true, compress: true, 20 | }, 21 | src: 'dist/binarypack.js', 22 | dest: 'dist/binarypack.min.js' 23 | } 24 | }, 25 | 26 | concat: { 27 | dev: { 28 | options: { 29 | banner: '/*! binarypack.js build:<%= pkg.version %>, production. '+ 30 | 'Copyright(c) 2012 Eric Zhang MIT Licensed */' 31 | }, 32 | src: 'dist/binarypack.js', 33 | dest: 'dist/binarypack.js', 34 | }, 35 | prod: { 36 | options: { 37 | banner: '/*! binarypack.js build:<%= pkg.version %>, production. '+ 38 | 'Copyright(c) 2012 Eric Zhang MIT Licensed */' 39 | }, 40 | src: 'dist/binarypack.min.js', 41 | dest: 'dist/binarypack.min.js', 42 | } 43 | } 44 | }); 45 | 46 | grunt.loadNpmTasks('grunt-browserify'); 47 | grunt.loadNpmTasks('grunt-contrib-uglify'); 48 | grunt.loadNpmTasks('grunt-contrib-concat'); 49 | 50 | grunt.registerTask('default', ['browserify', 'uglify', 'concat']); 51 | } -------------------------------------------------------------------------------- /lib/bufferbuilder.js: -------------------------------------------------------------------------------- 1 | var binaryFeatures = {}; 2 | binaryFeatures.useBlobBuilder = (function(){ 3 | try { 4 | new Blob([]); 5 | return false; 6 | } catch (e) { 7 | return true; 8 | } 9 | })(); 10 | 11 | binaryFeatures.useArrayBufferView = !binaryFeatures.useBlobBuilder && (function(){ 12 | try { 13 | return (new Blob([new Uint8Array([])])).size === 0; 14 | } catch (e) { 15 | return true; 16 | } 17 | })(); 18 | 19 | module.exports.binaryFeatures = binaryFeatures; 20 | var BlobBuilder = module.exports.BlobBuilder; 21 | if (typeof window != 'undefined') { 22 | BlobBuilder = module.exports.BlobBuilder = window.WebKitBlobBuilder || 23 | window.MozBlobBuilder || window.MSBlobBuilder || window.BlobBuilder; 24 | } 25 | 26 | function BufferBuilder(){ 27 | this._pieces = []; 28 | this._parts = []; 29 | } 30 | 31 | BufferBuilder.prototype.append = function(data) { 32 | if(typeof data === 'number') { 33 | this._pieces.push(data); 34 | } else { 35 | this.flush(); 36 | this._parts.push(data); 37 | } 38 | }; 39 | 40 | BufferBuilder.prototype.flush = function() { 41 | if (this._pieces.length > 0) { 42 | var buf = new Uint8Array(this._pieces); 43 | if(!binaryFeatures.useArrayBufferView) { 44 | buf = buf.buffer; 45 | } 46 | this._parts.push(buf); 47 | this._pieces = []; 48 | } 49 | }; 50 | 51 | BufferBuilder.prototype.getBuffer = function() { 52 | this.flush(); 53 | if(binaryFeatures.useBlobBuilder) { 54 | var builder = new BlobBuilder(); 55 | for(var i = 0, ii = this._parts.length; i < ii; i++) { 56 | builder.append(this._parts[i]); 57 | } 58 | return builder.getBlob(); 59 | } else { 60 | return new Blob(this._parts); 61 | } 62 | }; 63 | 64 | module.exports.BufferBuilder = BufferBuilder; 65 | -------------------------------------------------------------------------------- /dist/binarypack.min.js: -------------------------------------------------------------------------------- 1 | /*! binarypack.js build:0.0.9, production. Copyright(c) 2012 Eric Zhang MIT Licensed */!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=b?"00":65535>=b?"000":2097151>=b?"0000":67108863>=b?"00000":"000000"}function f(a){return a.length>600?new Blob([a]).size:a.replace(/[^\u0000-\u007F]/g,e).length}var g=a("./bufferbuilder").BufferBuilder,h=a("./bufferbuilder").binaryFeatures,i={unpack:function(a){var b=new c(a);return b.unpack()},pack:function(a){var b=new d;b.pack(a);var c=b.getBuffer();return c}};b.exports=i,c.prototype.unpack=function(){var a=this.unpack_uint8();if(128>a){var b=a;return b}if(32>(224^a)){var c=(224^a)-32;return c}var d;if((d=160^a)<=15)return this.unpack_raw(d);if((d=176^a)<=15)return this.unpack_string(d);if((d=144^a)<=15)return this.unpack_array(d);if((d=128^a)<=15)return this.unpack_map(d);switch(a){case 192:return null;case 193:return void 0;case 194:return!1;case 195:return!0;case 202:return this.unpack_float();case 203:return this.unpack_double();case 204:return this.unpack_uint8();case 205:return this.unpack_uint16();case 206:return this.unpack_uint32();case 207:return this.unpack_uint64();case 208:return this.unpack_int8();case 209:return this.unpack_int16();case 210:return this.unpack_int32();case 211:return this.unpack_int64();case 212:return void 0;case 213:return void 0;case 214:return void 0;case 215:return void 0;case 216:return d=this.unpack_uint16(),this.unpack_string(d);case 217:return d=this.unpack_uint32(),this.unpack_string(d);case 218:return d=this.unpack_uint16(),this.unpack_raw(d);case 219:return d=this.unpack_uint32(),this.unpack_raw(d);case 220:return d=this.unpack_uint16(),this.unpack_array(d);case 221:return d=this.unpack_uint32(),this.unpack_array(d);case 222:return d=this.unpack_uint16(),this.unpack_map(d);case 223:return d=this.unpack_uint32(),this.unpack_map(d)}},c.prototype.unpack_uint8=function(){var a=255&this.dataView[this.index];return this.index++,a},c.prototype.unpack_uint16=function(){var a=this.read(2),b=256*(255&a[0])+(255&a[1]);return this.index+=2,b},c.prototype.unpack_uint32=function(){var a=this.read(4),b=256*(256*(256*a[0]+a[1])+a[2])+a[3];return this.index+=4,b},c.prototype.unpack_uint64=function(){var a=this.read(8),b=256*(256*(256*(256*(256*(256*(256*a[0]+a[1])+a[2])+a[3])+a[4])+a[5])+a[6])+a[7];return this.index+=8,b},c.prototype.unpack_int8=function(){var a=this.unpack_uint8();return 128>a?a:a-256},c.prototype.unpack_int16=function(){var a=this.unpack_uint16();return 32768>a?a:a-65536},c.prototype.unpack_int32=function(){var a=this.unpack_uint32();return ae;)b=d[e],128>b?(f+=String.fromCharCode(b),e++):32>(192^b)?(c=(192^b)<<6|63&d[e+1],f+=String.fromCharCode(c),e+=2):(c=(15&b)<<12|(63&d[e+1])<<6|63&d[e+2],f+=String.fromCharCode(c),e+=3);return this.index+=a,f},c.prototype.unpack_array=function(a){for(var b=new Array(a),c=0;a>c;c++)b[c]=this.unpack();return b},c.prototype.unpack_map=function(a){for(var b={},c=0;a>c;c++){var d=this.unpack(),e=this.unpack();b[d]=e}return b},c.prototype.unpack_float=function(){var a=this.unpack_uint32(),b=a>>31,c=(a>>23&255)-127,d=8388607&a|8388608;return(0==b?1:-1)*d*Math.pow(2,c-23)},c.prototype.unpack_double=function(){var a=this.unpack_uint32(),b=this.unpack_uint32(),c=a>>31,d=(a>>20&2047)-1023,e=1048575&a|1048576,f=e*Math.pow(2,d-20)+b*Math.pow(2,d-52);return(0==c?1:-1)*f},c.prototype.read=function(a){var b=this.index;if(b+a<=this.length)return this.dataView.subarray(b,b+a);throw new Error("BinaryPackFailure: read index out of range")},d.prototype.getBuffer=function(){return this.bufferBuilder.getBuffer()},d.prototype.pack=function(a){var b=typeof a;if("string"==b)this.pack_string(a);else if("number"==b)Math.floor(a)===a?this.pack_integer(a):this.pack_double(a);else if("boolean"==b)a===!0?this.bufferBuilder.append(195):a===!1&&this.bufferBuilder.append(194);else if("undefined"==b)this.bufferBuilder.append(192);else{if("object"!=b)throw new Error('Type "'+b+'" not yet supported');if(null===a)this.bufferBuilder.append(192);else{var c=a.constructor;if(c==Array)this.pack_array(a);else if(c==Blob||c==File)this.pack_bin(a);else if(c==ArrayBuffer)this.pack_bin(h.useArrayBufferView?new Uint8Array(a):a);else if("BYTES_PER_ELEMENT"in a)this.pack_bin(h.useArrayBufferView?new Uint8Array(a.buffer):a.buffer);else if(c==Object)this.pack_object(a);else if(c==Date)this.pack_string(a.toString());else{if("function"!=typeof a.toBinaryPack)throw new Error('Type "'+c.toString()+'" not yet supported');this.bufferBuilder.append(a.toBinaryPack())}}}this.bufferBuilder.flush()},d.prototype.pack_bin=function(a){var b=a.length||a.byteLength||a.size;if(15>=b)this.pack_uint8(160+b);else if(65535>=b)this.bufferBuilder.append(218),this.pack_uint16(b);else{if(!(4294967295>=b))throw new Error("Invalid length");this.bufferBuilder.append(219),this.pack_uint32(b)}this.bufferBuilder.append(a)},d.prototype.pack_string=function(a){var b=f(a);if(15>=b)this.pack_uint8(176+b);else if(65535>=b)this.bufferBuilder.append(216),this.pack_uint16(b);else{if(!(4294967295>=b))throw new Error("Invalid length");this.bufferBuilder.append(217),this.pack_uint32(b)}this.bufferBuilder.append(a)},d.prototype.pack_array=function(a){var b=a.length;if(15>=b)this.pack_uint8(144+b);else if(65535>=b)this.bufferBuilder.append(220),this.pack_uint16(b);else{if(!(4294967295>=b))throw new Error("Invalid length");this.bufferBuilder.append(221),this.pack_uint32(b)}for(var c=0;b>c;c++)this.pack(a[c])},d.prototype.pack_integer=function(a){if(a>=-32&&127>=a)this.bufferBuilder.append(255&a);else if(a>=0&&255>=a)this.bufferBuilder.append(204),this.pack_uint8(a);else if(a>=-128&&127>=a)this.bufferBuilder.append(208),this.pack_int8(a);else if(a>=0&&65535>=a)this.bufferBuilder.append(205),this.pack_uint16(a);else if(a>=-32768&&32767>=a)this.bufferBuilder.append(209),this.pack_int16(a);else if(a>=0&&4294967295>=a)this.bufferBuilder.append(206),this.pack_uint32(a);else if(a>=-2147483648&&2147483647>=a)this.bufferBuilder.append(210),this.pack_int32(a);else if(a>=-0x8000000000000000&&0x8000000000000000>=a)this.bufferBuilder.append(211),this.pack_int64(a);else{if(!(a>=0&&0x10000000000000000>=a))throw new Error("Invalid integer");this.bufferBuilder.append(207),this.pack_uint64(a)}},d.prototype.pack_double=function(a){var b=0;0>a&&(b=1,a=-a);var c=Math.floor(Math.log(a)/Math.LN2),d=a/Math.pow(2,c)-1,e=Math.floor(d*Math.pow(2,52)),f=Math.pow(2,32),g=b<<31|c+1023<<20|e/f&1048575,h=e%f;this.bufferBuilder.append(203),this.pack_int32(g),this.pack_int32(h)},d.prototype.pack_object=function(a){var b=Object.keys(a),c=b.length;if(15>=c)this.pack_uint8(128+c);else if(65535>=c)this.bufferBuilder.append(222),this.pack_uint16(c);else{if(!(4294967295>=c))throw new Error("Invalid length");this.bufferBuilder.append(223),this.pack_uint32(c)}for(var d in a)a.hasOwnProperty(d)&&(this.pack(d),this.pack(a[d]))},d.prototype.pack_uint8=function(a){this.bufferBuilder.append(a)},d.prototype.pack_uint16=function(a){this.bufferBuilder.append(a>>8),this.bufferBuilder.append(255&a)},d.prototype.pack_uint32=function(a){var b=4294967295&a;this.bufferBuilder.append((4278190080&b)>>>24),this.bufferBuilder.append((16711680&b)>>>16),this.bufferBuilder.append((65280&b)>>>8),this.bufferBuilder.append(255&b)},d.prototype.pack_uint64=function(a){var b=a/Math.pow(2,32),c=a%Math.pow(2,32);this.bufferBuilder.append((4278190080&b)>>>24),this.bufferBuilder.append((16711680&b)>>>16),this.bufferBuilder.append((65280&b)>>>8),this.bufferBuilder.append(255&b),this.bufferBuilder.append((4278190080&c)>>>24),this.bufferBuilder.append((16711680&c)>>>16),this.bufferBuilder.append((65280&c)>>>8),this.bufferBuilder.append(255&c)},d.prototype.pack_int8=function(a){this.bufferBuilder.append(255&a)},d.prototype.pack_int16=function(a){this.bufferBuilder.append((65280&a)>>8),this.bufferBuilder.append(255&a)},d.prototype.pack_int32=function(a){this.bufferBuilder.append(a>>>24&255),this.bufferBuilder.append((16711680&a)>>>16),this.bufferBuilder.append((65280&a)>>>8),this.bufferBuilder.append(255&a)},d.prototype.pack_int64=function(a){var b=Math.floor(a/Math.pow(2,32)),c=a%Math.pow(2,32);this.bufferBuilder.append((4278190080&b)>>>24),this.bufferBuilder.append((16711680&b)>>>16),this.bufferBuilder.append((65280&b)>>>8),this.bufferBuilder.append(255&b),this.bufferBuilder.append((4278190080&c)>>>24),this.bufferBuilder.append((16711680&c)>>>16),this.bufferBuilder.append((65280&c)>>>8),this.bufferBuilder.append(255&c)}},{"./bufferbuilder":2}],2:[function(a,b){function c(){this._pieces=[],this._parts=[]}var d={};d.useBlobBuilder=function(){try{return new Blob([]),!1}catch(a){return!0}}(),d.useArrayBufferView=!d.useBlobBuilder&&function(){try{return 0===new Blob([new Uint8Array([])]).size}catch(a){return!0}}(),b.exports.binaryFeatures=d;var e=b.exports.BlobBuilder;"undefined"!=typeof window&&(e=b.exports.BlobBuilder=window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder||window.BlobBuilder),c.prototype.append=function(a){"number"==typeof a?this._pieces.push(a):(this.flush(),this._parts.push(a))},c.prototype.flush=function(){if(this._pieces.length>0){var a=new Uint8Array(this._pieces);d.useArrayBufferView||(a=a.buffer),this._parts.push(a),this._pieces=[]}},c.prototype.getBuffer=function(){if(this.flush(),d.useBlobBuilder){for(var a=new e,b=0,c=this._parts.length;c>b;b++)a.append(this._parts[b]);return a.getBlob()}return new Blob(this._parts)},b.exports.BufferBuilder=c},{}],3:[function(a){var b=a("./bufferbuilder");window.BufferBuilder=b.BufferBuilder,window.binaryFeatures=b.binaryFeatures,window.BlobBuilder=b.BlobBuilder,window.BinaryPack=a("./binarypack")},{"./binarypack":1,"./bufferbuilder":2}]},{},[3]); -------------------------------------------------------------------------------- /lib/binarypack.js: -------------------------------------------------------------------------------- 1 | var BufferBuilder = require('./bufferbuilder').BufferBuilder; 2 | var binaryFeatures = require('./bufferbuilder').binaryFeatures; 3 | 4 | var BinaryPack = { 5 | unpack: function(data){ 6 | var unpacker = new Unpacker(data); 7 | return unpacker.unpack(); 8 | }, 9 | pack: function(data){ 10 | var packer = new Packer(); 11 | packer.pack(data); 12 | var buffer = packer.getBuffer(); 13 | return buffer; 14 | } 15 | }; 16 | 17 | module.exports = BinaryPack; 18 | 19 | function Unpacker (data){ 20 | // Data is ArrayBuffer 21 | this.index = 0; 22 | this.dataBuffer = data; 23 | this.dataView = new Uint8Array(this.dataBuffer); 24 | this.length = this.dataBuffer.byteLength; 25 | } 26 | 27 | Unpacker.prototype.unpack = function(){ 28 | var type = this.unpack_uint8(); 29 | if (type < 0x80){ 30 | var positive_fixnum = type; 31 | return positive_fixnum; 32 | } else if ((type ^ 0xe0) < 0x20){ 33 | var negative_fixnum = (type ^ 0xe0) - 0x20; 34 | return negative_fixnum; 35 | } 36 | var size; 37 | if ((size = type ^ 0xa0) <= 0x0f){ 38 | return this.unpack_raw(size); 39 | } else if ((size = type ^ 0xb0) <= 0x0f){ 40 | return this.unpack_string(size); 41 | } else if ((size = type ^ 0x90) <= 0x0f){ 42 | return this.unpack_array(size); 43 | } else if ((size = type ^ 0x80) <= 0x0f){ 44 | return this.unpack_map(size); 45 | } 46 | switch(type){ 47 | case 0xc0: 48 | return null; 49 | case 0xc1: 50 | return undefined; 51 | case 0xc2: 52 | return false; 53 | case 0xc3: 54 | return true; 55 | case 0xca: 56 | return this.unpack_float(); 57 | case 0xcb: 58 | return this.unpack_double(); 59 | case 0xcc: 60 | return this.unpack_uint8(); 61 | case 0xcd: 62 | return this.unpack_uint16(); 63 | case 0xce: 64 | return this.unpack_uint32(); 65 | case 0xcf: 66 | return this.unpack_uint64(); 67 | case 0xd0: 68 | return this.unpack_int8(); 69 | case 0xd1: 70 | return this.unpack_int16(); 71 | case 0xd2: 72 | return this.unpack_int32(); 73 | case 0xd3: 74 | return this.unpack_int64(); 75 | case 0xd4: 76 | return undefined; 77 | case 0xd5: 78 | return undefined; 79 | case 0xd6: 80 | return undefined; 81 | case 0xd7: 82 | return undefined; 83 | case 0xd8: 84 | size = this.unpack_uint16(); 85 | return this.unpack_string(size); 86 | case 0xd9: 87 | size = this.unpack_uint32(); 88 | return this.unpack_string(size); 89 | case 0xda: 90 | size = this.unpack_uint16(); 91 | return this.unpack_raw(size); 92 | case 0xdb: 93 | size = this.unpack_uint32(); 94 | return this.unpack_raw(size); 95 | case 0xdc: 96 | size = this.unpack_uint16(); 97 | return this.unpack_array(size); 98 | case 0xdd: 99 | size = this.unpack_uint32(); 100 | return this.unpack_array(size); 101 | case 0xde: 102 | size = this.unpack_uint16(); 103 | return this.unpack_map(size); 104 | case 0xdf: 105 | size = this.unpack_uint32(); 106 | return this.unpack_map(size); 107 | } 108 | } 109 | 110 | Unpacker.prototype.unpack_uint8 = function(){ 111 | var byte = this.dataView[this.index] & 0xff; 112 | this.index++; 113 | return byte; 114 | }; 115 | 116 | Unpacker.prototype.unpack_uint16 = function(){ 117 | var bytes = this.read(2); 118 | var uint16 = 119 | ((bytes[0] & 0xff) * 256) + (bytes[1] & 0xff); 120 | this.index += 2; 121 | return uint16; 122 | } 123 | 124 | Unpacker.prototype.unpack_uint32 = function(){ 125 | var bytes = this.read(4); 126 | var uint32 = 127 | ((bytes[0] * 256 + 128 | bytes[1]) * 256 + 129 | bytes[2]) * 256 + 130 | bytes[3]; 131 | this.index += 4; 132 | return uint32; 133 | } 134 | 135 | Unpacker.prototype.unpack_uint64 = function(){ 136 | var bytes = this.read(8); 137 | var uint64 = 138 | ((((((bytes[0] * 256 + 139 | bytes[1]) * 256 + 140 | bytes[2]) * 256 + 141 | bytes[3]) * 256 + 142 | bytes[4]) * 256 + 143 | bytes[5]) * 256 + 144 | bytes[6]) * 256 + 145 | bytes[7]; 146 | this.index += 8; 147 | return uint64; 148 | } 149 | 150 | 151 | Unpacker.prototype.unpack_int8 = function(){ 152 | var uint8 = this.unpack_uint8(); 153 | return (uint8 < 0x80 ) ? uint8 : uint8 - (1 << 8); 154 | }; 155 | 156 | Unpacker.prototype.unpack_int16 = function(){ 157 | var uint16 = this.unpack_uint16(); 158 | return (uint16 < 0x8000 ) ? uint16 : uint16 - (1 << 16); 159 | } 160 | 161 | Unpacker.prototype.unpack_int32 = function(){ 162 | var uint32 = this.unpack_uint32(); 163 | return (uint32 < Math.pow(2, 31) ) ? uint32 : 164 | uint32 - Math.pow(2, 32); 165 | } 166 | 167 | Unpacker.prototype.unpack_int64 = function(){ 168 | var uint64 = this.unpack_uint64(); 169 | return (uint64 < Math.pow(2, 63) ) ? uint64 : 170 | uint64 - Math.pow(2, 64); 171 | } 172 | 173 | Unpacker.prototype.unpack_raw = function(size){ 174 | if ( this.length < this.index + size){ 175 | throw new Error('BinaryPackFailure: index is out of range' 176 | + ' ' + this.index + ' ' + size + ' ' + this.length); 177 | } 178 | var buf = this.dataBuffer.slice(this.index, this.index + size); 179 | this.index += size; 180 | 181 | //buf = util.bufferToString(buf); 182 | 183 | return buf; 184 | } 185 | 186 | Unpacker.prototype.unpack_string = function(size){ 187 | var bytes = this.read(size); 188 | var i = 0, str = '', c, code; 189 | while(i < size){ 190 | c = bytes[i]; 191 | if ( c < 128){ 192 | str += String.fromCharCode(c); 193 | i++; 194 | } else if ((c ^ 0xc0) < 32){ 195 | code = ((c ^ 0xc0) << 6) | (bytes[i+1] & 63); 196 | str += String.fromCharCode(code); 197 | i += 2; 198 | } else { 199 | code = ((c & 15) << 12) | ((bytes[i+1] & 63) << 6) | 200 | (bytes[i+2] & 63); 201 | str += String.fromCharCode(code); 202 | i += 3; 203 | } 204 | } 205 | this.index += size; 206 | return str; 207 | } 208 | 209 | Unpacker.prototype.unpack_array = function(size){ 210 | var objects = new Array(size); 211 | for(var i = 0; i < size ; i++){ 212 | objects[i] = this.unpack(); 213 | } 214 | return objects; 215 | } 216 | 217 | Unpacker.prototype.unpack_map = function(size){ 218 | var map = {}; 219 | for(var i = 0; i < size ; i++){ 220 | var key = this.unpack(); 221 | var value = this.unpack(); 222 | map[key] = value; 223 | } 224 | return map; 225 | } 226 | 227 | Unpacker.prototype.unpack_float = function(){ 228 | var uint32 = this.unpack_uint32(); 229 | var sign = uint32 >> 31; 230 | var exp = ((uint32 >> 23) & 0xff) - 127; 231 | var fraction = ( uint32 & 0x7fffff ) | 0x800000; 232 | return (sign == 0 ? 1 : -1) * 233 | fraction * Math.pow(2, exp - 23); 234 | } 235 | 236 | Unpacker.prototype.unpack_double = function(){ 237 | var h32 = this.unpack_uint32(); 238 | var l32 = this.unpack_uint32(); 239 | var sign = h32 >> 31; 240 | var exp = ((h32 >> 20) & 0x7ff) - 1023; 241 | var hfrac = ( h32 & 0xfffff ) | 0x100000; 242 | var frac = hfrac * Math.pow(2, exp - 20) + 243 | l32 * Math.pow(2, exp - 52); 244 | return (sign == 0 ? 1 : -1) * frac; 245 | } 246 | 247 | Unpacker.prototype.read = function(length){ 248 | var j = this.index; 249 | if (j + length <= this.length) { 250 | return this.dataView.subarray(j, j + length); 251 | } else { 252 | throw new Error('BinaryPackFailure: read index out of range'); 253 | } 254 | } 255 | 256 | function Packer(){ 257 | this.bufferBuilder = new BufferBuilder(); 258 | } 259 | 260 | Packer.prototype.getBuffer = function(){ 261 | return this.bufferBuilder.getBuffer(); 262 | } 263 | 264 | Packer.prototype.pack = function(value){ 265 | var type = typeof(value); 266 | if (type == 'string'){ 267 | this.pack_string(value); 268 | } else if (type == 'number'){ 269 | if (Math.floor(value) === value){ 270 | this.pack_integer(value); 271 | } else{ 272 | this.pack_double(value); 273 | } 274 | } else if (type == 'boolean'){ 275 | if (value === true){ 276 | this.bufferBuilder.append(0xc3); 277 | } else if (value === false){ 278 | this.bufferBuilder.append(0xc2); 279 | } 280 | } else if (type == 'undefined'){ 281 | this.bufferBuilder.append(0xc0); 282 | } else if (type == 'object'){ 283 | if (value === null){ 284 | this.bufferBuilder.append(0xc0); 285 | } else { 286 | var constructor = value.constructor; 287 | if (constructor == Array){ 288 | this.pack_array(value); 289 | } else if (constructor == Blob || constructor == File) { 290 | this.pack_bin(value); 291 | } else if (constructor == ArrayBuffer) { 292 | if(binaryFeatures.useArrayBufferView) { 293 | this.pack_bin(new Uint8Array(value)); 294 | } else { 295 | this.pack_bin(value); 296 | } 297 | } else if ('BYTES_PER_ELEMENT' in value){ 298 | if(binaryFeatures.useArrayBufferView) { 299 | this.pack_bin(new Uint8Array(value.buffer)); 300 | } else { 301 | this.pack_bin(value.buffer); 302 | } 303 | } else if (constructor == Object){ 304 | this.pack_object(value); 305 | } else if (constructor == Date){ 306 | this.pack_string(value.toString()); 307 | } else if (typeof value.toBinaryPack == 'function'){ 308 | this.bufferBuilder.append(value.toBinaryPack()); 309 | } else { 310 | throw new Error('Type "' + constructor.toString() + '" not yet supported'); 311 | } 312 | } 313 | } else { 314 | throw new Error('Type "' + type + '" not yet supported'); 315 | } 316 | this.bufferBuilder.flush(); 317 | } 318 | 319 | 320 | Packer.prototype.pack_bin = function(blob){ 321 | var length = blob.length || blob.byteLength || blob.size; 322 | if (length <= 0x0f){ 323 | this.pack_uint8(0xa0 + length); 324 | } else if (length <= 0xffff){ 325 | this.bufferBuilder.append(0xda) ; 326 | this.pack_uint16(length); 327 | } else if (length <= 0xffffffff){ 328 | this.bufferBuilder.append(0xdb); 329 | this.pack_uint32(length); 330 | } else{ 331 | throw new Error('Invalid length'); 332 | } 333 | this.bufferBuilder.append(blob); 334 | } 335 | 336 | Packer.prototype.pack_string = function(str){ 337 | var length = utf8Length(str); 338 | 339 | if (length <= 0x0f){ 340 | this.pack_uint8(0xb0 + length); 341 | } else if (length <= 0xffff){ 342 | this.bufferBuilder.append(0xd8) ; 343 | this.pack_uint16(length); 344 | } else if (length <= 0xffffffff){ 345 | this.bufferBuilder.append(0xd9); 346 | this.pack_uint32(length); 347 | } else{ 348 | throw new Error('Invalid length'); 349 | } 350 | this.bufferBuilder.append(str); 351 | } 352 | 353 | Packer.prototype.pack_array = function(ary){ 354 | var length = ary.length; 355 | if (length <= 0x0f){ 356 | this.pack_uint8(0x90 + length); 357 | } else if (length <= 0xffff){ 358 | this.bufferBuilder.append(0xdc) 359 | this.pack_uint16(length); 360 | } else if (length <= 0xffffffff){ 361 | this.bufferBuilder.append(0xdd); 362 | this.pack_uint32(length); 363 | } else{ 364 | throw new Error('Invalid length'); 365 | } 366 | for(var i = 0; i < length ; i++){ 367 | this.pack(ary[i]); 368 | } 369 | } 370 | 371 | Packer.prototype.pack_integer = function(num){ 372 | if ( -0x20 <= num && num <= 0x7f){ 373 | this.bufferBuilder.append(num & 0xff); 374 | } else if (0x00 <= num && num <= 0xff){ 375 | this.bufferBuilder.append(0xcc); 376 | this.pack_uint8(num); 377 | } else if (-0x80 <= num && num <= 0x7f){ 378 | this.bufferBuilder.append(0xd0); 379 | this.pack_int8(num); 380 | } else if ( 0x0000 <= num && num <= 0xffff){ 381 | this.bufferBuilder.append(0xcd); 382 | this.pack_uint16(num); 383 | } else if (-0x8000 <= num && num <= 0x7fff){ 384 | this.bufferBuilder.append(0xd1); 385 | this.pack_int16(num); 386 | } else if ( 0x00000000 <= num && num <= 0xffffffff){ 387 | this.bufferBuilder.append(0xce); 388 | this.pack_uint32(num); 389 | } else if (-0x80000000 <= num && num <= 0x7fffffff){ 390 | this.bufferBuilder.append(0xd2); 391 | this.pack_int32(num); 392 | } else if (-0x8000000000000000 <= num && num <= 0x7FFFFFFFFFFFFFFF){ 393 | this.bufferBuilder.append(0xd3); 394 | this.pack_int64(num); 395 | } else if (0x0000000000000000 <= num && num <= 0xFFFFFFFFFFFFFFFF){ 396 | this.bufferBuilder.append(0xcf); 397 | this.pack_uint64(num); 398 | } else{ 399 | throw new Error('Invalid integer'); 400 | } 401 | } 402 | 403 | Packer.prototype.pack_double = function(num){ 404 | var sign = 0; 405 | if (num < 0){ 406 | sign = 1; 407 | num = -num; 408 | } 409 | var exp = Math.floor(Math.log(num) / Math.LN2); 410 | var frac0 = num / Math.pow(2, exp) - 1; 411 | var frac1 = Math.floor(frac0 * Math.pow(2, 52)); 412 | var b32 = Math.pow(2, 32); 413 | var h32 = (sign << 31) | ((exp+1023) << 20) | 414 | (frac1 / b32) & 0x0fffff; 415 | var l32 = frac1 % b32; 416 | this.bufferBuilder.append(0xcb); 417 | this.pack_int32(h32); 418 | this.pack_int32(l32); 419 | } 420 | 421 | Packer.prototype.pack_object = function(obj){ 422 | var keys = Object.keys(obj); 423 | var length = keys.length; 424 | if (length <= 0x0f){ 425 | this.pack_uint8(0x80 + length); 426 | } else if (length <= 0xffff){ 427 | this.bufferBuilder.append(0xde); 428 | this.pack_uint16(length); 429 | } else if (length <= 0xffffffff){ 430 | this.bufferBuilder.append(0xdf); 431 | this.pack_uint32(length); 432 | } else{ 433 | throw new Error('Invalid length'); 434 | } 435 | for(var prop in obj){ 436 | if (obj.hasOwnProperty(prop)){ 437 | this.pack(prop); 438 | this.pack(obj[prop]); 439 | } 440 | } 441 | } 442 | 443 | Packer.prototype.pack_uint8 = function(num){ 444 | this.bufferBuilder.append(num); 445 | } 446 | 447 | Packer.prototype.pack_uint16 = function(num){ 448 | this.bufferBuilder.append(num >> 8); 449 | this.bufferBuilder.append(num & 0xff); 450 | } 451 | 452 | Packer.prototype.pack_uint32 = function(num){ 453 | var n = num & 0xffffffff; 454 | this.bufferBuilder.append((n & 0xff000000) >>> 24); 455 | this.bufferBuilder.append((n & 0x00ff0000) >>> 16); 456 | this.bufferBuilder.append((n & 0x0000ff00) >>> 8); 457 | this.bufferBuilder.append((n & 0x000000ff)); 458 | } 459 | 460 | Packer.prototype.pack_uint64 = function(num){ 461 | var high = num / Math.pow(2, 32); 462 | var low = num % Math.pow(2, 32); 463 | this.bufferBuilder.append((high & 0xff000000) >>> 24); 464 | this.bufferBuilder.append((high & 0x00ff0000) >>> 16); 465 | this.bufferBuilder.append((high & 0x0000ff00) >>> 8); 466 | this.bufferBuilder.append((high & 0x000000ff)); 467 | this.bufferBuilder.append((low & 0xff000000) >>> 24); 468 | this.bufferBuilder.append((low & 0x00ff0000) >>> 16); 469 | this.bufferBuilder.append((low & 0x0000ff00) >>> 8); 470 | this.bufferBuilder.append((low & 0x000000ff)); 471 | } 472 | 473 | Packer.prototype.pack_int8 = function(num){ 474 | this.bufferBuilder.append(num & 0xff); 475 | } 476 | 477 | Packer.prototype.pack_int16 = function(num){ 478 | this.bufferBuilder.append((num & 0xff00) >> 8); 479 | this.bufferBuilder.append(num & 0xff); 480 | } 481 | 482 | Packer.prototype.pack_int32 = function(num){ 483 | this.bufferBuilder.append((num >>> 24) & 0xff); 484 | this.bufferBuilder.append((num & 0x00ff0000) >>> 16); 485 | this.bufferBuilder.append((num & 0x0000ff00) >>> 8); 486 | this.bufferBuilder.append((num & 0x000000ff)); 487 | } 488 | 489 | Packer.prototype.pack_int64 = function(num){ 490 | var high = Math.floor(num / Math.pow(2, 32)); 491 | var low = num % Math.pow(2, 32); 492 | this.bufferBuilder.append((high & 0xff000000) >>> 24); 493 | this.bufferBuilder.append((high & 0x00ff0000) >>> 16); 494 | this.bufferBuilder.append((high & 0x0000ff00) >>> 8); 495 | this.bufferBuilder.append((high & 0x000000ff)); 496 | this.bufferBuilder.append((low & 0xff000000) >>> 24); 497 | this.bufferBuilder.append((low & 0x00ff0000) >>> 16); 498 | this.bufferBuilder.append((low & 0x0000ff00) >>> 8); 499 | this.bufferBuilder.append((low & 0x000000ff)); 500 | } 501 | 502 | function _utf8Replace(m){ 503 | var code = m.charCodeAt(0); 504 | 505 | if(code <= 0x7ff) return '00'; 506 | if(code <= 0xffff) return '000'; 507 | if(code <= 0x1fffff) return '0000'; 508 | if(code <= 0x3ffffff) return '00000'; 509 | return '000000'; 510 | } 511 | 512 | function utf8Length(str){ 513 | if (str.length > 600) { 514 | // Blob method faster for large strings 515 | return (new Blob([str])).size; 516 | } else { 517 | return str.replace(/[^\u0000-\u007F]/g, _utf8Replace).length; 518 | } 519 | } 520 | -------------------------------------------------------------------------------- /dist/binarypack.js: -------------------------------------------------------------------------------- 1 | /*! binarypack.js build:0.0.9, production. Copyright(c) 2012 Eric Zhang MIT Licensed */(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 31; 231 | var exp = ((uint32 >> 23) & 0xff) - 127; 232 | var fraction = ( uint32 & 0x7fffff ) | 0x800000; 233 | return (sign == 0 ? 1 : -1) * 234 | fraction * Math.pow(2, exp - 23); 235 | } 236 | 237 | Unpacker.prototype.unpack_double = function(){ 238 | var h32 = this.unpack_uint32(); 239 | var l32 = this.unpack_uint32(); 240 | var sign = h32 >> 31; 241 | var exp = ((h32 >> 20) & 0x7ff) - 1023; 242 | var hfrac = ( h32 & 0xfffff ) | 0x100000; 243 | var frac = hfrac * Math.pow(2, exp - 20) + 244 | l32 * Math.pow(2, exp - 52); 245 | return (sign == 0 ? 1 : -1) * frac; 246 | } 247 | 248 | Unpacker.prototype.read = function(length){ 249 | var j = this.index; 250 | if (j + length <= this.length) { 251 | return this.dataView.subarray(j, j + length); 252 | } else { 253 | throw new Error('BinaryPackFailure: read index out of range'); 254 | } 255 | } 256 | 257 | function Packer(){ 258 | this.bufferBuilder = new BufferBuilder(); 259 | } 260 | 261 | Packer.prototype.getBuffer = function(){ 262 | return this.bufferBuilder.getBuffer(); 263 | } 264 | 265 | Packer.prototype.pack = function(value){ 266 | var type = typeof(value); 267 | if (type == 'string'){ 268 | this.pack_string(value); 269 | } else if (type == 'number'){ 270 | if (Math.floor(value) === value){ 271 | this.pack_integer(value); 272 | } else{ 273 | this.pack_double(value); 274 | } 275 | } else if (type == 'boolean'){ 276 | if (value === true){ 277 | this.bufferBuilder.append(0xc3); 278 | } else if (value === false){ 279 | this.bufferBuilder.append(0xc2); 280 | } 281 | } else if (type == 'undefined'){ 282 | this.bufferBuilder.append(0xc0); 283 | } else if (type == 'object'){ 284 | if (value === null){ 285 | this.bufferBuilder.append(0xc0); 286 | } else { 287 | var constructor = value.constructor; 288 | if (constructor == Array){ 289 | this.pack_array(value); 290 | } else if (constructor == Blob || constructor == File) { 291 | this.pack_bin(value); 292 | } else if (constructor == ArrayBuffer) { 293 | if(binaryFeatures.useArrayBufferView) { 294 | this.pack_bin(new Uint8Array(value)); 295 | } else { 296 | this.pack_bin(value); 297 | } 298 | } else if ('BYTES_PER_ELEMENT' in value){ 299 | if(binaryFeatures.useArrayBufferView) { 300 | this.pack_bin(new Uint8Array(value.buffer)); 301 | } else { 302 | this.pack_bin(value.buffer); 303 | } 304 | } else if (constructor == Object){ 305 | this.pack_object(value); 306 | } else if (constructor == Date){ 307 | this.pack_string(value.toString()); 308 | } else if (typeof value.toBinaryPack == 'function'){ 309 | this.bufferBuilder.append(value.toBinaryPack()); 310 | } else { 311 | throw new Error('Type "' + constructor.toString() + '" not yet supported'); 312 | } 313 | } 314 | } else { 315 | throw new Error('Type "' + type + '" not yet supported'); 316 | } 317 | this.bufferBuilder.flush(); 318 | } 319 | 320 | 321 | Packer.prototype.pack_bin = function(blob){ 322 | var length = blob.length || blob.byteLength || blob.size; 323 | if (length <= 0x0f){ 324 | this.pack_uint8(0xa0 + length); 325 | } else if (length <= 0xffff){ 326 | this.bufferBuilder.append(0xda) ; 327 | this.pack_uint16(length); 328 | } else if (length <= 0xffffffff){ 329 | this.bufferBuilder.append(0xdb); 330 | this.pack_uint32(length); 331 | } else{ 332 | throw new Error('Invalid length'); 333 | } 334 | this.bufferBuilder.append(blob); 335 | } 336 | 337 | Packer.prototype.pack_string = function(str){ 338 | var length = utf8Length(str); 339 | 340 | if (length <= 0x0f){ 341 | this.pack_uint8(0xb0 + length); 342 | } else if (length <= 0xffff){ 343 | this.bufferBuilder.append(0xd8) ; 344 | this.pack_uint16(length); 345 | } else if (length <= 0xffffffff){ 346 | this.bufferBuilder.append(0xd9); 347 | this.pack_uint32(length); 348 | } else{ 349 | throw new Error('Invalid length'); 350 | } 351 | this.bufferBuilder.append(str); 352 | } 353 | 354 | Packer.prototype.pack_array = function(ary){ 355 | var length = ary.length; 356 | if (length <= 0x0f){ 357 | this.pack_uint8(0x90 + length); 358 | } else if (length <= 0xffff){ 359 | this.bufferBuilder.append(0xdc) 360 | this.pack_uint16(length); 361 | } else if (length <= 0xffffffff){ 362 | this.bufferBuilder.append(0xdd); 363 | this.pack_uint32(length); 364 | } else{ 365 | throw new Error('Invalid length'); 366 | } 367 | for(var i = 0; i < length ; i++){ 368 | this.pack(ary[i]); 369 | } 370 | } 371 | 372 | Packer.prototype.pack_integer = function(num){ 373 | if ( -0x20 <= num && num <= 0x7f){ 374 | this.bufferBuilder.append(num & 0xff); 375 | } else if (0x00 <= num && num <= 0xff){ 376 | this.bufferBuilder.append(0xcc); 377 | this.pack_uint8(num); 378 | } else if (-0x80 <= num && num <= 0x7f){ 379 | this.bufferBuilder.append(0xd0); 380 | this.pack_int8(num); 381 | } else if ( 0x0000 <= num && num <= 0xffff){ 382 | this.bufferBuilder.append(0xcd); 383 | this.pack_uint16(num); 384 | } else if (-0x8000 <= num && num <= 0x7fff){ 385 | this.bufferBuilder.append(0xd1); 386 | this.pack_int16(num); 387 | } else if ( 0x00000000 <= num && num <= 0xffffffff){ 388 | this.bufferBuilder.append(0xce); 389 | this.pack_uint32(num); 390 | } else if (-0x80000000 <= num && num <= 0x7fffffff){ 391 | this.bufferBuilder.append(0xd2); 392 | this.pack_int32(num); 393 | } else if (-0x8000000000000000 <= num && num <= 0x7FFFFFFFFFFFFFFF){ 394 | this.bufferBuilder.append(0xd3); 395 | this.pack_int64(num); 396 | } else if (0x0000000000000000 <= num && num <= 0xFFFFFFFFFFFFFFFF){ 397 | this.bufferBuilder.append(0xcf); 398 | this.pack_uint64(num); 399 | } else{ 400 | throw new Error('Invalid integer'); 401 | } 402 | } 403 | 404 | Packer.prototype.pack_double = function(num){ 405 | var sign = 0; 406 | if (num < 0){ 407 | sign = 1; 408 | num = -num; 409 | } 410 | var exp = Math.floor(Math.log(num) / Math.LN2); 411 | var frac0 = num / Math.pow(2, exp) - 1; 412 | var frac1 = Math.floor(frac0 * Math.pow(2, 52)); 413 | var b32 = Math.pow(2, 32); 414 | var h32 = (sign << 31) | ((exp+1023) << 20) | 415 | (frac1 / b32) & 0x0fffff; 416 | var l32 = frac1 % b32; 417 | this.bufferBuilder.append(0xcb); 418 | this.pack_int32(h32); 419 | this.pack_int32(l32); 420 | } 421 | 422 | Packer.prototype.pack_object = function(obj){ 423 | var keys = Object.keys(obj); 424 | var length = keys.length; 425 | if (length <= 0x0f){ 426 | this.pack_uint8(0x80 + length); 427 | } else if (length <= 0xffff){ 428 | this.bufferBuilder.append(0xde); 429 | this.pack_uint16(length); 430 | } else if (length <= 0xffffffff){ 431 | this.bufferBuilder.append(0xdf); 432 | this.pack_uint32(length); 433 | } else{ 434 | throw new Error('Invalid length'); 435 | } 436 | for(var prop in obj){ 437 | if (obj.hasOwnProperty(prop)){ 438 | this.pack(prop); 439 | this.pack(obj[prop]); 440 | } 441 | } 442 | } 443 | 444 | Packer.prototype.pack_uint8 = function(num){ 445 | this.bufferBuilder.append(num); 446 | } 447 | 448 | Packer.prototype.pack_uint16 = function(num){ 449 | this.bufferBuilder.append(num >> 8); 450 | this.bufferBuilder.append(num & 0xff); 451 | } 452 | 453 | Packer.prototype.pack_uint32 = function(num){ 454 | var n = num & 0xffffffff; 455 | this.bufferBuilder.append((n & 0xff000000) >>> 24); 456 | this.bufferBuilder.append((n & 0x00ff0000) >>> 16); 457 | this.bufferBuilder.append((n & 0x0000ff00) >>> 8); 458 | this.bufferBuilder.append((n & 0x000000ff)); 459 | } 460 | 461 | Packer.prototype.pack_uint64 = function(num){ 462 | var high = num / Math.pow(2, 32); 463 | var low = num % Math.pow(2, 32); 464 | this.bufferBuilder.append((high & 0xff000000) >>> 24); 465 | this.bufferBuilder.append((high & 0x00ff0000) >>> 16); 466 | this.bufferBuilder.append((high & 0x0000ff00) >>> 8); 467 | this.bufferBuilder.append((high & 0x000000ff)); 468 | this.bufferBuilder.append((low & 0xff000000) >>> 24); 469 | this.bufferBuilder.append((low & 0x00ff0000) >>> 16); 470 | this.bufferBuilder.append((low & 0x0000ff00) >>> 8); 471 | this.bufferBuilder.append((low & 0x000000ff)); 472 | } 473 | 474 | Packer.prototype.pack_int8 = function(num){ 475 | this.bufferBuilder.append(num & 0xff); 476 | } 477 | 478 | Packer.prototype.pack_int16 = function(num){ 479 | this.bufferBuilder.append((num & 0xff00) >> 8); 480 | this.bufferBuilder.append(num & 0xff); 481 | } 482 | 483 | Packer.prototype.pack_int32 = function(num){ 484 | this.bufferBuilder.append((num >>> 24) & 0xff); 485 | this.bufferBuilder.append((num & 0x00ff0000) >>> 16); 486 | this.bufferBuilder.append((num & 0x0000ff00) >>> 8); 487 | this.bufferBuilder.append((num & 0x000000ff)); 488 | } 489 | 490 | Packer.prototype.pack_int64 = function(num){ 491 | var high = Math.floor(num / Math.pow(2, 32)); 492 | var low = num % Math.pow(2, 32); 493 | this.bufferBuilder.append((high & 0xff000000) >>> 24); 494 | this.bufferBuilder.append((high & 0x00ff0000) >>> 16); 495 | this.bufferBuilder.append((high & 0x0000ff00) >>> 8); 496 | this.bufferBuilder.append((high & 0x000000ff)); 497 | this.bufferBuilder.append((low & 0xff000000) >>> 24); 498 | this.bufferBuilder.append((low & 0x00ff0000) >>> 16); 499 | this.bufferBuilder.append((low & 0x0000ff00) >>> 8); 500 | this.bufferBuilder.append((low & 0x000000ff)); 501 | } 502 | 503 | function _utf8Replace(m){ 504 | var code = m.charCodeAt(0); 505 | 506 | if(code <= 0x7ff) return '00'; 507 | if(code <= 0xffff) return '000'; 508 | if(code <= 0x1fffff) return '0000'; 509 | if(code <= 0x3ffffff) return '00000'; 510 | return '000000'; 511 | } 512 | 513 | function utf8Length(str){ 514 | if (str.length > 600) { 515 | // Blob method faster for large strings 516 | return (new Blob([str])).size; 517 | } else { 518 | return str.replace(/[^\u0000-\u007F]/g, _utf8Replace).length; 519 | } 520 | } 521 | 522 | },{"./bufferbuilder":2}],2:[function(require,module,exports){ 523 | var binaryFeatures = {}; 524 | binaryFeatures.useBlobBuilder = (function(){ 525 | try { 526 | new Blob([]); 527 | return false; 528 | } catch (e) { 529 | return true; 530 | } 531 | })(); 532 | 533 | binaryFeatures.useArrayBufferView = !binaryFeatures.useBlobBuilder && (function(){ 534 | try { 535 | return (new Blob([new Uint8Array([])])).size === 0; 536 | } catch (e) { 537 | return true; 538 | } 539 | })(); 540 | 541 | module.exports.binaryFeatures = binaryFeatures; 542 | var BlobBuilder = module.exports.BlobBuilder; 543 | if (typeof window != 'undefined') { 544 | BlobBuilder = module.exports.BlobBuilder = window.WebKitBlobBuilder || 545 | window.MozBlobBuilder || window.MSBlobBuilder || window.BlobBuilder; 546 | } 547 | 548 | function BufferBuilder(){ 549 | this._pieces = []; 550 | this._parts = []; 551 | } 552 | 553 | BufferBuilder.prototype.append = function(data) { 554 | if(typeof data === 'number') { 555 | this._pieces.push(data); 556 | } else { 557 | this.flush(); 558 | this._parts.push(data); 559 | } 560 | }; 561 | 562 | BufferBuilder.prototype.flush = function() { 563 | if (this._pieces.length > 0) { 564 | var buf = new Uint8Array(this._pieces); 565 | if(!binaryFeatures.useArrayBufferView) { 566 | buf = buf.buffer; 567 | } 568 | this._parts.push(buf); 569 | this._pieces = []; 570 | } 571 | }; 572 | 573 | BufferBuilder.prototype.getBuffer = function() { 574 | this.flush(); 575 | if(binaryFeatures.useBlobBuilder) { 576 | var builder = new BlobBuilder(); 577 | for(var i = 0, ii = this._parts.length; i < ii; i++) { 578 | builder.append(this._parts[i]); 579 | } 580 | return builder.getBlob(); 581 | } else { 582 | return new Blob(this._parts); 583 | } 584 | }; 585 | 586 | module.exports.BufferBuilder = BufferBuilder; 587 | 588 | },{}],3:[function(require,module,exports){ 589 | var BufferBuilderExports = require('./bufferbuilder'); 590 | 591 | window.BufferBuilder = BufferBuilderExports.BufferBuilder; 592 | window.binaryFeatures = BufferBuilderExports.binaryFeatures; 593 | window.BlobBuilder = BufferBuilderExports.BlobBuilder; 594 | window.BinaryPack = require('./binarypack'); 595 | 596 | },{"./binarypack":1,"./bufferbuilder":2}]},{},[3]); 597 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | js-binarypack Test 4 | 5 | 6 | 7 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |

Test binarypack performance on JSON (non-Blob/ArrayBuffer) data types

70 | 73 |

74 | 75 | 76 |

77 | Results are shown in the Javascript console 78 | --------------------------------------------------------------------------------