diff options
Diffstat (limited to 'core/codecArrayBuffer.js')
-rw-r--r-- | core/codecArrayBuffer.js | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/core/codecArrayBuffer.js b/core/codecArrayBuffer.js new file mode 100644 index 0000000..c2be4ca --- /dev/null +++ b/core/codecArrayBuffer.js @@ -0,0 +1,113 @@ +/** @fileOverview Bit array codec implementations. + * + * @author Marco Munizaga + */ + +//patch arraybuffers if they don't exist +if (typeof(ArrayBuffer) === 'undefined') { + (function(globals){ + "use strict"; + globals.ArrayBuffer = function(){}; + globals.DataView = function(){}; + }(this)); +} + +/** @namespace ArrayBuffer */ +sjcl.codec.arrayBuffer = { + /** Convert from a bitArray to an ArrayBuffer. + * Will default to 8byte padding if padding is undefined*/ + fromBits: function (arr, padding, padding_count) { + var out, i, ol, tmp, smallest; + padding = padding==undefined ? true : padding + padding_count = padding_count || 8 + + if (arr.length === 0) { + return new ArrayBuffer(0); + } + + ol = sjcl.bitArray.bitLength(arr)/8; + + //check to make sure the bitLength is divisible by 8, if it isn't + //we can't do anything since arraybuffers work with bytes, not bits + if ( sjcl.bitArray.bitLength(arr)%8 !== 0 ) { + throw new sjcl.exception.invalid("Invalid bit size, must be divisble by 8 to fit in an arraybuffer correctly") + } + + if (padding && ol%padding_count !== 0){ + ol += padding_count - (ol%padding_count); + } + + + //padded temp for easy copying + tmp = new DataView(new ArrayBuffer(arr.length*4)); + for (i=0; i<arr.length; i++) { + tmp.setUint32(i*4, (arr[i]<<32)); //get rid of the higher bits + } + + //now copy the final message if we are not going to 0 pad + out = new DataView(new ArrayBuffer(ol)); + + //save a step when the tmp and out bytelength are === + if (out.byteLength === tmp.byteLength){ + return tmp.buffer; + } + + smallest = tmp.byteLength < out.byteLength ? tmp.byteLength : out.byteLength; + for(i=0; i<smallest; i++){ + out.setUint8(i,tmp.getUint8(i)); + } + + + return out.buffer + }, + + toBits: function (buffer) { + var i, out=[], len, inView, tmp; + + if (buffer.byteLength === 0) { + return []; + } + + inView = new DataView(buffer); + len = inView.byteLength - inView.byteLength%4; + + for (var i = 0; i < len; i+=4) { + out.push(inView.getUint32(i)); + } + + if (inView.byteLength%4 != 0) { + tmp = new DataView(new ArrayBuffer(4)); + for (var i = 0, l = inView.byteLength%4; i < l; i++) { + //we want the data to the right, because partial slices off the starting bits + tmp.setUint8(i+4-l, inView.getUint8(len+i)); // big-endian, + } + out.push( + sjcl.bitArray.partial( (inView.byteLength%4)*8, tmp.getUint32(0) ) + ); + } + return out; + }, + + + + /** Prints a hex output of the buffer contents, akin to hexdump **/ + hexDumpBuffer: function(buffer){ + var stringBufferView = new DataView(buffer) + var string = '' + var pad = function (n, width) { + n = n + ''; + return n.length >= width ? n : new Array(width - n.length + 1).join('0') + n; + } + + for (var i = 0; i < stringBufferView.byteLength; i+=2) { + if (i%16 == 0) string += ('\n'+(i).toString(16)+'\t') + string += ( pad(stringBufferView.getUint16(i).toString(16),4) + ' ') + } + + if ( typeof console === undefined ){ + console = console || {log:function(){}} //fix for IE + } + console.log(string.toUpperCase()) + } +}; + |