diff --git a/build b/build new file mode 100755 index 0000000..2e967da --- /dev/null +++ b/build @@ -0,0 +1,4 @@ +#!/bin/bash + +browserify index.js > dist/pluie.bin.js +uglifyjs dist/pluie.bin.js -c -m -o dist/pluie.bin.min.js diff --git a/dist/pluie.bin.js b/dist/pluie.bin.js new file mode 100644 index 0000000..4da708f --- /dev/null +++ b/dist/pluie.bin.js @@ -0,0 +1,222 @@ +(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 0) { + // Big Endian + for (var i = value = 0, lim = bytes.length; i < lim; i++) { + value = value * 256 + bytes[i]; + } + } + return value; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bytesFromInt : function(value, size) + { + var bytes = new Uint8Array(size); + while (value) { + bytes.set([value & 255], --size); + value >>= 8; + } + return bytes; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + pack : function(size, type, value) + { + var packed = null + if (type == 'n' || type == 'N') { + // js int max on 32 signed bits + if (value >= 0 && value <= 2147483647) { + packed = this.bytesFromInt(value, type == 'n' ? 2 : 4); + } + } + else if (type == 'a') { + packed = new Uint8Array(size); + packed.set(this.enc.encode(value), 0); + } + return packed; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + unpack : function(size, type, bytes) + { + var unpacked = null + if (type == 'n' || type == 'N') { + var selByte = bytes.slice(0, size*(type == 'n' ? 2 : 4)); + unpacked = this.intFromBytes(selByte); + } + else if (type == 'a') { + unpacked = this.dec.decode(bytes.slice(0, size)).removeEndNullBytes(); + } + return unpacked; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + mergeBuffers : function(bufferArray) + { + var maxLength = 0; + for(var i=0, lim=bufferArray.length; i < lim; i++) { + if (bufferArray[i] != null) { + maxLength += bufferArray[i].byteLength; + } + } + var tmp = new Uint8Array(maxLength); + for(var i=0, pos = 0, lim=bufferArray.length; i < lim; i++) { + if (bufferArray[i] != null) { + tmp.set(new Uint8Array(bufferArray[i]), pos); + pos += bufferArray[i].byteLength; + } + } + return tmp; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + getBuffer : function(array, size) + { + var buffer = new Uint8Array(!size ? array.length : size); + buffer.set(new Uint8Array(array), 0); + return buffer; + }, +} +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +require('./file')(bin); +module.exports = bin; + +},{"./file":3}],3:[function(require,module,exports){ +module.exports = function (bin) { + require('./header')(bin); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.File = function(binary, header) { + this.header = header; + this.binary = binary; + this.extractProperties = function(binary) { + if (!binary) binary = this.binary; + if (binary != null && binary.length >= this.header.def.length) { + this.header.def.map.forEach (function(prop) { + var bytes = binary.slice(prop.offset, prop.offset+prop.length); + var unpacked = bin.unpack(prop.size, prop.type, bytes); + prop.value = unpacked; + }); + } + }; + this.buildProperties = function(properties) { + var data = []; + this.header.buildProperties(properties); + this.header.def.map.forEach (function(prop) { + var packed = bin.pack(prop.size, prop.type, prop.value); + data.push(packed); + }); + data = bin.mergeBuffers(data); + }; + this.extractProperties(binary); + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.smpFile = function(binary) { + return new bin.File(binary, new bin.Header([ + ['signature', 'a', 9, '∢SMP0.2'], + ['size' , 'N', 1, ''], + ['id' , 'N', 1, ''], + ['from' , 'a', 32, ''], + ['to' , 'a', 32, ''], + ['channel' , 'a', 32, ''], + ['command' , 'n', 1, ''], + ['index' , 'n', 1, ''], + ['split' , 'n', 1, ''] + ])); + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.smpsFile = function(binary) { + return new bin.File(binary, new bin.Header([ + ['signature', 'a', 13, 'ﷸSMPS0.2∢'], + ['size' , 'N', 1, ''], + ['nonce' , 'a', 12, ''], + ['cypher' , 'a', 135, ''] + ])); + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.smpaFile = function(binary) { + return new bin.BaseFile(binary, new bin.Header([ + ['signature', 'a', 13, 'ﷸSMPA0.2∢'], + ['size' , 'N', 1, ''], + ['nonce' , 'a', 24, ''], + ['cypher' , 'a', 199, ''] + ])); + } +} + +},{"./header":4}],4:[function(require,module,exports){ +'use strict'; + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +module.exports = function (bin) { + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + var HeaderProperty = function(name, type, size, defaultValue) + { + this.name = name; + this.type = type; + this.size = size; + this.length = type == 'N' ? size*4 : (type == 'n' ? size*2 : size ); + this.value = defaultValue; + }; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + var HeaderDef = function(mapData) + { + var map = []; + mapData.forEach(function (def) { + map.push(new HeaderProperty(def[0], def[1], def[2], def[3])); + }); + this.map = map; + var keys = []; + var indexes = {}; + var offset = 0; + var index = 0; + this.map.forEach(function(prop) { + prop.offset = offset; + keys[keys.length] = prop.name; + offset += prop.length; + indexes[prop.name] = index++; + }); + this.indexes = indexes; + this.keys = keys; + this.length = offset; + this.getProperty = function(key) { + return this.map[this.indexes[key]]; + } + }; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.Header = function(def) { + this.def = new HeaderDef(def); + this.value = function(key) { + return this.def.getProperty(key).value; + }; + this.buildProperties = function(properties) { + this.def.map.forEach(function(prop) { + if (prop.name != 'signature') { + if (typeof properties[prop.name] != 'undefined') { + prop.value = properties[prop.name]; + } + } + }); + }; + } +} + +},{}]},{},[1]); diff --git a/dist/pluie.bin.min.js b/dist/pluie.bin.min.js new file mode 100644 index 0000000..0c3b7a0 --- /dev/null +++ b/dist/pluie.bin.min.js @@ -0,0 +1 @@ +!function e(n,t,r){function i(u,o){if(!t[u]){if(!n[u]){var s="function"==typeof require&&require;if(!o&&s)return s(u,!0);if(a)return a(u,!0);var f=new Error("Cannot find module '"+u+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[u]={exports:{}};n[u][0].call(c.exports,function(e){var t=n[u][1][e];return i(t?t:e)},c,c.exports,e,n,t,r)}return t[u].exports}for(var a="function"==typeof require&&require,u=0;u0)for(var t=n=0,r=e.length;t>=8;return t},pack:function(e,n,t){var r=null;return"n"==n||"N"==n?t>=0&&t<=2147483647&&(r=this.bytesFromInt(t,"n"==n?2:4)):"a"==n&&(r=new Uint8Array(e),r.set(this.enc.encode(t),0)),r},unpack:function(e,n,t){var r=null;if("n"==n||"N"==n){var i=t.slice(0,e*("n"==n?2:4));r=this.intFromBytes(i)}else"a"==n&&(r=this.dec.decode(t.slice(0,e)).removeEndNullBytes());return r},mergeBuffers:function(e){for(var n=0,t=0,r=e.length;t=this.header.def.length&&this.header.def.map.forEach(function(t){var r=e.slice(t.offset,t.offset+t.length),i=n.unpack(t.size,t.type,r);t.value=i})},this.buildProperties=function(e){var t=[];this.header.buildProperties(e),this.header.def.map.forEach(function(e){var r=n.pack(e.size,e.type,e.value);t.push(r)}),t=n.mergeBuffers(t)},this.extractProperties(e)},n.smpFile=function(e){return new n.File(e,new n.Header([["signature","a",9,"∢SMP0.2"],["size","N",1,""],["id","N",1,""],["from","a",32,""],["to","a",32,""],["channel","a",32,""],["command","n",1,""],["index","n",1,""],["split","n",1,""]]))},n.smpsFile=function(e){return new n.File(e,new n.Header([["signature","a",13,"ﷸSMPS0.2∢"],["size","N",1,""],["nonce","a",12,""],["cypher","a",135,""]]))},n.smpaFile=function(e){return new n.BaseFile(e,new n.Header([["signature","a",13,"ﷸSMPA0.2∢"],["size","N",1,""],["nonce","a",24,""],["cypher","a",199,""]]))}}},{"./header":4}],4:[function(e,n,t){"use strict";n.exports=function(e){var n=function(e,n,t,r){this.name=e,this.type=n,this.size=t,this.length="N"==n?4*t:"n"==n?2*t:t,this.value=r},t=function(e){var t=[];e.forEach(function(e){t.push(new n(e[0],e[1],e[2],e[3]))}),this.map=t;var r=[],i={},a=0,u=0;this.map.forEach(function(e){e.offset=a,r[r.length]=e.name,a+=e.length,i[e.name]=u++}),this.indexes=i,this.keys=r,this.length=a,this.getProperty=function(e){return this.map[this.indexes[e]]}};e.Header=function(e){this.def=new t(e),this.value=function(e){return this.def.getProperty(e).value},this.buildProperties=function(e){this.def.map.forEach(function(n){"signature"!=n.name&&"undefined"!=typeof e[n.name]&&(n.value=e[n.name])})}}}},{}]},{},[1]); \ No newline at end of file diff --git a/index.js b/index.js index 8d639ca..0f36466 100644 --- a/index.js +++ b/index.js @@ -1,68 +1,2 @@ -'use strict'; - -String.prototype.removeEndNullBytes = function() { - return this.replace(/\0+$/g, ''); -} -String.prototype.removeStartNullBytes = function() { - return this.replace(/^\0+/g, ''); -} - -var pluie = -{ - bin : - { - enc : new TextEncoder("utf-8"), - - dec : new TextDecoder("utf-8", {fatal: true}), - - intFromBytes : function(bytes) - { - // Big Endian - for (var i = value = 0, lim = bytes.length; i < lim; i++) { - value = value * 256 + bytes[i]; - } - return value; - }, - - bytesFromInt : function(value, size) - { - var bytes = new Uint8Array(size); - while (value) { - bytes.set([value & 255], --size); - value >>= 8;; - } - return bytes; - }, - - pack : function(size, type, value) - { - var packed = null - if (type == 'n' || type == 'N') { - // js int max on 32 signed bits - if (value >= 0 && value <= 2147483647) { - packed = this.bytesFromInt(value, type == 'n' ? 2 : 4); - } - } - else if (type == 'a') { - packed = new Uint8Array(size); - packed.set(this.enc.encode(value), 0); - } - return packed; - }, - - unpack : function(size, type, bytes) - { - var unpacked = null - if (type == 'n' || type == 'N') { - var selByte = bytes.slice(0, size*(type == 'n' ? 2 : 4)); - unpacked = this.intFromBytes(selByte); - } - else if (type == 'a') { - unpacked = this.dec.decode(bytes.slice(0, size)).removeEndNullBytes(); - } - return unpacked; - } - } -} - -module.exports = pluie.bin; +bin = require('./lib/bin'); +module.exports = bin; diff --git a/lib/bin.js b/lib/bin.js new file mode 100644 index 0000000..87f53a9 --- /dev/null +++ b/lib/bin.js @@ -0,0 +1,96 @@ +'use strict'; + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +String.prototype.removeEndNullBytes = function() { + return this.replace(/\0+$/g, ''); +} +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +String.prototype.removeStartNullBytes = function() { + return this.replace(/^\0+/g, ''); +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +var bin = +{ + enc : new TextEncoder("utf-8"), + dec : new TextDecoder("utf-8", {fatal: true}), + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + intFromBytes : function(bytes) + { + var value = null; + if (bytes!=null && bytes.length > 0) { + // Big Endian + for (var i = value = 0, lim = bytes.length; i < lim; i++) { + value = value * 256 + bytes[i]; + } + } + return value; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bytesFromInt : function(value, size) + { + var bytes = new Uint8Array(size); + while (value) { + bytes.set([value & 255], --size); + value >>= 8; + } + return bytes; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + pack : function(size, type, value) + { + var packed = null + if (type == 'n' || type == 'N') { + // js int max on 32 signed bits + if (value >= 0 && value <= 2147483647) { + packed = this.bytesFromInt(value, type == 'n' ? 2 : 4); + } + } + else if (type == 'a') { + packed = new Uint8Array(size); + packed.set(this.enc.encode(value), 0); + } + return packed; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + unpack : function(size, type, bytes) + { + var unpacked = null + if (type == 'n' || type == 'N') { + var selByte = bytes.slice(0, size*(type == 'n' ? 2 : 4)); + unpacked = this.intFromBytes(selByte); + } + else if (type == 'a') { + unpacked = this.dec.decode(bytes.slice(0, size)).removeEndNullBytes(); + } + return unpacked; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + mergeBuffers : function(bufferArray) + { + var maxLength = 0; + for(var i=0, lim=bufferArray.length; i < lim; i++) { + if (bufferArray[i] != null) { + maxLength += bufferArray[i].byteLength; + } + } + var tmp = new Uint8Array(maxLength); + for(var i=0, pos = 0, lim=bufferArray.length; i < lim; i++) { + if (bufferArray[i] != null) { + tmp.set(new Uint8Array(bufferArray[i]), pos); + pos += bufferArray[i].byteLength; + } + } + return tmp; + }, + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + getBuffer : function(array, size) + { + var buffer = new Uint8Array(!size ? array.length : size); + buffer.set(new Uint8Array(array), 0); + return buffer; + }, +} +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +require('./file')(bin); +module.exports = bin; diff --git a/lib/file.js b/lib/file.js new file mode 100644 index 0000000..6607c4f --- /dev/null +++ b/lib/file.js @@ -0,0 +1,60 @@ +module.exports = function (bin) { + require('./header')(bin); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.File = function(binary, header) { + this.header = header; + this.binary = binary; + this.extractProperties = function(binary) { + if (!binary) binary = this.binary; + if (binary != null && binary.length >= this.header.def.length) { + this.header.def.map.forEach (function(prop) { + var bytes = binary.slice(prop.offset, prop.offset+prop.length); + var unpacked = bin.unpack(prop.size, prop.type, bytes); + prop.value = unpacked; + }); + } + }; + this.buildProperties = function(properties) { + var data = []; + this.header.buildProperties(properties); + this.header.def.map.forEach (function(prop) { + var packed = bin.pack(prop.size, prop.type, prop.value); + data.push(packed); + }); + data = bin.mergeBuffers(data); + }; + this.extractProperties(binary); + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.smpFile = function(binary) { + return new bin.File(binary, new bin.Header([ + ['signature', 'a', 9, '∢SMP0.2'], + ['size' , 'N', 1, ''], + ['id' , 'N', 1, ''], + ['from' , 'a', 32, ''], + ['to' , 'a', 32, ''], + ['channel' , 'a', 32, ''], + ['command' , 'n', 1, ''], + ['index' , 'n', 1, ''], + ['split' , 'n', 1, ''] + ])); + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.smpsFile = function(binary) { + return new bin.File(binary, new bin.Header([ + ['signature', 'a', 13, 'ﷸSMPS0.2∢'], + ['size' , 'N', 1, ''], + ['nonce' , 'a', 12, ''], + ['cypher' , 'a', 135, ''] + ])); + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.smpaFile = function(binary) { + return new bin.BaseFile(binary, new bin.Header([ + ['signature', 'a', 13, 'ﷸSMPA0.2∢'], + ['size' , 'N', 1, ''], + ['nonce' , 'a', 24, ''], + ['cypher' , 'a', 199, ''] + ])); + } +} diff --git a/lib/header.js b/lib/header.js new file mode 100644 index 0000000..355b4ae --- /dev/null +++ b/lib/header.js @@ -0,0 +1,55 @@ +'use strict'; + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +module.exports = function (bin) { + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + var HeaderProperty = function(name, type, size, defaultValue) + { + this.name = name; + this.type = type; + this.size = size; + this.length = type == 'N' ? size*4 : (type == 'n' ? size*2 : size ); + this.value = defaultValue; + }; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + var HeaderDef = function(mapData) + { + var map = []; + mapData.forEach(function (def) { + map.push(new HeaderProperty(def[0], def[1], def[2], def[3])); + }); + this.map = map; + var keys = []; + var indexes = {}; + var offset = 0; + var index = 0; + this.map.forEach(function(prop) { + prop.offset = offset; + keys[keys.length] = prop.name; + offset += prop.length; + indexes[prop.name] = index++; + }); + this.indexes = indexes; + this.keys = keys; + this.length = offset; + this.getProperty = function(key) { + return this.map[this.indexes[key]]; + } + }; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bin.Header = function(def) { + this.def = new HeaderDef(def); + this.value = function(key) { + return this.def.getProperty(key).value; + }; + this.buildProperties = function(properties) { + this.def.map.forEach(function(prop) { + if (prop.name != 'signature') { + if (typeof properties[prop.name] != 'undefined') { + prop.value = properties[prop.name]; + } + } + }); + }; + } +} diff --git a/package.json b/package.json index 35e5041..0cb9c72 100644 --- a/package.json +++ b/package.json @@ -12,5 +12,7 @@ "repository": { "type": "git", "url": "https://git.pluie.org/pluie/js-bin.git" + }, + "dependencies": { } }