| var bfr = new Buffer(1) | ||
| var nobfr = [] | ||
| suite('instanceof vs Buffer.isBuffer', function() { | ||
| bench('isBuffer', function() { | ||
| var x = Buffer.isBuffer(bfr) | ||
| var y = Buffer.isBuffer(nobfr) | ||
| }) | ||
| bench('instanceof', function() { | ||
| var x = (bfr instanceof Buffer) | ||
| var y = (nobfr instanceof Buffer) | ||
| }) | ||
| }) |
| # Just a plain list of people who contributed to this project. | ||
| # People who are already listed in AUTHORS are not listed again. | ||
| Conrad Pankoff <deoxxa@fknsrs.biz> | ||
| Patrick Williams <patrick@bittorrent.com> |
+152
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <title>Benchmark</title> | ||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/0.3.0/benchmark.min.js"></script> | ||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script> | ||
| <script src="./bencode.js"></script> | ||
| <script src="./bncode.js"></script> | ||
| <script src="./test.js"></script> | ||
| <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> | ||
| </head> | ||
| <body> | ||
| <div class="col-lg-5" style="margin:auto;float:none;margin-top:3em;"> | ||
| <div class="panel panel-default"> | ||
| <div class="panel-heading">decode:</div> | ||
| <ul class="list-group" id="results-decode"></ul> | ||
| </div> | ||
| <div class="panel panel-default"> | ||
| <div class="panel-heading">encode:</div> | ||
| <ul class="list-group" id="results-encode"></ul> | ||
| </div> | ||
| </div> | ||
| <script> | ||
| var deepDiffMapper = function() { | ||
| return { | ||
| VALUE_CREATED: 'created', | ||
| VALUE_UPDATED: 'updated', | ||
| VALUE_DELETED: 'deleted', | ||
| VALUE_UNCHANGED: 'unchanged', | ||
| map: function(obj1, obj2) { | ||
| if (this.isFunction(obj1) || this.isFunction(obj2)) { | ||
| throw 'Invalid argument. Function given, object expected.'; | ||
| } | ||
| if (this.isValue(obj1) || this.isValue(obj2)) { | ||
| return {type: this.compareValues(obj1, obj2), data: obj1 || obj2}; | ||
| } | ||
| var diff = {}; | ||
| for (var key in obj1) { | ||
| if (this.isFunction(obj1[key])) { | ||
| continue; | ||
| } | ||
| var value2 = undefined; | ||
| if ('undefined' != typeof(obj2[key])) { | ||
| value2 = obj2[key]; | ||
| } | ||
| diff[key] = this.map(obj1[key], value2); | ||
| } | ||
| for (var key in obj2) { | ||
| if (this.isFunction(obj2[key]) || ('undefined' != typeof(diff[key]))) { | ||
| continue; | ||
| } | ||
| diff[key] = this.map(undefined, obj2[key]); | ||
| } | ||
| return diff; | ||
| }, | ||
| compareValues: function(value1, value2) { | ||
| if (value1 === value2) { | ||
| return this.VALUE_UNCHANGED; | ||
| } | ||
| if ('undefined' == typeof(value1)) { | ||
| return this.VALUE_CREATED; | ||
| } | ||
| if ('undefined' == typeof(value2)) { | ||
| return this.VALUE_DELETED; | ||
| } | ||
| return this.VALUE_UPDATED; | ||
| }, | ||
| isFunction: function(obj) { | ||
| return toString.apply(obj) === '[object Function]'; | ||
| }, | ||
| isArray: function(obj) { | ||
| return toString.apply(obj) === '[object Array]'; | ||
| }, | ||
| isObject: function(obj) { | ||
| return toString.apply(obj) === '[object Object]'; | ||
| }, | ||
| isValue: function(obj) { | ||
| return !this.isObject(obj) && !this.isArray(obj); | ||
| } | ||
| } | ||
| }(); | ||
| var input = window.data.toString('ascii') | ||
| var object_ben = bencode.decode( window.data ) | ||
| var result_ben = bencode.encode(object_ben).toString('ascii') | ||
| console.log(_.isEqual(input, result_ben)) | ||
| var object_bn = bncode.decode( window.data ) | ||
| var result_bn = bencode.encode(object_ben).toString('ascii') | ||
| console.log(_.isEqual(input, result_bn)) | ||
| console.log(_.isEqual(result_ben, result_bn)) | ||
| console.log(object_ben.announce._isBuffer, object_bn.announce._isBuffer) | ||
| // add tests | ||
| function testDecode(done) { | ||
| var suite = new Benchmark.Suite; | ||
| suite.add('bencode.decode', function() { | ||
| bencode.decode( window.data ) | ||
| }) | ||
| .add('bncode.decode', function() { | ||
| bncode.decode( window.data ) | ||
| }) | ||
| .on( 'cycle', function ( event, bench ) { | ||
| var results = document.getElementById('results-decode') | ||
| var html = results.innerHTML | ||
| html += '<li class="list-group-item" id="result-'+bench.name+'">' + bench.toString()+ '</li>' | ||
| results.innerHTML = html | ||
| }) | ||
| .on( 'complete', function ( event, bench ) { | ||
| var name = this.filter( 'fastest' ).pluck( 'name' ) | ||
| document.getElementById('result-' + name).classList.add('list-group-item-success') | ||
| done() | ||
| }) | ||
| .run({ async: true }) | ||
| } | ||
| function testEncode(done) { | ||
| var suite = new Benchmark.Suite; | ||
| suite.add('bencode.encode', function() { | ||
| bencode.encode(object_ben) | ||
| }) | ||
| .add('bncode.encode', function() { | ||
| bncode.encode(object_ben) | ||
| }) | ||
| .on( 'cycle', function ( event, bench ) { | ||
| var results = document.getElementById('results-encode') | ||
| var html = results.innerHTML | ||
| html += '<li class="list-group-item" id="result-'+bench.name+'">' + bench.toString()+ '</li>' | ||
| results.innerHTML = html | ||
| }) | ||
| .on( 'complete', function ( event, bench ) { | ||
| var name = this.filter( 'fastest' ).pluck( 'name' ) | ||
| document.getElementById('result-' + name).classList.add('list-group-item-success') | ||
| done() | ||
| }) | ||
| .run({ async: true }) | ||
| } | ||
| testDecode(testEncode.bind(null, function() { console.log('done') })) | ||
| </script> | ||
| </body> | ||
| </html> |
+1553
| !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.bencode=e()}}(function(){var define,module,exports;return (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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ | ||
| module.exports = { | ||
| encode: _dereq_( './lib/encode' ), | ||
| decode: _dereq_( './lib/decode' ) | ||
| } | ||
| },{"./lib/decode":2,"./lib/encode":3}],2:[function(_dereq_,module,exports){ | ||
| (function (Buffer){ | ||
| /** | ||
| * Decodes bencoded data. | ||
| * | ||
| * @param {Buffer} data | ||
| * @param {String} encoding | ||
| * @return {Object|Array|Buffer|String|Number} | ||
| */ | ||
| function decode( data, encoding ) { | ||
| decode.position = 0 | ||
| decode.encoding = encoding || null | ||
| decode.data = !( Buffer.isBuffer(data) ) | ||
| ? new Buffer( data ) | ||
| : data | ||
| return decode.next() | ||
| } | ||
| decode.position = 0 | ||
| decode.data = null | ||
| decode.encoding = null | ||
| decode.next = function() { | ||
| switch( decode.data[decode.position] ) { | ||
| case 0x64: return decode.dictionary(); break | ||
| case 0x6C: return decode.list(); break | ||
| case 0x69: return decode.integer(); break | ||
| default: return decode.bytes(); break | ||
| } | ||
| } | ||
| decode.find = function( chr ) { | ||
| var i = decode.position | ||
| var c = decode.data.length | ||
| var d = decode.data | ||
| while( i < c ) { | ||
| if( d[i] === chr ) | ||
| return i | ||
| i++ | ||
| } | ||
| throw new Error( | ||
| 'Invalid data: Missing delimiter "' + | ||
| String.fromCharCode( chr ) + '" [0x' + | ||
| chr.toString( 16 ) + ']' | ||
| ) | ||
| } | ||
| decode.dictionary = function() { | ||
| decode.position++ | ||
| var dict = {} | ||
| while( decode.data[decode.position] !== 0x65 ) { | ||
| dict[ decode.bytes() ] = decode.next() | ||
| } | ||
| decode.position++ | ||
| return dict | ||
| } | ||
| decode.list = function() { | ||
| decode.position++ | ||
| var lst = [] | ||
| while( decode.data[decode.position] !== 0x65 ) { | ||
| lst.push( decode.next() ) | ||
| } | ||
| decode.position++ | ||
| return lst | ||
| } | ||
| decode.integer = function() { | ||
| var end = decode.find( 0x65 ) | ||
| var number = decode.data.toString( 'ascii', decode.position + 1, end ) | ||
| decode.position += end + 1 - decode.position | ||
| return parseInt( number, 10 ) | ||
| } | ||
| decode.bytes = function() { | ||
| var sep = decode.find( 0x3A ) | ||
| var length = parseInt( decode.data.toString( 'ascii', decode.position, sep ), 10 ) | ||
| var end = ++sep + length | ||
| decode.position = end | ||
| return decode.encoding | ||
| ? decode.data.toString( decode.encoding, sep, end ) | ||
| : decode.data.slice( sep, end ) | ||
| } | ||
| // Exports | ||
| module.exports = decode | ||
| }).call(this,_dereq_("buffer").Buffer) | ||
| },{"buffer":4}],3:[function(_dereq_,module,exports){ | ||
| (function (Buffer){ | ||
| /** | ||
| * Encodes data in bencode. | ||
| * | ||
| * @param {Buffer|Array|String|Object|Number} data | ||
| * @return {Buffer} | ||
| */ | ||
| function encode( data ) { | ||
| var buffers = [] | ||
| encode._encode( buffers, data ) | ||
| return Buffer.concat( buffers ) | ||
| } | ||
| encode._floatConversionDetected = false | ||
| encode._encode = function( buffers, data ) { | ||
| if( Buffer.isBuffer(data) ) { | ||
| buffers.push(new Buffer(data.length + ':')) | ||
| buffers.push(data) | ||
| return; | ||
| } | ||
| switch( typeof data ) { | ||
| case 'string': | ||
| encode.bytes( buffers, data ) | ||
| break | ||
| case 'number': | ||
| encode.number( buffers, data ) | ||
| break | ||
| case 'object': | ||
| data.constructor === Array | ||
| ? encode.list( buffers, data ) | ||
| : encode.dict( buffers, data ) | ||
| break | ||
| } | ||
| } | ||
| var buff_e = new Buffer('e') | ||
| , buff_d = new Buffer('d') | ||
| , buff_l = new Buffer('l') | ||
| encode.bytes = function( buffers, data ) { | ||
| buffers.push( new Buffer(Buffer.byteLength( data ) + ':' + data) ) | ||
| } | ||
| encode.number = function( buffers, data ) { | ||
| var maxLo = 0x80000000 | ||
| var hi = ( data / maxLo ) << 0 | ||
| var lo = ( data % maxLo ) << 0 | ||
| var val = hi * maxLo + lo | ||
| buffers.push( new Buffer( 'i' + val + 'e' )) | ||
| if( val !== data && !encode._floatConversionDetected ) { | ||
| encode._floatConversionDetected = true | ||
| console.warn( | ||
| 'WARNING: Possible data corruption detected with value "'+data+'":', | ||
| 'Bencoding only defines support for integers, value was converted to "'+val+'"' | ||
| ) | ||
| console.trace() | ||
| } | ||
| } | ||
| encode.dict = function( buffers, data ) { | ||
| buffers.push( buff_d ) | ||
| var j = 0 | ||
| var k | ||
| // fix for issue #13 - sorted dicts | ||
| var keys = Object.keys( data ).sort() | ||
| var kl = keys.length | ||
| for( ; j < kl ; j++) { | ||
| k=keys[j] | ||
| encode.bytes( buffers, k ) | ||
| encode._encode( buffers, data[k] ) | ||
| } | ||
| buffers.push( buff_e ) | ||
| } | ||
| encode.list = function( buffers, data ) { | ||
| var i = 0, j = 1 | ||
| var c = data.length | ||
| buffers.push( buff_l ) | ||
| for( ; i < c; i++ ) { | ||
| encode._encode( buffers, data[i] ) | ||
| } | ||
| buffers.push( buff_e ) | ||
| } | ||
| // Expose | ||
| module.exports = encode | ||
| }).call(this,_dereq_("buffer").Buffer) | ||
| },{"buffer":4}],4:[function(_dereq_,module,exports){ | ||
| /** | ||
| * The buffer module from node.js, for the browser. | ||
| * | ||
| * Author: Feross Aboukhadijeh <feross@feross.org> <http://feross.org> | ||
| * License: MIT | ||
| * | ||
| * `npm install buffer` | ||
| */ | ||
| var base64 = _dereq_('base64-js') | ||
| var ieee754 = _dereq_('ieee754') | ||
| exports.Buffer = Buffer | ||
| exports.SlowBuffer = Buffer | ||
| exports.INSPECT_MAX_BYTES = 50 | ||
| Buffer.poolSize = 8192 | ||
| /** | ||
| * If `Buffer._useTypedArrays`: | ||
| * === true Use Uint8Array implementation (fastest) | ||
| * === false Use Object implementation (compatible down to IE6) | ||
| */ | ||
| Buffer._useTypedArrays = (function () { | ||
| // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, | ||
| // Firefox 4+, Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. | ||
| if (typeof Uint8Array !== 'function' || typeof ArrayBuffer !== 'function') | ||
| return false | ||
| // Does the browser support adding properties to `Uint8Array` instances? If | ||
| // not, then that's the same as no `Uint8Array` support. We need to be able to | ||
| // add all the node Buffer API methods. | ||
| // Bug in Firefox 4-29, now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438 | ||
| try { | ||
| var arr = new Uint8Array(0) | ||
| arr.foo = function () { return 42 } | ||
| return 42 === arr.foo() && | ||
| typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray` | ||
| } catch (e) { | ||
| return false | ||
| } | ||
| })() | ||
| /** | ||
| * Class: Buffer | ||
| * ============= | ||
| * | ||
| * The Buffer constructor returns instances of `Uint8Array` that are augmented | ||
| * with function properties for all the node `Buffer` API functions. We use | ||
| * `Uint8Array` so that square bracket notation works as expected -- it returns | ||
| * a single octet. | ||
| * | ||
| * By augmenting the instances, we can avoid modifying the `Uint8Array` | ||
| * prototype. | ||
| */ | ||
| function Buffer (subject, encoding, noZero) { | ||
| if (!(this instanceof Buffer)) | ||
| return new Buffer(subject, encoding, noZero) | ||
| var type = typeof subject | ||
| // Workaround: node's base64 implementation allows for non-padded strings | ||
| // while base64-js does not. | ||
| if (encoding === 'base64' && type === 'string') { | ||
| subject = stringtrim(subject) | ||
| while (subject.length % 4 !== 0) { | ||
| subject = subject + '=' | ||
| } | ||
| } | ||
| // Find the length | ||
| var length | ||
| if (type === 'number') | ||
| length = coerce(subject) | ||
| else if (type === 'string') | ||
| length = Buffer.byteLength(subject, encoding) | ||
| else if (type === 'object') | ||
| length = coerce(subject.length) // Assume object is an array | ||
| else | ||
| throw new Error('First argument needs to be a number, array or string.') | ||
| var buf | ||
| if (Buffer._useTypedArrays) { | ||
| // Preferred: Return an augmented `Uint8Array` instance for best performance | ||
| buf = augment(new Uint8Array(length)) | ||
| } else { | ||
| // Fallback: Return THIS instance of Buffer (created by `new`) | ||
| buf = this | ||
| buf.length = length | ||
| buf._isBuffer = true | ||
| } | ||
| var i | ||
| if (Buffer._useTypedArrays && typeof Uint8Array === 'function' && | ||
| subject instanceof Uint8Array) { | ||
| // Speed optimization -- use set if we're copying from a Uint8Array | ||
| buf._set(subject) | ||
| } else if (isArrayish(subject)) { | ||
| // Treat array-ish objects as a byte array | ||
| for (i = 0; i < length; i++) { | ||
| if (Buffer.isBuffer(subject)) | ||
| buf[i] = subject.readUInt8(i) | ||
| else | ||
| buf[i] = subject[i] | ||
| } | ||
| } else if (type === 'string') { | ||
| buf.write(subject, 0, encoding) | ||
| } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) { | ||
| for (i = 0; i < length; i++) { | ||
| buf[i] = 0 | ||
| } | ||
| } | ||
| return buf | ||
| } | ||
| // STATIC METHODS | ||
| // ============== | ||
| Buffer.isEncoding = function (encoding) { | ||
| switch (String(encoding).toLowerCase()) { | ||
| case 'hex': | ||
| case 'utf8': | ||
| case 'utf-8': | ||
| case 'ascii': | ||
| case 'binary': | ||
| case 'base64': | ||
| case 'raw': | ||
| case 'ucs2': | ||
| case 'ucs-2': | ||
| case 'utf16le': | ||
| case 'utf-16le': | ||
| return true | ||
| default: | ||
| return false | ||
| } | ||
| } | ||
| Buffer.isBuffer = function (b) { | ||
| return !!(b !== null && b !== undefined && b._isBuffer) | ||
| } | ||
| Buffer.byteLength = function (str, encoding) { | ||
| var ret | ||
| str = str + '' | ||
| switch (encoding || 'utf8') { | ||
| case 'hex': | ||
| ret = str.length / 2 | ||
| break | ||
| case 'utf8': | ||
| case 'utf-8': | ||
| ret = utf8ToBytes(str).length | ||
| break | ||
| case 'ascii': | ||
| case 'binary': | ||
| case 'raw': | ||
| ret = str.length | ||
| break | ||
| case 'base64': | ||
| ret = base64ToBytes(str).length | ||
| break | ||
| case 'ucs2': | ||
| case 'ucs-2': | ||
| case 'utf16le': | ||
| case 'utf-16le': | ||
| ret = str.length * 2 | ||
| break | ||
| default: | ||
| throw new Error('Unknown encoding') | ||
| } | ||
| return ret | ||
| } | ||
| Buffer.concat = function (list, totalLength) { | ||
| assert(isArray(list), 'Usage: Buffer.concat(list, [totalLength])\n' + | ||
| 'list should be an Array.') | ||
| if (list.length === 0) { | ||
| return new Buffer(0) | ||
| } else if (list.length === 1) { | ||
| return list[0] | ||
| } | ||
| var i | ||
| if (typeof totalLength !== 'number') { | ||
| totalLength = 0 | ||
| for (i = 0; i < list.length; i++) { | ||
| totalLength += list[i].length | ||
| } | ||
| } | ||
| var buf = new Buffer(totalLength) | ||
| var pos = 0 | ||
| for (i = 0; i < list.length; i++) { | ||
| var item = list[i] | ||
| item.copy(buf, pos) | ||
| pos += item.length | ||
| } | ||
| return buf | ||
| } | ||
| // BUFFER INSTANCE METHODS | ||
| // ======================= | ||
| function _hexWrite (buf, string, offset, length) { | ||
| offset = Number(offset) || 0 | ||
| var remaining = buf.length - offset | ||
| if (!length) { | ||
| length = remaining | ||
| } else { | ||
| length = Number(length) | ||
| if (length > remaining) { | ||
| length = remaining | ||
| } | ||
| } | ||
| // must be an even number of digits | ||
| var strLen = string.length | ||
| assert(strLen % 2 === 0, 'Invalid hex string') | ||
| if (length > strLen / 2) { | ||
| length = strLen / 2 | ||
| } | ||
| for (var i = 0; i < length; i++) { | ||
| var byte = parseInt(string.substr(i * 2, 2), 16) | ||
| assert(!isNaN(byte), 'Invalid hex string') | ||
| buf[offset + i] = byte | ||
| } | ||
| Buffer._charsWritten = i * 2 | ||
| return i | ||
| } | ||
| function _utf8Write (buf, string, offset, length) { | ||
| var charsWritten = Buffer._charsWritten = | ||
| blitBuffer(utf8ToBytes(string), buf, offset, length) | ||
| return charsWritten | ||
| } | ||
| function _asciiWrite (buf, string, offset, length) { | ||
| var charsWritten = Buffer._charsWritten = | ||
| blitBuffer(asciiToBytes(string), buf, offset, length) | ||
| return charsWritten | ||
| } | ||
| function _binaryWrite (buf, string, offset, length) { | ||
| return _asciiWrite(buf, string, offset, length) | ||
| } | ||
| function _base64Write (buf, string, offset, length) { | ||
| var charsWritten = Buffer._charsWritten = | ||
| blitBuffer(base64ToBytes(string), buf, offset, length) | ||
| return charsWritten | ||
| } | ||
| function _utf16leWrite (buf, string, offset, length) { | ||
| var charsWritten = Buffer._charsWritten = | ||
| blitBuffer(utf16leToBytes(string), buf, offset, length) | ||
| return charsWritten | ||
| } | ||
| Buffer.prototype.write = function (string, offset, length, encoding) { | ||
| // Support both (string, offset, length, encoding) | ||
| // and the legacy (string, encoding, offset, length) | ||
| if (isFinite(offset)) { | ||
| if (!isFinite(length)) { | ||
| encoding = length | ||
| length = undefined | ||
| } | ||
| } else { // legacy | ||
| var swap = encoding | ||
| encoding = offset | ||
| offset = length | ||
| length = swap | ||
| } | ||
| offset = Number(offset) || 0 | ||
| var remaining = this.length - offset | ||
| if (!length) { | ||
| length = remaining | ||
| } else { | ||
| length = Number(length) | ||
| if (length > remaining) { | ||
| length = remaining | ||
| } | ||
| } | ||
| encoding = String(encoding || 'utf8').toLowerCase() | ||
| var ret | ||
| switch (encoding) { | ||
| case 'hex': | ||
| ret = _hexWrite(this, string, offset, length) | ||
| break | ||
| case 'utf8': | ||
| case 'utf-8': | ||
| ret = _utf8Write(this, string, offset, length) | ||
| break | ||
| case 'ascii': | ||
| ret = _asciiWrite(this, string, offset, length) | ||
| break | ||
| case 'binary': | ||
| ret = _binaryWrite(this, string, offset, length) | ||
| break | ||
| case 'base64': | ||
| ret = _base64Write(this, string, offset, length) | ||
| break | ||
| case 'ucs2': | ||
| case 'ucs-2': | ||
| case 'utf16le': | ||
| case 'utf-16le': | ||
| ret = _utf16leWrite(this, string, offset, length) | ||
| break | ||
| default: | ||
| throw new Error('Unknown encoding') | ||
| } | ||
| return ret | ||
| } | ||
| Buffer.prototype.toString = function (encoding, start, end) { | ||
| var self = this | ||
| encoding = String(encoding || 'utf8').toLowerCase() | ||
| start = Number(start) || 0 | ||
| end = (end !== undefined) | ||
| ? Number(end) | ||
| : end = self.length | ||
| // Fastpath empty strings | ||
| if (end === start) | ||
| return '' | ||
| var ret | ||
| switch (encoding) { | ||
| case 'hex': | ||
| ret = _hexSlice(self, start, end) | ||
| break | ||
| case 'utf8': | ||
| case 'utf-8': | ||
| ret = _utf8Slice(self, start, end) | ||
| break | ||
| case 'ascii': | ||
| ret = _asciiSlice(self, start, end) | ||
| break | ||
| case 'binary': | ||
| ret = _binarySlice(self, start, end) | ||
| break | ||
| case 'base64': | ||
| ret = _base64Slice(self, start, end) | ||
| break | ||
| case 'ucs2': | ||
| case 'ucs-2': | ||
| case 'utf16le': | ||
| case 'utf-16le': | ||
| ret = _utf16leSlice(self, start, end) | ||
| break | ||
| default: | ||
| throw new Error('Unknown encoding') | ||
| } | ||
| return ret | ||
| } | ||
| Buffer.prototype.toJSON = function () { | ||
| return { | ||
| type: 'Buffer', | ||
| data: Array.prototype.slice.call(this._arr || this, 0) | ||
| } | ||
| } | ||
| // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) | ||
| Buffer.prototype.copy = function (target, target_start, start, end) { | ||
| var source = this | ||
| if (!start) start = 0 | ||
| if (!end && end !== 0) end = this.length | ||
| if (!target_start) target_start = 0 | ||
| // Copy 0 bytes; we're done | ||
| if (end === start) return | ||
| if (target.length === 0 || source.length === 0) return | ||
| // Fatal error conditions | ||
| assert(end >= start, 'sourceEnd < sourceStart') | ||
| assert(target_start >= 0 && target_start < target.length, | ||
| 'targetStart out of bounds') | ||
| assert(start >= 0 && start < source.length, 'sourceStart out of bounds') | ||
| assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds') | ||
| // Are we oob? | ||
| if (end > this.length) | ||
| end = this.length | ||
| if (target.length - target_start < end - start) | ||
| end = target.length - target_start + start | ||
| // copy! | ||
| for (var i = 0; i < end - start; i++) | ||
| target[i + target_start] = this[i + start] | ||
| } | ||
| function _base64Slice (buf, start, end) { | ||
| if (start === 0 && end === buf.length) { | ||
| return base64.fromByteArray(buf) | ||
| } else { | ||
| return base64.fromByteArray(buf.slice(start, end)) | ||
| } | ||
| } | ||
| function _utf8Slice (buf, start, end) { | ||
| var res = '' | ||
| var tmp = '' | ||
| end = Math.min(buf.length, end) | ||
| for (var i = start; i < end; i++) { | ||
| if (buf[i] <= 0x7F) { | ||
| res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) | ||
| tmp = '' | ||
| } else { | ||
| tmp += '%' + buf[i].toString(16) | ||
| } | ||
| } | ||
| return res + decodeUtf8Char(tmp) | ||
| } | ||
| function _asciiSlice (buf, start, end) { | ||
| var ret = '' | ||
| end = Math.min(buf.length, end) | ||
| for (var i = start; i < end; i++) | ||
| ret += String.fromCharCode(buf[i]) | ||
| return ret | ||
| } | ||
| function _binarySlice (buf, start, end) { | ||
| return _asciiSlice(buf, start, end) | ||
| } | ||
| function _hexSlice (buf, start, end) { | ||
| var len = buf.length | ||
| if (!start || start < 0) start = 0 | ||
| if (!end || end < 0 || end > len) end = len | ||
| var out = '' | ||
| for (var i = start; i < end; i++) { | ||
| out += toHex(buf[i]) | ||
| } | ||
| return out | ||
| } | ||
| function _utf16leSlice (buf, start, end) { | ||
| var bytes = buf.slice(start, end) | ||
| var res = '' | ||
| for (var i = 0; i < bytes.length; i += 2) { | ||
| res += String.fromCharCode(bytes[i] + bytes[i+1] * 256) | ||
| } | ||
| return res | ||
| } | ||
| Buffer.prototype.slice = function (start, end) { | ||
| var len = this.length | ||
| start = clamp(start, len, 0) | ||
| end = clamp(end, len, len) | ||
| if (Buffer._useTypedArrays) { | ||
| return augment(this.subarray(start, end)) | ||
| } else { | ||
| var sliceLen = end - start | ||
| var newBuf = new Buffer(sliceLen, undefined, true) | ||
| for (var i = 0; i < sliceLen; i++) { | ||
| newBuf[i] = this[i + start] | ||
| } | ||
| return newBuf | ||
| } | ||
| } | ||
| // `get` will be removed in Node 0.13+ | ||
| Buffer.prototype.get = function (offset) { | ||
| console.log('.get() is deprecated. Access using array indexes instead.') | ||
| return this.readUInt8(offset) | ||
| } | ||
| // `set` will be removed in Node 0.13+ | ||
| Buffer.prototype.set = function (v, offset) { | ||
| console.log('.set() is deprecated. Access using array indexes instead.') | ||
| return this.writeUInt8(v, offset) | ||
| } | ||
| Buffer.prototype.readUInt8 = function (offset, noAssert) { | ||
| if (!noAssert) { | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset < this.length, 'Trying to read beyond buffer length') | ||
| } | ||
| if (offset >= this.length) | ||
| return | ||
| return this[offset] | ||
| } | ||
| function _readUInt16 (buf, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| var val | ||
| if (littleEndian) { | ||
| val = buf[offset] | ||
| if (offset + 1 < len) | ||
| val |= buf[offset + 1] << 8 | ||
| } else { | ||
| val = buf[offset] << 8 | ||
| if (offset + 1 < len) | ||
| val |= buf[offset + 1] | ||
| } | ||
| return val | ||
| } | ||
| Buffer.prototype.readUInt16LE = function (offset, noAssert) { | ||
| return _readUInt16(this, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.readUInt16BE = function (offset, noAssert) { | ||
| return _readUInt16(this, offset, false, noAssert) | ||
| } | ||
| function _readUInt32 (buf, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| var val | ||
| if (littleEndian) { | ||
| if (offset + 2 < len) | ||
| val = buf[offset + 2] << 16 | ||
| if (offset + 1 < len) | ||
| val |= buf[offset + 1] << 8 | ||
| val |= buf[offset] | ||
| if (offset + 3 < len) | ||
| val = val + (buf[offset + 3] << 24 >>> 0) | ||
| } else { | ||
| if (offset + 1 < len) | ||
| val = buf[offset + 1] << 16 | ||
| if (offset + 2 < len) | ||
| val |= buf[offset + 2] << 8 | ||
| if (offset + 3 < len) | ||
| val |= buf[offset + 3] | ||
| val = val + (buf[offset] << 24 >>> 0) | ||
| } | ||
| return val | ||
| } | ||
| Buffer.prototype.readUInt32LE = function (offset, noAssert) { | ||
| return _readUInt32(this, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.readUInt32BE = function (offset, noAssert) { | ||
| return _readUInt32(this, offset, false, noAssert) | ||
| } | ||
| Buffer.prototype.readInt8 = function (offset, noAssert) { | ||
| if (!noAssert) { | ||
| assert(offset !== undefined && offset !== null, | ||
| 'missing offset') | ||
| assert(offset < this.length, 'Trying to read beyond buffer length') | ||
| } | ||
| if (offset >= this.length) | ||
| return | ||
| var neg = this[offset] & 0x80 | ||
| if (neg) | ||
| return (0xff - this[offset] + 1) * -1 | ||
| else | ||
| return this[offset] | ||
| } | ||
| function _readInt16 (buf, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| var val = _readUInt16(buf, offset, littleEndian, true) | ||
| var neg = val & 0x8000 | ||
| if (neg) | ||
| return (0xffff - val + 1) * -1 | ||
| else | ||
| return val | ||
| } | ||
| Buffer.prototype.readInt16LE = function (offset, noAssert) { | ||
| return _readInt16(this, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.readInt16BE = function (offset, noAssert) { | ||
| return _readInt16(this, offset, false, noAssert) | ||
| } | ||
| function _readInt32 (buf, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| var val = _readUInt32(buf, offset, littleEndian, true) | ||
| var neg = val & 0x80000000 | ||
| if (neg) | ||
| return (0xffffffff - val + 1) * -1 | ||
| else | ||
| return val | ||
| } | ||
| Buffer.prototype.readInt32LE = function (offset, noAssert) { | ||
| return _readInt32(this, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.readInt32BE = function (offset, noAssert) { | ||
| return _readInt32(this, offset, false, noAssert) | ||
| } | ||
| function _readFloat (buf, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') | ||
| } | ||
| return ieee754.read(buf, offset, littleEndian, 23, 4) | ||
| } | ||
| Buffer.prototype.readFloatLE = function (offset, noAssert) { | ||
| return _readFloat(this, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.readFloatBE = function (offset, noAssert) { | ||
| return _readFloat(this, offset, false, noAssert) | ||
| } | ||
| function _readDouble (buf, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset + 7 < buf.length, 'Trying to read beyond buffer length') | ||
| } | ||
| return ieee754.read(buf, offset, littleEndian, 52, 8) | ||
| } | ||
| Buffer.prototype.readDoubleLE = function (offset, noAssert) { | ||
| return _readDouble(this, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.readDoubleBE = function (offset, noAssert) { | ||
| return _readDouble(this, offset, false, noAssert) | ||
| } | ||
| Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { | ||
| if (!noAssert) { | ||
| assert(value !== undefined && value !== null, 'missing value') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset < this.length, 'trying to write beyond buffer length') | ||
| verifuint(value, 0xff) | ||
| } | ||
| if (offset >= this.length) return | ||
| this[offset] = value | ||
| } | ||
| function _writeUInt16 (buf, value, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(value !== undefined && value !== null, 'missing value') | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 1 < buf.length, 'trying to write beyond buffer length') | ||
| verifuint(value, 0xffff) | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) { | ||
| buf[offset + i] = | ||
| (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> | ||
| (littleEndian ? i : 1 - i) * 8 | ||
| } | ||
| } | ||
| Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { | ||
| _writeUInt16(this, value, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { | ||
| _writeUInt16(this, value, offset, false, noAssert) | ||
| } | ||
| function _writeUInt32 (buf, value, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(value !== undefined && value !== null, 'missing value') | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 3 < buf.length, 'trying to write beyond buffer length') | ||
| verifuint(value, 0xffffffff) | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) { | ||
| buf[offset + i] = | ||
| (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff | ||
| } | ||
| } | ||
| Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { | ||
| _writeUInt32(this, value, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { | ||
| _writeUInt32(this, value, offset, false, noAssert) | ||
| } | ||
| Buffer.prototype.writeInt8 = function (value, offset, noAssert) { | ||
| if (!noAssert) { | ||
| assert(value !== undefined && value !== null, 'missing value') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset < this.length, 'Trying to write beyond buffer length') | ||
| verifsint(value, 0x7f, -0x80) | ||
| } | ||
| if (offset >= this.length) | ||
| return | ||
| if (value >= 0) | ||
| this.writeUInt8(value, offset, noAssert) | ||
| else | ||
| this.writeUInt8(0xff + value + 1, offset, noAssert) | ||
| } | ||
| function _writeInt16 (buf, value, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(value !== undefined && value !== null, 'missing value') | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 1 < buf.length, 'Trying to write beyond buffer length') | ||
| verifsint(value, 0x7fff, -0x8000) | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| if (value >= 0) | ||
| _writeUInt16(buf, value, offset, littleEndian, noAssert) | ||
| else | ||
| _writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert) | ||
| } | ||
| Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { | ||
| _writeInt16(this, value, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { | ||
| _writeInt16(this, value, offset, false, noAssert) | ||
| } | ||
| function _writeInt32 (buf, value, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(value !== undefined && value !== null, 'missing value') | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') | ||
| verifsint(value, 0x7fffffff, -0x80000000) | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| if (value >= 0) | ||
| _writeUInt32(buf, value, offset, littleEndian, noAssert) | ||
| else | ||
| _writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert) | ||
| } | ||
| Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { | ||
| _writeInt32(this, value, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { | ||
| _writeInt32(this, value, offset, false, noAssert) | ||
| } | ||
| function _writeFloat (buf, value, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(value !== undefined && value !== null, 'missing value') | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') | ||
| verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38) | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| ieee754.write(buf, value, offset, littleEndian, 23, 4) | ||
| } | ||
| Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { | ||
| _writeFloat(this, value, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { | ||
| _writeFloat(this, value, offset, false, noAssert) | ||
| } | ||
| function _writeDouble (buf, value, offset, littleEndian, noAssert) { | ||
| if (!noAssert) { | ||
| assert(value !== undefined && value !== null, 'missing value') | ||
| assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | ||
| assert(offset !== undefined && offset !== null, 'missing offset') | ||
| assert(offset + 7 < buf.length, | ||
| 'Trying to write beyond buffer length') | ||
| verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308) | ||
| } | ||
| var len = buf.length | ||
| if (offset >= len) | ||
| return | ||
| ieee754.write(buf, value, offset, littleEndian, 52, 8) | ||
| } | ||
| Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { | ||
| _writeDouble(this, value, offset, true, noAssert) | ||
| } | ||
| Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { | ||
| _writeDouble(this, value, offset, false, noAssert) | ||
| } | ||
| // fill(value, start=0, end=buffer.length) | ||
| Buffer.prototype.fill = function (value, start, end) { | ||
| if (!value) value = 0 | ||
| if (!start) start = 0 | ||
| if (!end) end = this.length | ||
| if (typeof value === 'string') { | ||
| value = value.charCodeAt(0) | ||
| } | ||
| assert(typeof value === 'number' && !isNaN(value), 'value is not a number') | ||
| assert(end >= start, 'end < start') | ||
| // Fill 0 bytes; we're done | ||
| if (end === start) return | ||
| if (this.length === 0) return | ||
| assert(start >= 0 && start < this.length, 'start out of bounds') | ||
| assert(end >= 0 && end <= this.length, 'end out of bounds') | ||
| for (var i = start; i < end; i++) { | ||
| this[i] = value | ||
| } | ||
| } | ||
| Buffer.prototype.inspect = function () { | ||
| var out = [] | ||
| var len = this.length | ||
| for (var i = 0; i < len; i++) { | ||
| out[i] = toHex(this[i]) | ||
| if (i === exports.INSPECT_MAX_BYTES) { | ||
| out[i + 1] = '...' | ||
| break | ||
| } | ||
| } | ||
| return '<Buffer ' + out.join(' ') + '>' | ||
| } | ||
| /** | ||
| * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. | ||
| * Added in Node 0.12. Only available in browsers that support ArrayBuffer. | ||
| */ | ||
| Buffer.prototype.toArrayBuffer = function () { | ||
| if (typeof Uint8Array === 'function') { | ||
| if (Buffer._useTypedArrays) { | ||
| return (new Buffer(this)).buffer | ||
| } else { | ||
| var buf = new Uint8Array(this.length) | ||
| for (var i = 0, len = buf.length; i < len; i += 1) | ||
| buf[i] = this[i] | ||
| return buf.buffer | ||
| } | ||
| } else { | ||
| throw new Error('Buffer.toArrayBuffer not supported in this browser') | ||
| } | ||
| } | ||
| // HELPER FUNCTIONS | ||
| // ================ | ||
| function stringtrim (str) { | ||
| if (str.trim) return str.trim() | ||
| return str.replace(/^\s+|\s+$/g, '') | ||
| } | ||
| var BP = Buffer.prototype | ||
| /** | ||
| * Augment the Uint8Array *instance* (not the class!) with Buffer methods | ||
| */ | ||
| function augment (arr) { | ||
| arr._isBuffer = true | ||
| // save reference to original Uint8Array get/set methods before overwriting | ||
| arr._get = arr.get | ||
| arr._set = arr.set | ||
| // deprecated, will be removed in node 0.13+ | ||
| arr.get = BP.get | ||
| arr.set = BP.set | ||
| arr.write = BP.write | ||
| arr.toString = BP.toString | ||
| arr.toLocaleString = BP.toString | ||
| arr.toJSON = BP.toJSON | ||
| arr.copy = BP.copy | ||
| arr.slice = BP.slice | ||
| arr.readUInt8 = BP.readUInt8 | ||
| arr.readUInt16LE = BP.readUInt16LE | ||
| arr.readUInt16BE = BP.readUInt16BE | ||
| arr.readUInt32LE = BP.readUInt32LE | ||
| arr.readUInt32BE = BP.readUInt32BE | ||
| arr.readInt8 = BP.readInt8 | ||
| arr.readInt16LE = BP.readInt16LE | ||
| arr.readInt16BE = BP.readInt16BE | ||
| arr.readInt32LE = BP.readInt32LE | ||
| arr.readInt32BE = BP.readInt32BE | ||
| arr.readFloatLE = BP.readFloatLE | ||
| arr.readFloatBE = BP.readFloatBE | ||
| arr.readDoubleLE = BP.readDoubleLE | ||
| arr.readDoubleBE = BP.readDoubleBE | ||
| arr.writeUInt8 = BP.writeUInt8 | ||
| arr.writeUInt16LE = BP.writeUInt16LE | ||
| arr.writeUInt16BE = BP.writeUInt16BE | ||
| arr.writeUInt32LE = BP.writeUInt32LE | ||
| arr.writeUInt32BE = BP.writeUInt32BE | ||
| arr.writeInt8 = BP.writeInt8 | ||
| arr.writeInt16LE = BP.writeInt16LE | ||
| arr.writeInt16BE = BP.writeInt16BE | ||
| arr.writeInt32LE = BP.writeInt32LE | ||
| arr.writeInt32BE = BP.writeInt32BE | ||
| arr.writeFloatLE = BP.writeFloatLE | ||
| arr.writeFloatBE = BP.writeFloatBE | ||
| arr.writeDoubleLE = BP.writeDoubleLE | ||
| arr.writeDoubleBE = BP.writeDoubleBE | ||
| arr.fill = BP.fill | ||
| arr.inspect = BP.inspect | ||
| arr.toArrayBuffer = BP.toArrayBuffer | ||
| return arr | ||
| } | ||
| // slice(start, end) | ||
| function clamp (index, len, defaultValue) { | ||
| if (typeof index !== 'number') return defaultValue | ||
| index = ~~index; // Coerce to integer. | ||
| if (index >= len) return len | ||
| if (index >= 0) return index | ||
| index += len | ||
| if (index >= 0) return index | ||
| return 0 | ||
| } | ||
| function coerce (length) { | ||
| // Coerce length to a number (possibly NaN), round up | ||
| // in case it's fractional (e.g. 123.456) then do a | ||
| // double negate to coerce a NaN to 0. Easy, right? | ||
| length = ~~Math.ceil(+length) | ||
| return length < 0 ? 0 : length | ||
| } | ||
| function isArray (subject) { | ||
| return (Array.isArray || function (subject) { | ||
| return Object.prototype.toString.call(subject) === '[object Array]' | ||
| })(subject) | ||
| } | ||
| function isArrayish (subject) { | ||
| return isArray(subject) || Buffer.isBuffer(subject) || | ||
| subject && typeof subject === 'object' && | ||
| typeof subject.length === 'number' | ||
| } | ||
| function toHex (n) { | ||
| if (n < 16) return '0' + n.toString(16) | ||
| return n.toString(16) | ||
| } | ||
| function utf8ToBytes (str) { | ||
| var byteArray = [] | ||
| for (var i = 0; i < str.length; i++) { | ||
| var b = str.charCodeAt(i) | ||
| if (b <= 0x7F) | ||
| byteArray.push(str.charCodeAt(i)) | ||
| else { | ||
| var start = i | ||
| if (b >= 0xD800 && b <= 0xDFFF) i++ | ||
| var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') | ||
| for (var j = 0; j < h.length; j++) | ||
| byteArray.push(parseInt(h[j], 16)) | ||
| } | ||
| } | ||
| return byteArray | ||
| } | ||
| function asciiToBytes (str) { | ||
| var byteArray = [] | ||
| for (var i = 0; i < str.length; i++) { | ||
| // Node's code seems to be doing this and not & 0x7F.. | ||
| byteArray.push(str.charCodeAt(i) & 0xFF) | ||
| } | ||
| return byteArray | ||
| } | ||
| function utf16leToBytes (str) { | ||
| var c, hi, lo | ||
| var byteArray = [] | ||
| for (var i = 0; i < str.length; i++) { | ||
| c = str.charCodeAt(i) | ||
| hi = c >> 8 | ||
| lo = c % 256 | ||
| byteArray.push(lo) | ||
| byteArray.push(hi) | ||
| } | ||
| return byteArray | ||
| } | ||
| function base64ToBytes (str) { | ||
| return base64.toByteArray(str) | ||
| } | ||
| function blitBuffer (src, dst, offset, length) { | ||
| var pos | ||
| for (var i = 0; i < length; i++) { | ||
| if ((i + offset >= dst.length) || (i >= src.length)) | ||
| break | ||
| dst[i + offset] = src[i] | ||
| } | ||
| return i | ||
| } | ||
| function decodeUtf8Char (str) { | ||
| try { | ||
| return decodeURIComponent(str) | ||
| } catch (err) { | ||
| return String.fromCharCode(0xFFFD) // UTF 8 invalid char | ||
| } | ||
| } | ||
| /* | ||
| * We have to make sure that the value is a valid integer. This means that it | ||
| * is non-negative. It has no fractional component and that it does not | ||
| * exceed the maximum allowed value. | ||
| */ | ||
| function verifuint (value, max) { | ||
| assert(typeof value === 'number', 'cannot write a non-number as a number') | ||
| assert(value >= 0, 'specified a negative value for writing an unsigned value') | ||
| assert(value <= max, 'value is larger than maximum value for type') | ||
| assert(Math.floor(value) === value, 'value has a fractional component') | ||
| } | ||
| function verifsint (value, max, min) { | ||
| assert(typeof value === 'number', 'cannot write a non-number as a number') | ||
| assert(value <= max, 'value larger than maximum allowed value') | ||
| assert(value >= min, 'value smaller than minimum allowed value') | ||
| assert(Math.floor(value) === value, 'value has a fractional component') | ||
| } | ||
| function verifIEEE754 (value, max, min) { | ||
| assert(typeof value === 'number', 'cannot write a non-number as a number') | ||
| assert(value <= max, 'value larger than maximum allowed value') | ||
| assert(value >= min, 'value smaller than minimum allowed value') | ||
| } | ||
| function assert (test, message) { | ||
| if (!test) throw new Error(message || 'Failed assertion') | ||
| } | ||
| },{"base64-js":5,"ieee754":6}],5:[function(_dereq_,module,exports){ | ||
| var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | ||
| ;(function (exports) { | ||
| 'use strict'; | ||
| var Arr = (typeof Uint8Array !== 'undefined') | ||
| ? Uint8Array | ||
| : Array | ||
| var ZERO = '0'.charCodeAt(0) | ||
| var PLUS = '+'.charCodeAt(0) | ||
| var SLASH = '/'.charCodeAt(0) | ||
| var NUMBER = '0'.charCodeAt(0) | ||
| var LOWER = 'a'.charCodeAt(0) | ||
| var UPPER = 'A'.charCodeAt(0) | ||
| function decode (elt) { | ||
| var code = elt.charCodeAt(0) | ||
| if (code === PLUS) | ||
| return 62 // '+' | ||
| if (code === SLASH) | ||
| return 63 // '/' | ||
| if (code < NUMBER) | ||
| return -1 //no match | ||
| if (code < NUMBER + 10) | ||
| return code - NUMBER + 26 + 26 | ||
| if (code < UPPER + 26) | ||
| return code - UPPER | ||
| if (code < LOWER + 26) | ||
| return code - LOWER + 26 | ||
| } | ||
| function b64ToByteArray (b64) { | ||
| var i, j, l, tmp, placeHolders, arr | ||
| if (b64.length % 4 > 0) { | ||
| throw new Error('Invalid string. Length must be a multiple of 4') | ||
| } | ||
| // the number of equal signs (place holders) | ||
| // if there are two placeholders, than the two characters before it | ||
| // represent one byte | ||
| // if there is only one, then the three characters before it represent 2 bytes | ||
| // this is just a cheap hack to not do indexOf twice | ||
| var len = b64.length | ||
| placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 | ||
| // base64 is 4/3 + up to two characters of the original data | ||
| arr = new Arr(b64.length * 3 / 4 - placeHolders) | ||
| // if there are placeholders, only get up to the last complete 4 chars | ||
| l = placeHolders > 0 ? b64.length - 4 : b64.length | ||
| var L = 0 | ||
| function push (v) { | ||
| arr[L++] = v | ||
| } | ||
| for (i = 0, j = 0; i < l; i += 4, j += 3) { | ||
| tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) | ||
| push((tmp & 0xFF0000) >> 16) | ||
| push((tmp & 0xFF00) >> 8) | ||
| push(tmp & 0xFF) | ||
| } | ||
| if (placeHolders === 2) { | ||
| tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) | ||
| push(tmp & 0xFF) | ||
| } else if (placeHolders === 1) { | ||
| tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) | ||
| push((tmp >> 8) & 0xFF) | ||
| push(tmp & 0xFF) | ||
| } | ||
| return arr | ||
| } | ||
| function uint8ToBase64 (uint8) { | ||
| var i, | ||
| extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes | ||
| output = "", | ||
| temp, length | ||
| function encode (num) { | ||
| return lookup.charAt(num) | ||
| } | ||
| function tripletToBase64 (num) { | ||
| return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) | ||
| } | ||
| // go through the array every three bytes, we'll deal with trailing stuff later | ||
| for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { | ||
| temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) | ||
| output += tripletToBase64(temp) | ||
| } | ||
| // pad the end with zeros, but make sure to not forget the extra bytes | ||
| switch (extraBytes) { | ||
| case 1: | ||
| temp = uint8[uint8.length - 1] | ||
| output += encode(temp >> 2) | ||
| output += encode((temp << 4) & 0x3F) | ||
| output += '==' | ||
| break | ||
| case 2: | ||
| temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) | ||
| output += encode(temp >> 10) | ||
| output += encode((temp >> 4) & 0x3F) | ||
| output += encode((temp << 2) & 0x3F) | ||
| output += '=' | ||
| break | ||
| } | ||
| return output | ||
| } | ||
| module.exports.toByteArray = b64ToByteArray | ||
| module.exports.fromByteArray = uint8ToBase64 | ||
| }()) | ||
| },{}],6:[function(_dereq_,module,exports){ | ||
| exports.read = function(buffer, offset, isLE, mLen, nBytes) { | ||
| var e, m, | ||
| eLen = nBytes * 8 - mLen - 1, | ||
| eMax = (1 << eLen) - 1, | ||
| eBias = eMax >> 1, | ||
| nBits = -7, | ||
| i = isLE ? (nBytes - 1) : 0, | ||
| d = isLE ? -1 : 1, | ||
| s = buffer[offset + i]; | ||
| i += d; | ||
| e = s & ((1 << (-nBits)) - 1); | ||
| s >>= (-nBits); | ||
| nBits += eLen; | ||
| for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); | ||
| m = e & ((1 << (-nBits)) - 1); | ||
| e >>= (-nBits); | ||
| nBits += mLen; | ||
| for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); | ||
| if (e === 0) { | ||
| e = 1 - eBias; | ||
| } else if (e === eMax) { | ||
| return m ? NaN : ((s ? -1 : 1) * Infinity); | ||
| } else { | ||
| m = m + Math.pow(2, mLen); | ||
| e = e - eBias; | ||
| } | ||
| return (s ? -1 : 1) * m * Math.pow(2, e - mLen); | ||
| }; | ||
| exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { | ||
| var e, m, c, | ||
| eLen = nBytes * 8 - mLen - 1, | ||
| eMax = (1 << eLen) - 1, | ||
| eBias = eMax >> 1, | ||
| rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), | ||
| i = isLE ? 0 : (nBytes - 1), | ||
| d = isLE ? 1 : -1, | ||
| s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; | ||
| value = Math.abs(value); | ||
| if (isNaN(value) || value === Infinity) { | ||
| m = isNaN(value) ? 1 : 0; | ||
| e = eMax; | ||
| } else { | ||
| e = Math.floor(Math.log(value) / Math.LN2); | ||
| if (value * (c = Math.pow(2, -e)) < 1) { | ||
| e--; | ||
| c *= 2; | ||
| } | ||
| if (e + eBias >= 1) { | ||
| value += rt / c; | ||
| } else { | ||
| value += rt * Math.pow(2, 1 - eBias); | ||
| } | ||
| if (value * c >= 2) { | ||
| e++; | ||
| c /= 2; | ||
| } | ||
| if (e + eBias >= eMax) { | ||
| m = 0; | ||
| e = eMax; | ||
| } else if (e + eBias >= 1) { | ||
| m = (value * c - 1) * Math.pow(2, mLen); | ||
| e = e + eBias; | ||
| } else { | ||
| m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); | ||
| e = 0; | ||
| } | ||
| } | ||
| for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); | ||
| e = (e << mLen) | m; | ||
| eLen += mLen; | ||
| for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); | ||
| buffer[offset + i - d] |= s * 128; | ||
| }; | ||
| },{}]},{},[1]) | ||
| (1) | ||
| }); |
Sorry, the diff of this file is too big to display
| <script src='./tape.js'></script> |
Sorry, the diff of this file is too big to display
| <script src='tests.js'></script> |
| window.data = new bencode.Buffer('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', 'base64'); |
Sorry, the diff of this file is too big to display
| module.exports = decode | ||
| function* decode(data) { | ||
| this.position = 0 | ||
| this.encoding = encoding || null | ||
| this.data = !( data instanceof Buffer ) | ||
| ? new Buffer( data ) | ||
| : data | ||
| while(this.position + 1 < this.data.length) { | ||
| switch( this.data[this.position] ) { | ||
| case 0x64: yield this.dictionary(); break | ||
| case 0x6C: yield this.list(); break | ||
| case 0x69: yield this.integer(); break | ||
| default: yield this.bytes(); break | ||
| } | ||
| } | ||
| } |
+21
| .PHONY: all test benchmark | ||
| browserify: bencode.js lib/*.js | ||
| mkdir -p dist | ||
| browserify bencode.js -s bencode -o dist/bencode.js | ||
| # TODO: thats not how it should behave! | ||
| browser-test: bencode.js lib/*.js test/*.js | ||
| mkdir -p dist | ||
| browserify test/*.test.js -o dist/tests.js | ||
| echo "<script src='tests.js'></script>" > dist/test.html | ||
| # open dist/test.html in your browser now | ||
| test: | ||
| npm test | ||
| benchmark: | ||
| npm run-script bench | ||
| all: browserify test |
+25
| require('buffer') | ||
| //var test = require('tape').test | ||
| var bencode = require('./lib.js') | ||
| var data = require('./data.js') | ||
| /*var input = new Buffer('w6TDtsO8w58=', 'base64') | ||
| console.log(data.binKeyName) | ||
| var decoded = bencode.decode(data.binKeyData, 'utf8') | ||
| console.log(Buffer.byteLength(Object.keys(decoded.files))) | ||
| //t.ok(decoded.files.hasOwnProperty(data.binKeyName)) | ||
| console.log('binKeyName.length', Buffer.byteLength(data.binKeyName.toString('utf8'))) | ||
| var x = bencode.decode(bencode.encode(data.binKeyName.toString('utf8'))) | ||
| console.log(x.length) | ||
| console.log(x.toString('utf8')) | ||
| var bla = { | ||
| files: {} | ||
| } | ||
| bla.files[x] = { complete: 0, downloaded: 10, incomplete: 0 } | ||
| console.log(data.binKeyData.toString('utf8')) | ||
| console.log(bencode.encode(bla).toString('utf8')) | ||
| console.log(bla)*/ | ||
| var x = {files: { '7�U�ࣚ�K�ϧז����$w': { complete: 0, downloaded: 10, incomplete: 0 } }} | ||
| console.log(bencode.encode(x).toString('base64')) | ||
| var decoded = bencode.decode(data.binKeyData, 'utf8') | ||
| console.log(decoded.files) |
| var assert = require('assert') | ||
| var bencode = require('./lib.js') | ||
| var data = require('./data.js') | ||
| describe("bencode", function() { | ||
| describe("#decode(x)", function() { | ||
| it('should be able to decode an integer', function() { | ||
| assert.deepEqual(bencode.decode('i123e'), 123); | ||
| assert.deepEqual(bencode.decode('i-123e'), -123); | ||
| }); | ||
| it('should be able to decode a float (as int)', function() { | ||
| assert.deepEqual(bencode.decode('i12.3e'), 12); | ||
| assert.deepEqual(bencode.decode('i-12.3e'), -12); | ||
| }); | ||
| it('should be able to decode a string', function() { | ||
| assert.deepEqual(bencode.decode('5:asdfe'), new Buffer('asdfe')); | ||
| assert.deepEqual(bencode.decode('4:öö'), new Buffer('öö')); | ||
| }); | ||
| it('should be able to decode "binary keys"', function() { | ||
| assert.ok(bencode.decode(data.binKeyData).files.hasOwnProperty(data.binKeyName)); | ||
| }); | ||
| it('should be able to decode a dictionary', function() { | ||
| assert.deepEqual( | ||
| bencode.decode( 'd3:cow3:moo4:spam4:eggse' ), | ||
| { | ||
| cow: new Buffer('moo'), | ||
| spam: new Buffer('eggs') | ||
| } | ||
| ) | ||
| assert.deepEqual( | ||
| bencode.decode( 'd4:spaml1:a1:bee' ), | ||
| { spam: [ | ||
| new Buffer('a'), | ||
| new Buffer('b') | ||
| ] } | ||
| ) | ||
| assert.deepEqual( | ||
| bencode.decode( 'd9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee'), | ||
| { | ||
| 'publisher': new Buffer('bob'), | ||
| 'publisher-webpage': new Buffer('www.example.com'), | ||
| 'publisher.location': new Buffer('home') | ||
| } | ||
| ) | ||
| }); | ||
| it('should be able to decode a list', function() { | ||
| assert.deepEqual( | ||
| bencode.decode( 'l4:spam4:eggse'), | ||
| [ new Buffer('spam'), | ||
| new Buffer('eggs') ] | ||
| ) | ||
| }); | ||
| it('should return the correct type', function() { | ||
| assert.ok(bencode.decode('4:öö') instanceof Buffer); | ||
| }); | ||
| it('should be able to decode stuff in dicts (issue #12)', function() { | ||
| var someData = { | ||
| string: 'Hello World', | ||
| integer: 12345, | ||
| dict: { | ||
| key: 'This is a string within a dictionary' | ||
| }, | ||
| list: [ 1, 2, 3, 4, 'string', 5, {} ] | ||
| } | ||
| var result = bencode.encode( someData ) | ||
| var dat = bencode.decode ( result ) | ||
| assert.equal(dat.integer, 12345) | ||
| assert.deepEqual(dat.string, new Buffer("Hello World")) | ||
| assert.deepEqual(dat.dict.key, new Buffer("This is a string within a dictionary")) | ||
| assert.deepEqual(dat.list, [1, 2, 3, 4, new Buffer('string'), 5, {}]) | ||
| }); | ||
| }); | ||
| }); |
| var assert = require('assert') | ||
| var bencode = require('./lib.js') | ||
| var data = require('./data.js') | ||
| describe("bencode", function() { | ||
| describe("#decode(x, 'uft8')", function() { | ||
| it('should be able to decode an integer', function() { | ||
| assert.deepEqual(bencode.decode('i123e', 'utf8'), 123); | ||
| assert.deepEqual(bencode.decode('i-123e', 'utf8'), -123); | ||
| }); | ||
| it('should be able to decode a float (as int)', function() { | ||
| assert.deepEqual(bencode.decode('i12.3e', 'utf8'), 12); | ||
| assert.deepEqual(bencode.decode('i-12.3e', 'utf8'), -12); | ||
| }); | ||
| it('should be able to decode a string', function() { | ||
| assert.deepEqual(bencode.decode('5:asdfe', 'utf8'), 'asdfe'); | ||
| assert.deepEqual(bencode.decode('4:öö', 'utf8'), 'öö'); | ||
| }); | ||
| it('should be able to decode "binary keys"', function() { | ||
| var decoded = bencode.decode(data.binKeyData, 'utf8') | ||
| assert.ok(decoded.files.hasOwnProperty(data.binKeyName)); | ||
| }); | ||
| it('should be able to decode a dictionary', function() { | ||
| assert.deepEqual( | ||
| bencode.decode( 'd3:cow3:moo4:spam4:eggse', 'utf8' ), | ||
| { | ||
| cow: 'moo', | ||
| spam: 'eggs' | ||
| } | ||
| ) | ||
| assert.deepEqual( | ||
| bencode.decode( 'd4:spaml1:a1:bee', 'utf8' ), | ||
| { spam: [ 'a', 'b' ] } | ||
| ) | ||
| assert.deepEqual( | ||
| bencode.decode( 'd9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee', 'utf8' ), | ||
| { | ||
| 'publisher': 'bob', | ||
| 'publisher-webpage': 'www.example.com', | ||
| 'publisher.location': 'home' | ||
| } | ||
| ) | ||
| }); | ||
| it('should be able to decode a list', function() { | ||
| assert.deepEqual( | ||
| bencode.decode( 'l4:spam4:eggse', 'utf8' ), | ||
| [ 'spam', 'eggs' ] | ||
| ) | ||
| }); | ||
| it('should return the correct type', function() { | ||
| assert.ok(typeof(bencode.decode('4:öö', 'utf8')) === 'string'); | ||
| }); | ||
| it('should be able to decode stuff in dicts (issue #12)', function() { | ||
| var someData = { | ||
| string: 'Hello World', | ||
| integer: 12345, | ||
| dict: { | ||
| key: 'This is a string within a dictionary' | ||
| }, | ||
| list: [ 1, 2, 3, 4, 'string', 5, {} ] | ||
| } | ||
| var result = bencode.encode( someData ) | ||
| var dat = bencode.decode ( result, 'utf8' ) | ||
| assert.equal(dat.integer, 12345) | ||
| assert.deepEqual(dat.string, "Hello World") | ||
| assert.deepEqual(dat.dict.key, "This is a string within a dictionary") | ||
| assert.deepEqual(dat.list, [1, 2, 3, 4, 'string', 5, {}]) | ||
| }); | ||
| }); | ||
| }); |
| var assert = require("assert"); | ||
| var bencode = require('./lib.js'); | ||
| describe("bencode", function() { | ||
| // prevent the warning showing up in the test | ||
| bencode.encode._floatConversionDetected = true | ||
| describe("#encode()", function() { | ||
| it('should always return a Buffer', function() { | ||
| assert.ok(Buffer.isBuffer(bencode.encode({})), "its not a buffer for empty dicts"); | ||
| assert.ok(Buffer.isBuffer(bencode.encode("test")), "its not a buffer for strings"); | ||
| assert.ok(Buffer.isBuffer(bencode.encode([3, 2])), "its not a buffer for lists"); | ||
| assert.ok(Buffer.isBuffer(bencode.encode({"a": "b", 3: 6})), "its not a buffer for big dicts"); | ||
| assert.ok(Buffer.isBuffer(bencode.encode(123)), "its not a buffer for numbers"); | ||
| }); | ||
| it('should sort dictionories', function() { | ||
| var data = { | ||
| string: 'Hello World', | ||
| integer: 12345, | ||
| }; | ||
| assert.equal(bencode.encode(data).toString(), "d7:integeri12345e6:string11:Hello Worlde"); | ||
| }) | ||
| it('should force keys to be strings', function() { | ||
| var data = { | ||
| 12: 'Hello World', | ||
| 34: 12345, | ||
| }; | ||
| assert.equal(bencode.encode(data).toString(), "d2:1211:Hello World2:34i12345ee") | ||
| }) | ||
| it('should be able to encode a positive integer', function() { | ||
| assert.equal(bencode.encode(123), 'i123e'); | ||
| }) | ||
| it('should be able to encode a negative integer', function() { | ||
| assert.equal(bencode.encode(-123), 'i-123e'); | ||
| }) | ||
| it('should be able to encode a positive float (as int)', function() { | ||
| assert.equal(bencode.encode(123.5), 'i123e'); | ||
| }) | ||
| it('should be able to encode a negative float (as int)', function() { | ||
| assert.equal(bencode.encode(-123.5), 'i-123e'); | ||
| }) | ||
| it('should be able to safely encode numbers between -/+ 2 ^ 53 (as ints)', function() { | ||
| assert.equal(bencode.encode(0), 'i' + 0 + 'e'); | ||
| var JAVASCRIPT_INT_BITS = 53; | ||
| var MAX_JAVASCRIPT_INT = Math.pow(2, JAVASCRIPT_INT_BITS); | ||
| for (var exp = 1; exp < JAVASCRIPT_INT_BITS; ++exp) { | ||
| var val = Math.pow(2, exp); | ||
| // try the positive and negative | ||
| assert.equal(bencode.encode(val), 'i' + val + 'e'); | ||
| assert.equal(bencode.encode(-val), 'i-' + val + 'e'); | ||
| // try the value, one above and one below, both positive and negative | ||
| var above = val + 1; | ||
| var below = val - 1; | ||
| assert.equal(bencode.encode(above), 'i' + above + 'e'); | ||
| assert.equal(bencode.encode(-above), 'i-' + above + 'e'); | ||
| assert.equal(bencode.encode(below), 'i' + below + 'e'); | ||
| assert.equal(bencode.encode(-below), 'i-' + below + 'e'); | ||
| } | ||
| assert.equal(bencode.encode(MAX_JAVASCRIPT_INT), 'i' + MAX_JAVASCRIPT_INT + 'e'); | ||
| assert.equal(bencode.encode(-MAX_JAVASCRIPT_INT), 'i-' + MAX_JAVASCRIPT_INT + 'e'); | ||
| }); | ||
| it('should be able to encode a previously problematice 64 bit int', function() { | ||
| assert.equal(bencode.encode(2433088826), 'i' + 2433088826 + 'e'); | ||
| }) | ||
| it('should be able to encode a negative 64 bit int', function() { | ||
| assert.equal(bencode.encode(-0xffffffff), 'i-' + 0xffffffff + 'e'); | ||
| }) | ||
| it('should be able to encode a positive 64 bit float (as int)', function() { | ||
| assert.equal(bencode.encode(0xffffffff + 0.5), 'i' + 0xffffffff + 'e'); | ||
| }) | ||
| it('should be able to encode a negative 64 bit float (as int)', function() { | ||
| assert.equal(bencode.encode(-0xffffffff - 0.5), 'i-' + 0xffffffff + 'e'); | ||
| }) | ||
| it('should be able to encode a string', function() { | ||
| assert.equal(bencode.encode("asdf"), '4:asdf'); | ||
| assert.equal(bencode.encode(":asdf:"), '6::asdf:'); | ||
| }) | ||
| it('should be able to encode a unicode string', function() { | ||
| assert.equal(bencode.encode("ö±sdf"), '7:ö±sdf'); | ||
| assert.equal(bencode.encode(new Buffer("ö±sdf")), '7:ö±sdf'); | ||
| }) | ||
| it('should be able to encode a buffer', function() { | ||
| assert.equal(bencode.encode(new Buffer("asdf")), '4:asdf'); | ||
| assert.equal(bencode.encode(new Buffer(":asdf:")), '6::asdf:'); | ||
| }) | ||
| it('should be able to encode an array', function() { | ||
| assert.equal(bencode.encode([32, 12]), 'li32ei12ee'); | ||
| assert.equal(bencode.encode([":asdf:"]), 'l6::asdf:e'); | ||
| }) | ||
| it('should be able to encode an object', function() { | ||
| assert.equal(bencode.encode({"a": "bc"}), 'd1:a2:bce') | ||
| assert.equal(bencode.encode({"a": "45", "b": 45}), 'd1:a2:451:bi45ee') | ||
| assert.equal(bencode.encode({"a": new Buffer("bc")}), 'd1:a2:bce') | ||
| }) | ||
| }) | ||
| }); |
+1
-0
@@ -5,1 +5,2 @@ language: node_js | ||
| - 0.10 | ||
| - 0.11 |
+2
-2
@@ -13,3 +13,3 @@ /** | ||
| decode.data = !( data instanceof Buffer ) | ||
| decode.data = !( Buffer.isBuffer(data) ) | ||
| ? new Buffer( data ) | ||
@@ -97,3 +97,3 @@ : data | ||
| return parseInt( number, 10 ) | ||
| } | ||
@@ -100,0 +100,0 @@ |
+1
-1
@@ -17,3 +17,3 @@ /** | ||
| if( data instanceof Buffer ) { | ||
| if( Buffer.isBuffer(data) ) { | ||
| buffers.push(new Buffer(data.length + ':')) | ||
@@ -20,0 +20,0 @@ buffers.push(data) |
+23
-12
| { | ||
| "name": "bencode", | ||
| "version": "0.5.2", | ||
| "version": "0.6.0", | ||
| "license": "MIT", | ||
| "description": "Bencode de/encoder", | ||
| "keywords": [ "torrent", "bittorrent", "bencode", "bdecode", "bencoding" ], | ||
| "keywords": [ | ||
| "torrent", | ||
| "bittorrent", | ||
| "bencode", | ||
| "bdecode", | ||
| "bencoding" | ||
| ], | ||
| "contributors": [ | ||
@@ -18,7 +23,4 @@ { | ||
| } | ||
| ], | ||
| "main": "bencode.js", | ||
| "devDependencies": { | ||
@@ -30,10 +32,8 @@ "matcha": "", | ||
| "dht.js": "", | ||
| "mocha": "" | ||
| "tape": "~2.12" | ||
| }, | ||
| "scripts": { | ||
| "test": "node node_modules/mocha/bin/mocha", | ||
| "test": "node node_modules/tape/bin/tape test/*.test.js", | ||
| "bench": "node node_modules/matcha/bin/matcha benchmark/*.js" | ||
| }, | ||
| "repository": { | ||
@@ -43,7 +43,18 @@ "type": "git", | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/themasch/node-bencode/issues" | ||
| }, | ||
| "testling": { | ||
| "files": "test/*.test.js", | ||
| "browsers": [ | ||
| "ie/6..latest", | ||
| "chrome/22..latest", | ||
| "firefox/16..latest", | ||
| "safari/latest", | ||
| "opera/11.0..latest", | ||
| "iphone/6..latest", | ||
| "ipad/6..latest", | ||
| "android-browser/latest" | ||
| ] | ||
| } | ||
| } |
+4
-1
@@ -1,2 +0,1 @@ | ||
| # node-bencode [](http://travis-ci.org/themasch/node-bencode) [](https://npmjs.org/package/bencode) | ||
@@ -71,2 +70,6 @@ | ||
| You can also use node-bencode with browserify to be able to use it in a lot of modern browsers. | ||
| [](https://ci.testling.com/themasch/node-bencode) | ||
| ### Encoding | ||
@@ -73,0 +76,0 @@ |
+5
-2
| module.exports = { | ||
| binKeyData: new Buffer("ZDU6ZmlsZXNkMjA6N7VVuuCjmp5LoM+n15a5iM/XJHdkODpjb21wbGV0ZWkwZTEwOmRvd25sb2FkZWRpMTBlMTA6aW5jb21wbGV0ZWkwZWVlZQ==", 'base64') | ||
| , binKeyName: (new Buffer("N++/vVXvv73go5rvv71L77+9z6fXlu+/ve+/ve+/ve+/vSR3", 'base64')).toString() | ||
| //binKeyData: new Buffer("ZDU6ZmlsZXNkMjA6N7VVuuCjmp5LoM+n15a5iM/XJHdkODpjb21wbGV0ZWkwZTEwOmRvd25sb2FkZWRpMTBlMTA6aW5jb21wbGV0ZWkwZWVlZQ==", 'base64') | ||
| binKeyData: new Buffer('ZDU6ZmlsZXNkMzY6N++/vVXvv73go5rvv71L77+9z6fXlu+/ve+/ve+/ve+/vSR3ZDg6Y29tcGxldGVpMGUxMDpkb3dubG9hZGVkaTEwZTEwOmluY29tcGxldGVpMGVlZWU=', 'base64') | ||
| , binKeyName: new Buffer("N++/vVXvv73go5rvv71L77+9z6fXlu+/ve+/ve+/ve+/vSR3", 'base64') | ||
| , binStringData: new Buffer('w7bCsXNkZg==', 'base64') | ||
| , binResultData: new Buffer('NzrDtsKxc2Rm', 'base64') | ||
| } |
@@ -1,75 +0,85 @@ | ||
| var assert = require('assert') | ||
| var test = require('tape').test | ||
| var bencode = require('./lib.js') | ||
| var data = require('./data.js') | ||
| describe("bencode", function() { | ||
| describe("#decode(x)", function() { | ||
| it('should be able to decode an integer', function() { | ||
| assert.deepEqual(bencode.decode('i123e'), 123); | ||
| assert.deepEqual(bencode.decode('i-123e'), -123); | ||
| }); | ||
| it('should be able to decode a float (as int)', function() { | ||
| assert.deepEqual(bencode.decode('i12.3e'), 12); | ||
| assert.deepEqual(bencode.decode('i-12.3e'), -12); | ||
| }); | ||
| it('should be able to decode a string', function() { | ||
| assert.deepEqual(bencode.decode('5:asdfe'), new Buffer('asdfe')); | ||
| assert.deepEqual(bencode.decode('4:öö'), new Buffer('öö')); | ||
| }); | ||
| it('should be able to decode "binary keys"', function() { | ||
| assert.ok(bencode.decode(data.binKeyData).files.hasOwnProperty(data.binKeyName)); | ||
| }); | ||
| test("bencode#decode(x)", function(t) { | ||
| it('should be able to decode a dictionary', function() { | ||
| assert.deepEqual( | ||
| bencode.decode( 'd3:cow3:moo4:spam4:eggse' ), | ||
| { | ||
| cow: new Buffer('moo'), | ||
| spam: new Buffer('eggs') | ||
| } | ||
| ) | ||
| assert.deepEqual( | ||
| bencode.decode( 'd4:spaml1:a1:bee' ), | ||
| { spam: [ | ||
| new Buffer('a'), | ||
| new Buffer('b') | ||
| ] } | ||
| ) | ||
| assert.deepEqual( | ||
| bencode.decode( 'd9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee'), | ||
| { | ||
| 'publisher': new Buffer('bob'), | ||
| 'publisher-webpage': new Buffer('www.example.com'), | ||
| 'publisher.location': new Buffer('home') | ||
| } | ||
| ) | ||
| }); | ||
| t.test('should be able to decode an integer', function(t) { | ||
| t.plan(2) | ||
| t.equal(bencode.decode('i123e'), 123); | ||
| t.equal(bencode.decode('i-123e'), -123); | ||
| }) | ||
| it('should be able to decode a list', function() { | ||
| assert.deepEqual( | ||
| bencode.decode( 'l4:spam4:eggse'), | ||
| [ new Buffer('spam'), | ||
| new Buffer('eggs') ] | ||
| ) | ||
| }); | ||
| it('should return the correct type', function() { | ||
| assert.ok(bencode.decode('4:öö') instanceof Buffer); | ||
| }); | ||
| it('should be able to decode stuff in dicts (issue #12)', function() { | ||
| var someData = { | ||
| string: 'Hello World', | ||
| integer: 12345, | ||
| dict: { | ||
| key: 'This is a string within a dictionary' | ||
| }, | ||
| list: [ 1, 2, 3, 4, 'string', 5, {} ] | ||
| t.test('should be able to decode a float (as int)', function(t) { | ||
| t.plan(2) | ||
| t.equal(bencode.decode('i12.3e'), 12); | ||
| t.equal(bencode.decode('i-12.3e'), -12); | ||
| }) | ||
| t.test('should be able to decode a string', function(t) { | ||
| t.plan(2) | ||
| t.deepEqual(bencode.decode('5:asdfe'), new Buffer('asdfe')); | ||
| t.deepEqual(bencode.decode(data.binResultData.toString()), data.binStringData); | ||
| }) | ||
| t.test('should be able to decode "binary keys"', function(t) { | ||
| t.plan(1) | ||
| t.ok(bencode.decode(data.binKeyData).files.hasOwnProperty(data.binKeyName)); | ||
| }) | ||
| t.test('should be able to decode a dictionary', function(t) { | ||
| t.plan(3) | ||
| t.deepEqual( | ||
| bencode.decode( 'd3:cow3:moo4:spam4:eggse' ), | ||
| { | ||
| cow: new Buffer('moo'), | ||
| spam: new Buffer('eggs') | ||
| } | ||
| var result = bencode.encode( someData ) | ||
| var dat = bencode.decode ( result ) | ||
| assert.equal(dat.integer, 12345) | ||
| assert.deepEqual(dat.string, new Buffer("Hello World")) | ||
| assert.deepEqual(dat.dict.key, new Buffer("This is a string within a dictionary")) | ||
| assert.deepEqual(dat.list, [1, 2, 3, 4, new Buffer('string'), 5, {}]) | ||
| }); | ||
| ) | ||
| t.deepEqual( | ||
| bencode.decode( 'd4:spaml1:a1:bee' ), | ||
| { spam: [ | ||
| new Buffer('a'), | ||
| new Buffer('b') | ||
| ] } | ||
| ) | ||
| t.deepEqual( | ||
| bencode.decode( 'd9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee'), | ||
| { | ||
| 'publisher': new Buffer('bob'), | ||
| 'publisher-webpage': new Buffer('www.example.com'), | ||
| 'publisher.location': new Buffer('home') | ||
| } | ||
| ) | ||
| }); | ||
| }); | ||
| t.test('should be able to decode a list', function(t) { | ||
| t.plan(1) | ||
| t.deepEqual( | ||
| bencode.decode( 'l4:spam4:eggse'), | ||
| [ new Buffer('spam'), | ||
| new Buffer('eggs') ] | ||
| ) | ||
| }) | ||
| t.test('should return the correct type', function(t) { | ||
| t.plan(1) | ||
| t.ok(Buffer.isBuffer(bencode.decode('4:öö'))); | ||
| }) | ||
| t.test('should be able to decode stuff in dicts (issue #12)', function(t) { | ||
| t.plan(4) | ||
| var someData = { | ||
| string: 'Hello World', | ||
| integer: 12345, | ||
| dict: { | ||
| key: 'This is a string within a dictionary' | ||
| }, | ||
| list: [ 1, 2, 3, 4, 'string', 5, {} ] | ||
| } | ||
| var result = bencode.encode( someData ) | ||
| var dat = bencode.decode ( result ) | ||
| t.equal(dat.integer, 12345) | ||
| t.deepEqual(dat.string, new Buffer("Hello World")) | ||
| t.deepEqual(dat.dict.key, new Buffer("This is a string within a dictionary")) | ||
| t.deepEqual(dat.list, [1, 2, 3, 4, new Buffer('string'), 5, {}]) | ||
| }) | ||
| }) |
+74
-67
@@ -1,72 +0,79 @@ | ||
| var assert = require('assert') | ||
| var test = require('tape').test | ||
| var bencode = require('./lib.js') | ||
| var data = require('./data.js') | ||
| describe("bencode", function() { | ||
| describe("#decode(x, 'uft8')", function() { | ||
| it('should be able to decode an integer', function() { | ||
| assert.deepEqual(bencode.decode('i123e', 'utf8'), 123); | ||
| assert.deepEqual(bencode.decode('i-123e', 'utf8'), -123); | ||
| }); | ||
| it('should be able to decode a float (as int)', function() { | ||
| assert.deepEqual(bencode.decode('i12.3e', 'utf8'), 12); | ||
| assert.deepEqual(bencode.decode('i-12.3e', 'utf8'), -12); | ||
| }); | ||
| it('should be able to decode a string', function() { | ||
| assert.deepEqual(bencode.decode('5:asdfe', 'utf8'), 'asdfe'); | ||
| assert.deepEqual(bencode.decode('4:öö', 'utf8'), 'öö'); | ||
| }); | ||
| it('should be able to decode "binary keys"', function() { | ||
| var decoded = bencode.decode(data.binKeyData, 'utf8') | ||
| assert.ok(decoded.files.hasOwnProperty(data.binKeyName)); | ||
| }); | ||
| test("bencode#decode(x, 'uft8')", function(t) { | ||
| t.test('should be able to decode an integer', function(t) { | ||
| t.plan(2) | ||
| t.equal(bencode.decode('i123e', 'utf8'), 123) | ||
| t.equal(bencode.decode('i-123e', 'utf8'), -123) | ||
| }) | ||
| t.test('should be able to decode a float (as int)', function(t) { | ||
| t.plan(2) | ||
| t.equal(bencode.decode('i12.3e', 'utf8'), 12) | ||
| t.equal(bencode.decode('i-12.3e', 'utf8'), -12) | ||
| }) | ||
| t.test('should be able to decode a string', function(t) { | ||
| t.plan(2) | ||
| t.equal(bencode.decode('5:asdfe', 'utf8'), 'asdfe') | ||
| t.deepEqual(bencode.decode(data.binResultData.toString(), 'utf8'), data.binStringData.toString()); | ||
| }) | ||
| t.test('should be able to decode "binary keys"', function(t) { | ||
| t.plan(1) | ||
| var decoded = bencode.decode(data.binKeyData, 'utf8') | ||
| t.ok(decoded.files.hasOwnProperty(data.binKeyName.toString('utf8'))) | ||
| }) | ||
| it('should be able to decode a dictionary', function() { | ||
| assert.deepEqual( | ||
| bencode.decode( 'd3:cow3:moo4:spam4:eggse', 'utf8' ), | ||
| { | ||
| cow: 'moo', | ||
| spam: 'eggs' | ||
| } | ||
| ) | ||
| assert.deepEqual( | ||
| bencode.decode( 'd4:spaml1:a1:bee', 'utf8' ), | ||
| { spam: [ 'a', 'b' ] } | ||
| ) | ||
| assert.deepEqual( | ||
| bencode.decode( 'd9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee', 'utf8' ), | ||
| { | ||
| 'publisher': 'bob', | ||
| 'publisher-webpage': 'www.example.com', | ||
| 'publisher.location': 'home' | ||
| } | ||
| ) | ||
| }); | ||
| t.test('should be able to decode a dictionary', function(t) { | ||
| t.plan(3) | ||
| t.deepEqual( | ||
| bencode.decode( 'd3:cow3:moo4:spam4:eggse', 'utf8' ), | ||
| { | ||
| cow: 'moo', | ||
| spam: 'eggs' | ||
| } | ||
| ) | ||
| t.deepEqual( | ||
| bencode.decode( 'd4:spaml1:a1:bee', 'utf8' ), | ||
| { spam: [ 'a', 'b' ] } | ||
| ) | ||
| t.deepEqual( | ||
| bencode.decode( 'd9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee', 'utf8' ), | ||
| { | ||
| 'publisher': 'bob', | ||
| 'publisher-webpage': 'www.example.com', | ||
| 'publisher.location': 'home' | ||
| } | ||
| ) | ||
| }) | ||
| it('should be able to decode a list', function() { | ||
| assert.deepEqual( | ||
| bencode.decode( 'l4:spam4:eggse', 'utf8' ), | ||
| [ 'spam', 'eggs' ] | ||
| ) | ||
| }); | ||
| it('should return the correct type', function() { | ||
| assert.ok(typeof(bencode.decode('4:öö', 'utf8')) === 'string'); | ||
| }); | ||
| it('should be able to decode stuff in dicts (issue #12)', function() { | ||
| var someData = { | ||
| string: 'Hello World', | ||
| integer: 12345, | ||
| dict: { | ||
| key: 'This is a string within a dictionary' | ||
| }, | ||
| list: [ 1, 2, 3, 4, 'string', 5, {} ] | ||
| } | ||
| var result = bencode.encode( someData ) | ||
| var dat = bencode.decode ( result, 'utf8' ) | ||
| assert.equal(dat.integer, 12345) | ||
| assert.deepEqual(dat.string, "Hello World") | ||
| assert.deepEqual(dat.dict.key, "This is a string within a dictionary") | ||
| assert.deepEqual(dat.list, [1, 2, 3, 4, 'string', 5, {}]) | ||
| }); | ||
| }); | ||
| }); | ||
| t.test('should be able to decode a list', function(t) { | ||
| t.plan(1) | ||
| t.deepEqual( | ||
| bencode.decode( 'l4:spam4:eggse', 'utf8' ), | ||
| [ 'spam', 'eggs' ] | ||
| ) | ||
| }) | ||
| t.test('should return the correct type', function(t) { | ||
| t.plan(1) | ||
| t.ok(typeof(bencode.decode('4:öö', 'utf8')) === 'string') | ||
| }) | ||
| t.test('should be able to decode stuff in dicts (issue #12)', function(t) { | ||
| t.plan(4) | ||
| var someData = { | ||
| string: 'Hello World', | ||
| integer: 12345, | ||
| dict: { | ||
| key: 'This is a string within a dictionary' | ||
| }, | ||
| list: [ 1, 2, 3, 4, 'string', 5, {} ] | ||
| } | ||
| var result = bencode.encode( someData ) | ||
| var dat = bencode.decode ( result, 'utf8' ) | ||
| t.equal(dat.integer, 12345) | ||
| t.deepEqual(dat.string, "Hello World") | ||
| t.deepEqual(dat.dict.key, "This is a string within a dictionary") | ||
| t.deepEqual(dat.list, [1, 2, 3, 4, 'string', 5, {}]) | ||
| }) | ||
| }) |
+108
-91
@@ -1,5 +0,6 @@ | ||
| var assert = require("assert"); | ||
| var bencode = require('./lib.js'); | ||
| var test = require('tape').test | ||
| var bencode = require('./lib.js') | ||
| var data = require('./data.js') | ||
| describe("bencode", function() { | ||
| test('bencode#encode()', function(t) { | ||
@@ -9,95 +10,111 @@ // prevent the warning showing up in the test | ||
| describe("#encode()", function() { | ||
| it('should always return a Buffer', function() { | ||
| assert.ok(Buffer.isBuffer(bencode.encode({})), "its not a buffer for empty dicts"); | ||
| assert.ok(Buffer.isBuffer(bencode.encode("test")), "its not a buffer for strings"); | ||
| assert.ok(Buffer.isBuffer(bencode.encode([3, 2])), "its not a buffer for lists"); | ||
| assert.ok(Buffer.isBuffer(bencode.encode({"a": "b", 3: 6})), "its not a buffer for big dicts"); | ||
| assert.ok(Buffer.isBuffer(bencode.encode(123)), "its not a buffer for numbers"); | ||
| }); | ||
| it('should sort dictionories', function() { | ||
| var data = { | ||
| string: 'Hello World', | ||
| integer: 12345, | ||
| }; | ||
| assert.equal(bencode.encode(data).toString(), "d7:integeri12345e6:string11:Hello Worlde"); | ||
| }) | ||
| it('should force keys to be strings', function() { | ||
| var data = { | ||
| 12: 'Hello World', | ||
| 34: 12345, | ||
| }; | ||
| assert.equal(bencode.encode(data).toString(), "d2:1211:Hello World2:34i12345ee") | ||
| }) | ||
| it('should be able to encode a positive integer', function() { | ||
| assert.equal(bencode.encode(123), 'i123e'); | ||
| }) | ||
| it('should be able to encode a negative integer', function() { | ||
| assert.equal(bencode.encode(-123), 'i-123e'); | ||
| }) | ||
| it('should be able to encode a positive float (as int)', function() { | ||
| assert.equal(bencode.encode(123.5), 'i123e'); | ||
| }) | ||
| it('should be able to encode a negative float (as int)', function() { | ||
| assert.equal(bencode.encode(-123.5), 'i-123e'); | ||
| }) | ||
| it('should be able to safely encode numbers between -/+ 2 ^ 53 (as ints)', function() { | ||
| assert.equal(bencode.encode(0), 'i' + 0 + 'e'); | ||
| t.test('should always return a Buffer', function(t) { | ||
| t.plan(5) | ||
| t.ok(Buffer.isBuffer(bencode.encode({})), "its a buffer for empty dicts") | ||
| t.ok(Buffer.isBuffer(bencode.encode("test")), "its a buffer for strings") | ||
| t.ok(Buffer.isBuffer(bencode.encode([3, 2])), "its a buffer for lists") | ||
| t.ok(Buffer.isBuffer(bencode.encode({"a": "b", 3: 6})), "its a buffer for big dicts") | ||
| t.ok(Buffer.isBuffer(bencode.encode(123)), "its a buffer for numbers") | ||
| }) | ||
| var JAVASCRIPT_INT_BITS = 53; | ||
| var MAX_JAVASCRIPT_INT = Math.pow(2, JAVASCRIPT_INT_BITS); | ||
| t.test('should sort dictionaries', function(t) { | ||
| t.plan(1) | ||
| var data = { string: 'Hello World', integer: 12345 } | ||
| t.equal(bencode.encode(data).toString(), "d7:integeri12345e6:string11:Hello Worlde") | ||
| }) | ||
| for (var exp = 1; exp < JAVASCRIPT_INT_BITS; ++exp) { | ||
| var val = Math.pow(2, exp); | ||
| // try the positive and negative | ||
| assert.equal(bencode.encode(val), 'i' + val + 'e'); | ||
| assert.equal(bencode.encode(-val), 'i-' + val + 'e'); | ||
| t.test('should force keys to be strings', function(t) { | ||
| t.plan(1) | ||
| var data = { | ||
| 12: 'Hello World', | ||
| 34: 12345, | ||
| } | ||
| t.equal(bencode.encode(data).toString(), "d2:1211:Hello World2:34i12345ee") | ||
| }) | ||
| // try the value, one above and one below, both positive and negative | ||
| var above = val + 1; | ||
| var below = val - 1; | ||
| t.test('should be able to encode a positive integer', function(t) { | ||
| t.plan(1) | ||
| t.equal(bencode.encode(123).toString(), 'i123e') | ||
| }) | ||
| t.test('should be able to encode a negative integer', function(t) { | ||
| t.plan(1) | ||
| t.equal(bencode.encode(-123).toString(), 'i-123e') | ||
| }) | ||
| t.test('should be able to encode a positive float (as int)', function(t) { | ||
| t.plan(1) | ||
| t.equal(bencode.encode(123.5).toString(), 'i123e') | ||
| }) | ||
| t.test('should be able to encode a negative float (as int)', function(t) { | ||
| t.plan(1) | ||
| t.equal(bencode.encode(-123.5).toString(), 'i-123e') | ||
| }) | ||
| assert.equal(bencode.encode(above), 'i' + above + 'e'); | ||
| assert.equal(bencode.encode(-above), 'i-' + above + 'e'); | ||
| t.test('should be able to safely encode numbers between -/+ 2 ^ 53 (as ints)', function(t) { | ||
| var JAVASCRIPT_INT_BITS = 53 | ||
| var MAX_JAVASCRIPT_INT = Math.pow(2, JAVASCRIPT_INT_BITS) | ||
| assert.equal(bencode.encode(below), 'i' + below + 'e'); | ||
| assert.equal(bencode.encode(-below), 'i-' + below + 'e'); | ||
| } | ||
| assert.equal(bencode.encode(MAX_JAVASCRIPT_INT), 'i' + MAX_JAVASCRIPT_INT + 'e'); | ||
| assert.equal(bencode.encode(-MAX_JAVASCRIPT_INT), 'i-' + MAX_JAVASCRIPT_INT + 'e'); | ||
| }); | ||
| it('should be able to encode a previously problematice 64 bit int', function() { | ||
| assert.equal(bencode.encode(2433088826), 'i' + 2433088826 + 'e'); | ||
| }) | ||
| it('should be able to encode a negative 64 bit int', function() { | ||
| assert.equal(bencode.encode(-0xffffffff), 'i-' + 0xffffffff + 'e'); | ||
| }) | ||
| it('should be able to encode a positive 64 bit float (as int)', function() { | ||
| assert.equal(bencode.encode(0xffffffff + 0.5), 'i' + 0xffffffff + 'e'); | ||
| }) | ||
| it('should be able to encode a negative 64 bit float (as int)', function() { | ||
| assert.equal(bencode.encode(-0xffffffff - 0.5), 'i-' + 0xffffffff + 'e'); | ||
| }) | ||
| it('should be able to encode a string', function() { | ||
| assert.equal(bencode.encode("asdf"), '4:asdf'); | ||
| assert.equal(bencode.encode(":asdf:"), '6::asdf:'); | ||
| }) | ||
| it('should be able to encode a unicode string', function() { | ||
| assert.equal(bencode.encode("ö±sdf"), '7:ö±sdf'); | ||
| assert.equal(bencode.encode(new Buffer("ö±sdf")), '7:ö±sdf'); | ||
| }) | ||
| it('should be able to encode a buffer', function() { | ||
| assert.equal(bencode.encode(new Buffer("asdf")), '4:asdf'); | ||
| assert.equal(bencode.encode(new Buffer(":asdf:")), '6::asdf:'); | ||
| }) | ||
| it('should be able to encode an array', function() { | ||
| assert.equal(bencode.encode([32, 12]), 'li32ei12ee'); | ||
| assert.equal(bencode.encode([":asdf:"]), 'l6::asdf:e'); | ||
| }) | ||
| it('should be able to encode an object', function() { | ||
| assert.equal(bencode.encode({"a": "bc"}), 'd1:a2:bce') | ||
| assert.equal(bencode.encode({"a": "45", "b": 45}), 'd1:a2:451:bi45ee') | ||
| assert.equal(bencode.encode({"a": new Buffer("bc")}), 'd1:a2:bce') | ||
| }) | ||
| t.plan((JAVASCRIPT_INT_BITS-1) * 6 + 3) | ||
| t.equal(bencode.encode(0).toString(), 'i' + 0 + 'e') | ||
| for (var exp = 1; exp < JAVASCRIPT_INT_BITS; ++exp) { | ||
| var val = Math.pow(2, exp) | ||
| // try the positive and negative | ||
| t.equal(bencode.encode(val).toString(), 'i' + val + 'e') | ||
| t.equal(bencode.encode(-val).toString(), 'i-' + val + 'e') | ||
| // try the value, one above and one below, both positive and negative | ||
| var above = val + 1 | ||
| var below = val - 1 | ||
| t.equal(bencode.encode(above).toString(), 'i' + above + 'e') | ||
| t.equal(bencode.encode(-above).toString(), 'i-' + above + 'e') | ||
| t.equal(bencode.encode(below).toString(), 'i' + below + 'e') | ||
| t.equal(bencode.encode(-below).toString(), 'i-' + below + 'e') | ||
| } | ||
| t.equal(bencode.encode(MAX_JAVASCRIPT_INT).toString(), 'i' + MAX_JAVASCRIPT_INT + 'e') | ||
| t.equal(bencode.encode(-MAX_JAVASCRIPT_INT).toString(), 'i-' + MAX_JAVASCRIPT_INT + 'e') | ||
| }) | ||
| }); | ||
| t.test('should be able to encode a previously problematice 64 bit int', function(t) { | ||
| t.plan(1) | ||
| t.equal(bencode.encode(2433088826).toString(), 'i' + 2433088826 + 'e') | ||
| }) | ||
| t.test('should be able to encode a negative 64 bit int', function(t) { | ||
| t.plan(1) | ||
| t.equal(bencode.encode(-0xffffffff).toString(), 'i-' + 0xffffffff + 'e') | ||
| }) | ||
| t.test('should be able to encode a positive 64 bit float (as int)', function(t) { | ||
| t.plan(1) | ||
| t.equal(bencode.encode(0xffffffff + 0.5).toString(), 'i' + 0xffffffff + 'e') | ||
| }) | ||
| t.test('should be able to encode a negative 64 bit float (as int)', function(t) { | ||
| t.plan(1) | ||
| t.equal(bencode.encode(-0xffffffff - 0.5).toString(), 'i-' + 0xffffffff + 'e') | ||
| }) | ||
| t.test('should be able to encode a string', function(t) { | ||
| t.plan(2) | ||
| t.equal(bencode.encode("asdf").toString(), '4:asdf') | ||
| t.equal(bencode.encode(":asdf:").toString(), '6::asdf:') | ||
| }) | ||
| t.test('should be able to encode a unicode string', function(t) { | ||
| t.plan(2) | ||
| t.deepEqual(bencode.encode(data.binStringData.toString()), data.binResultData) | ||
| t.deepEqual(bencode.encode(data.binStringData.toString()), data.binResultData) | ||
| }) | ||
| t.test('should be able to encode a buffer', function(t) { | ||
| t.plan(2) | ||
| t.equal(bencode.encode(new Buffer("asdf")).toString(), '4:asdf') | ||
| t.equal(bencode.encode(new Buffer(":asdf:")).toString(), '6::asdf:') | ||
| }) | ||
| t.test('should be able to encode an array', function(t) { | ||
| t.plan(2) | ||
| t.equal(bencode.encode([32, 12]).toString(), 'li32ei12ee') | ||
| t.equal(bencode.encode([":asdf:"]).toString(), 'l6::asdf:e') | ||
| }) | ||
| t.test('should be able to encode an object', function(t) { | ||
| t.plan(3) | ||
| t.equal(bencode.encode({"a": "bc"}).toString(), 'd1:a2:bce') | ||
| t.equal(bencode.encode({"a": "45", "b": 45}).toString(), 'd1:a2:451:bi45ee') | ||
| t.equal(bencode.encode({"a": new Buffer("bc")}).toString(), 'd1:a2:bce') | ||
| }) | ||
| }) |
| "use strict"; | ||
| var util = require('util') | ||
| , events = require('events') | ||
| , microtime = require('microtime') | ||
| var Benchmark = { | ||
| Test: require('./test.js') | ||
| , Suite: require('./suite.js') | ||
| } | ||
| module.exports = Benchmark; |
| "use strict"; | ||
| var util = require('util') | ||
| , events = require('events') | ||
| , Test = require('./test.js') | ||
| var Suite = function(options) | ||
| { | ||
| if(!(this instanceof Suite)) { | ||
| return new Suite(options) | ||
| } | ||
| events.EventEmitter.call(this) | ||
| this.options = options || {} | ||
| this.tests = [] | ||
| } | ||
| util.inherits(Suite, events.EventEmitter) | ||
| Suite.prototype.add = function(name, test, options) | ||
| { | ||
| this.tests.push( new Test(name, test, options, this) ) | ||
| return this | ||
| } | ||
| Suite.prototype.run = function(options) | ||
| { | ||
| var tl = this.tests.length | ||
| var results = {} | ||
| for(var a=0;a<5;a++) { | ||
| for(var i=0;i<tl;i++) { | ||
| var test = this.tests[i] | ||
| var samples = test.run(options) | ||
| if(!results[test.name]) { | ||
| results[test.name] = samples | ||
| } | ||
| else { | ||
| for(var j=0;j<samples.length;j++) { | ||
| results[test.name].push(samples[j]) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| var stats = {} | ||
| for(var i=0;i<tl;i++) { | ||
| var test = this.tests[i] | ||
| var s = results[test.name] | ||
| stats[test.name] = this.doMathStuff(s) | ||
| } | ||
| console.log(stats) | ||
| } | ||
| Suite.prototype.doMathStuff = function(samples) { | ||
| var l = samples.length | ||
| var time = 0, runs = 0 | ||
| var maxOPS = 0 | ||
| , minOPS = Infinity | ||
| for(var i=0; i < l ; i++ ) { | ||
| time += samples[i][0] | ||
| runs += samples[i][1] | ||
| maxOPS = Math.max(samples[i][2], maxOPS) | ||
| minOPS = Math.min(samples[i][2], minOPS) | ||
| } | ||
| return { | ||
| avg: runs/time * 1e9, | ||
| best: maxOPS, | ||
| worst: minOPS | ||
| } | ||
| } | ||
| module.exports = Suite | ||
| exports.merge_objs = function() { | ||
| var result = {} | ||
| for( var i = 0 ; i < arguments.length ; i++ ) { | ||
| var obj = arguments[i] | ||
| if(typeof obj !== 'object') { | ||
| continue | ||
| } | ||
| var keys = Object.getOwnPropertyNames(obj) | ||
| var keyl = keys.length | ||
| for( var j = 0 ; j < keyl ; j++ ) { | ||
| var key = keys[j] | ||
| result[key] = obj[key] | ||
| } | ||
| } | ||
| return result | ||
| } | ||
| exports.time = function() { | ||
| var t = process.hrtime() | ||
| return t[0]*1e9 + t[1] | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
720011
1212.67%36
56.52%19266
3002.42%153
2%3
50%98
2350%1
Infinity%