diff --git a/.gitignore b/.gitignore index 1ca9571..7e41c97 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ npm-debug.log +.idea/ diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 8305ec6..0000000 --- a/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules/ -npm-debug.log -ByteBuffer.png diff --git a/.travis.yml b/.travis.yml index 58f2371..233454e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,8 @@ +sudo: false + language: node_js + node_js: - - 0.6 - - 0.8 - - 0.10 + - 6 + - 4 + - 0.12 diff --git a/ByteBuffer.js b/ByteBuffer.js deleted file mode 100644 index d05586d..0000000 --- a/ByteBuffer.js +++ /dev/null @@ -1,2144 +0,0 @@ -/* - Copyright 2013 Daniel Wirtz - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/** - * @license ByteBuffer.js (c) 2013 Daniel Wirtz - * Released under the Apache License, Version 2.0 - * see: https://github.com/dcodeIO/ByteBuffer.js for details - */ -(function(global) { - "use strict"; - - // Note that this library carefully avoids using the array access operator - // (i.e. buffer[x]) on ArrayBufferView subclasses (e.g. Uint8Array), and - // uses DataView instead. This is required for IE 8 compatibility. - - function loadByteBuffer(Long) { - - // Support node's Buffer if available, http://nodejs.org/api/buffer.html - var Buffer = null; - if (typeof require === 'function') { - try { - var nodeBuffer = require("buffer"); - Buffer = nodeBuffer && typeof nodeBuffer['Buffer'] === 'function' && typeof nodeBuffer['Buffer']['isBuffer'] === 'function' - ? nodeBuffer['Buffer'] : null; - } catch (e) {} - } - - /** - * Constructs a new ByteBuffer. - * @exports ByteBuffer - * @class Provides a Java-like, Netty-inspired ByteBuffer implementation using typed arrays. It also tries to - * abstract a bit of the complexity away by providing convenience methods for those who just want to write stuff - * without caring about signed, unsigned and the actual bit sizes. - * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to false. - * @constructor - * @expose - */ - var ByteBuffer = function(capacity, littleEndian) { - - capacity = typeof capacity !== 'undefined' ? parseInt(capacity, 10) : ByteBuffer.DEFAULT_CAPACITY; - if (capacity < 1) capacity = ByteBuffer.DEFAULT_CAPACITY; - - /** - * Underlying ArrayBuffer. - * @type {ArrayBuffer} - * @expose - */ - this.array = arguments.length == 3 && arguments[2] === true ? null : new ArrayBuffer(capacity); - - /** - * DataView to mess with the ArrayBuffer. - * @type {DataView} - * @expose - */ - this.view = this.array != null ? new DataView(this.array) : null; - /** - * Current read/write offset. Length- and capacity-independent index. Contents are the bytes between offset and - * length, which are both absolute indexes. There is no capacity property, use {@link ByteBuffer#capacity} - * instead. - * @type {number} - * @expose - */ - this.offset = 0; - - /** - * Marked offset set through {@link ByteBuffer#mark}. Evaluates to -1 if there is no marked offset. - * @type {number} - * @expose - */ - this.markedOffset = -1; - - /** - * Length of the contained data. Offset- and capacity-independent index. Contents are the bytes between offset and - * length, which are both absolute indexes. There is no capacity property, use {@link ByteBuffer#capacity} - * instead. - * @type {number} - * @expose - */ - this.length = 0; - - /** - * Whether to use little endian multi byte values. - * @type {boolean} - * @expose - */ - this.littleEndian = typeof littleEndian != 'undefined' ? !!littleEndian : false; - }; - - /** - * Default buffer capacity of 16 if nothing else is stated. The ByteBuffer will be automatically resized by a factor - * of 2 if required. - * @type {number} - * @const - * @expose - */ - ByteBuffer.DEFAULT_CAPACITY = 16; - - /** - * Little endian constant for usage in constructors instead of a boolean value. Evaluates to true. - * @type {boolean} - * @const - * @expose - */ - ByteBuffer.LITTLE_ENDIAN = true; - - /** - * Big endian constant for usage in constructors instead of a boolean value. Evaluates to false. - * @type {boolean} - * @const - * @expose - */ - ByteBuffer.BIG_ENDIAN = false; - - /** - * Long class for int64 support. May be undefined if the Long class has not been loaded and int64 support is - * not available. - * @type {?Long} - * @const - * @expose - */ - ByteBuffer.Long = Long; - - /** - * Allocates a new ByteBuffer. - * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to true. - * @return {ByteBuffer} - * @expose - */ - ByteBuffer.allocate = function(capacity, littleEndian) { - return new ByteBuffer(capacity, littleEndian); - }; - - /** - * Converts a node.js <= 0.8 Buffer to an ArrayBuffer. - * @param {Buffer} buffer Buffer to convert - * @return {ArrayBuffer} Converted buffer - * @private - */ - function toArrayBuffer(buffer) { - var ab = new ArrayBuffer(buffer.length); - var view = new Uint8Array(ab); - for (var i = 0; i < buffer.length; ++i) { - view[i] = buffer[i]; - } - return ab; - } - - /** - * Wraps an ArrayBuffer, any object containing an ArrayBuffer or a string. Sets the created ByteBuffer's offset to 0 - * and its length to the wrapped objects byte length. - * @param {ArrayBuffer|Buffer|string|{array: ArrayBuffer}|{buffer: ArrayBuffer}|string} buffer ArrayBuffer, any object with an .array or .buffer property or a string to wrap - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to true. - * @return {ByteBuffer} - * @throws {Error} If the specified object cannot be wrapped - * @expose - */ - ByteBuffer.wrap = function(buffer, littleEndian) { - // Wrap a string - if (typeof buffer === 'string') { - return new ByteBuffer().writeUTF8String(buffer).flip(); - } - var b; - // Wrap Buffer - if (Buffer && Buffer.isBuffer(buffer)) { - b = new Uint8Array(buffer).buffer; // noop on node <= 0.8 - buffer = (b === buffer) ? toArrayBuffer(buffer) : b; - } - // Refuse to wrap anything that's null or not an object - if (buffer === null || typeof buffer !== 'object') { - throw(new Error("Cannot wrap null or non-object")); - } - // Wrap ByteBuffer by cloning (preserve offsets) - if (buffer instanceof ByteBuffer) { - return buffer.clone(); - } - // Wrap any object that is or contains an ArrayBuffer - if (!!buffer["array"]) { - buffer = buffer["array"]; - } else if (!!buffer["buffer"]) { - buffer = buffer["buffer"]; - } - if (!(buffer instanceof ArrayBuffer)) { - throw(new Error("Cannot wrap buffer of type "+typeof(buffer)+", "+buffer.constructor.name)); - } - b = new ByteBuffer(0, littleEndian, /* shadow copy */ true); - b.array = buffer; - b.view = new DataView(b.array); - b.offset = 0; - b.length = buffer.byteLength; - return b; - }; - - /** - * Switches to little endian byte order. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.LE = function() { - this.littleEndian = true; - return this; - }; - - /** - * Switches to bid endian byte order. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.BE = function() { - this.littleEndian = false; - return this; - }; - - /** - * Resizes the ByteBuffer to the given capacity. - * @param {number} capacity New capacity - * @return {boolean} true if actually resized, false if already that large or larger - * @expose - */ - ByteBuffer.prototype.resize = function(capacity) { - if (capacity < 1) return false; - if (this.array == null) { // Silently recreate - this.array = new ArrayBuffer(capacity); - this.view = new DataView(this.array); - } - if (this.array.byteLength < capacity) { - var src = this.array; - var srcView = new Uint8Array(src); - var dst = new ArrayBuffer(capacity); - var dstView = new Uint8Array(dst); - dstView.set(srcView); - this.array = dst; - this.view = new DataView(dst); - return true; - } - return false; - }; - - /** - * Slices the ByteBuffer. This is independent of the ByteBuffer's actual offsets. Does not compact the underlying - * ArrayBuffer (use {@link ByteBuffer#compact} and maybe {@link ByteBuffer.wrap} instead). - * @param {number} begin Begin offset - * @param {number} end End offset - * @return {ByteBuffer} Clone of this ByteBuffer with the specified slicing applied, backed by the same ArrayBuffer - * @throws {Error} If the buffer cannot be sliced - * @expose - */ - ByteBuffer.prototype.slice = function(begin, end) { - if (this.array == null) { - throw(new Error(this+" cannot be sliced: Already destroyed")); - } - if (end <= begin) { - throw(new Error(this+" cannot be sliced: End ("+end+") is less than begin ("+begin+")")); - } - if (begin < 0 || begin > this.array.byteLength || end < 1 || end > this.array.byteLength) { - throw(new Error(this+" cannot be sliced: Index out of bounds (0-"+this.array.byteLength+" -> "+begin+"-"+end+")")); - } - var b = this.clone(); - b.offset = begin; - b.length = end; - return b; - }; - - /** - * Slices and compacts the ByteBuffer. The resulting ByteBuffer will have its own ArrayBuffer with the compacted contents - * of this ByteBuffer's contents. - * @param {number} begin Begin offset - * @param {number} end End offset - * @return {ByteBuffer} - * @throws {Error} If the buffer cannot be sliced - * @expose - */ - ByteBuffer.prototype.sliceAndCompact = function(begin, end) { - return ByteBuffer.wrap(this.slice(begin,end).toArrayBuffer(true)); - }; - - /** - * Makes sure that the specified capacity is available. If the current capacity is exceeded, it will be doubled. If - * double the previous capacity is less than the required capacity, the required capacity will be used. - * @param {number} capacity Required capacity - * @return {boolean} true if actually resized, false if already that large or larger - * @expose - */ - ByteBuffer.prototype.ensureCapacity = function(capacity) { - if (this.array == null) { - return this.resize(capacity); - } - if (this.array.byteLength < capacity) return this.resize(this.array.byteLength*2 >= capacity ? this.array.byteLength*2 : capacity); - return false; - }; - - /** - * Makes the buffer ready for a new sequence of write or relative read operations. Sets length=offset and offset=0. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.flip = function() { - this.length = this.array == null ? 0 : this.offset; - this.offset = 0; - return this; - }; - - /** - * Marks the current offset in {@link ByteBuffer#markedOffset}. - * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}. - * @return {ByteBuffer} this - * @throws {Error} If the mark cannot be set - * @see ByteBuffer#reset - * @expose - */ - ByteBuffer.prototype.mark = function(offset) { - if (this.array == null) { - throw(new Error(this+" cannot be marked: Already destroyed")); - } - offset = typeof offset !== 'undefined' ? parseInt(offset, 10) : this.offset; - if (offset < 0 || offset > this.array.byteLength) { - throw(new Error(this+" cannot be marked: Offset to mark is less than 0 or bigger than the capacity ("+this.array.byteLength+"): "+offset)); - } - this.markedOffset = offset; - return this; - }; - - /** - * Resets the ByteBuffer. If an offset has been marked through {@link ByteBuffer#mark} before, the offset will be - * set to the marked offset and the marked offset will be discarded. Length will not be altered. If there is no - * marked offset, sets offset=0 and length=0. - * @return {ByteBuffer} this - * @see ByteBuffer#mark - * @expose - */ - ByteBuffer.prototype.reset = function() { - if (this.markedOffset >= 0) { - this.offset = this.markedOffset; - this.markedOffset = -1; - } else { - this.offset = 0; - this.length = 0; - } - return this; - }; - - /** - * Clones this ByteBuffer. The returned cloned ByteBuffer shares the same ArrayBuffer but will have its own offsets. - * @return {ByteBuffer} - * @expose - */ - ByteBuffer.prototype.clone = function() { - // When cloning, an undocumented third parameter is used to set array and view manually. - var b = new ByteBuffer(-1, this.littleEndian, /* shadow copy */ true); - b.array = this.array; - b.view = this.view; - b.offset = this.offset; - b.length = this.length; - return b; - }; - - /** - * Copies this ByteBuffer. The returned copied ByteBuffer has its own ArrayBuffer and uses the same offsets as this one. - * @return {ByteBuffer} - * @expose - */ - ByteBuffer.prototype.copy = function() { - if (this.array == null) { - return this.clone(); - } - var b = new ByteBuffer(this.array.byteLength, this.littleEndian); - var src = new Uint8Array(this.array); - var dst = new Uint8Array(b.array); - dst.set(src); - b.offset = this.offset; - b.length = this.length; - return b; - }; - - /** - * Gets the number of remaining readable bytes. Contents are the bytes between offset and length, so this returns - * length-offset. - * @return {number} Remaining readable bytes (may be negative if offset is larger than length) - * @expose - */ - ByteBuffer.prototype.remaining = function() { - if (this.array == null) return 0; - return this.length - this.offset; - }; - - /** - * Gets the capacity of the backing buffer. May be larger but not less than the contents actual length. Contents are the - * bytes between offset and length, which is independent of the actual capacity. - * @return {number} Capacity of the backing buffer or 0 if destroyed - * @expose - */ - ByteBuffer.prototype.capacity = function() { - return this.array != null ? this.array.byteLength : 0; - }; - - /** - * Compacts the ByteBuffer to be backed by an ArrayBuffer of its actual length. Will {@link ByteBuffer#flip} the - * ByteBuffer if its offset is larger than its length. If the ByteBuffer's offset is less than its length, only the - * portion between its offset and length will be contained in the compacted backing buffer. Will set offset=0 and - * length=capacity. Will do nothing but flipping, if required, if already compacted. - * @return {ByteBuffer} this - * @throws {Error} If the buffer cannot be compacted - * @expose - */ - ByteBuffer.prototype.compact = function() { - if (this.array == null) { - throw(new Error(this+" cannot be compacted: Already destroyed")); - } - if (this.offset > this.length) { - this.flip(); - } - if (this.offset == this.length) { - throw(new Error(this+" cannot be compacted: Offset ("+this.offset+") is equal to its length ("+this.length+")")); - } - if (this.offset == 0 && this.length == this.array.byteLength) { - return this; // Already compacted - } - var srcView = new Uint8Array(this.array); - var dst = new ArrayBuffer(this.length-this.offset); - var dstView = new Uint8Array(dst); - dstView.set(srcView.subarray(this.offset, this.length)); - this.array = dst; - this.offset = 0; - this.length = this.array.byteLength; - return this; - }; - - /** - * Destroys the ByteBuffer, releasing all references to the backing array. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.destroy = function() { - if (this.array == null) return; // Already destroyed - this.array = null; - this.view = null; - this.offset = 0; - this.length = 0; - return this; - }; - - /** - * Reverses the underlying back buffer and adapts offset and length to retain the same relative position on the - * reversed data in inverse order. Example: "00<01 02>03 04".reverse() = "04 03<02 01>00". - * @return {ByteBuffer} this - * @throws {Error} If the buffer is already destroyed - * @expose - */ - ByteBuffer.prototype.reverse = function() { - if (this.array == null) { - throw(new Error(this+" cannot be reversed: Already destroyed")); - } - // Not sure what for, but other implementations seem to have it :-) - Array.prototype.reverse.call(new Uint8Array(this.array)); - var o = this.offset; - this.offset = this.array.byteLength - this.length; - this.length = this.array.byteLength - o; - this.view = new DataView(this.array); - return this; - }; - - /** - * Appends another ByteBuffer to this one. Appends only the portion between offset and length of the specified - * ByteBuffer and overwrites any contents behind the specified offset up to the number of bytes appended from - * the specified ByteBuffer in this ByteBuffer. Will clone and flip the specified ByteBuffer if its offset is - * larger than its length (its offsets remain untouched through cloning). - * @param {*} src ByteBuffer or any object that can be wrapped by one to prepend - * @param {number=} offset Offset to append behind. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the specified buffer is already destroyed - * @expose - */ - ByteBuffer.prototype.append = function(src, offset) { - if (!(src instanceof ByteBuffer)) { - src = ByteBuffer.wrap(src); - } - if (src.array == null) { - throw(new Error(src+" cannot be appended to "+this+": Already destroyed")); - } - var n = src.length - src.offset; - if (n == 0) return this; // Nothing to append - if (n < 0) { - src = src.clone().flip(); - n = src.length - src.offset; - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=n)-n; - this.ensureCapacity(offset+n); - var srcView = new Uint8Array(src.array); - var dstView = new Uint8Array(this.array); - dstView.set(srcView.subarray(src.offset, src.length), offset); - return this; - }; - - /** - * Prepends another ByteBuffer to this one. Prepends only the portion between offset and length of the specified - * ByteBuffer and overwrites any contents before the specified offsets up to the number of bytes prepended from - * the specified ByteBuffer in this ByteBuffer. Will clone and flip the specified ByteBuffer if its offset is - * larger than its length (its offsets remain untouched through cloning). - * @param {*} src ByteBuffer or any object that can be wrapped by one to prepend - * @param {number=} offset Offset to prepend before. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the specified buffer is already destroyed - * @expose - */ - ByteBuffer.prototype.prepend = function(src, offset) { - if (!(src instanceof ByteBuffer)) { - src = ByteBuffer.wrap(src); - } - if (src.array == null) { - throw(src+" cannot be prepended to "+this+": Already destroyed"); - } - var n = src.length - src.offset; - if (n == 0) return this; // Nothing to prepend - if (n < 0) { - src = src.clone().flip(); - n = src.length - src.offset; - } - var modify = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var diff = n-offset; - if (diff > 0) { - // Doesn't fit, so maybe resize and move the contents that are already contained - this.ensureCapacity(this.length+diff); - this.append(this, n); - this.offset += diff; - this.length += diff; - this.append(src, 0); - } else { - this.append(src, offset-n); - } - if (modify) { - this.offset -= n; - } - return this; - }; - - /** - * Writes an 8bit singed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeInt8 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=1)-1; - this.ensureCapacity(offset+1); - this.view.setInt8(offset, value); - return this; - }; - - /** - * Reads an 8bit singed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readInt8 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=1)-1; - if (offset >= this.array.byteLength) { - throw(new Error("Cannot read int8 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt8(offset); - }; - - /** - * Writes a byte. This is an alias of {ByteBuffer#writeInt8}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeByte = ByteBuffer.prototype.writeInt8; - - /** - * Reads a byte. This is an alias of {@link ByteBuffer#readInt8}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readByte = ByteBuffer.prototype.readInt8; - - /** - * Writes an 8bit unsinged integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the offset is equal to or larger than the capacity - * @expose - */ - ByteBuffer.prototype.writeUint8 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=1)-1; - this.ensureCapacity(offset+1); - this.view.setUint8(offset, value); - return this; - }; - - /** - * Reads an 8bit unsinged integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readUint8 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=1)-1; - if (offset+1 > this.array.byteLength) { - throw(new Error("Cannot read uint8 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint8(offset); - }; - - /** - * Writes a 16bit signed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeInt16 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - this.ensureCapacity(offset+2); - this.view.setInt16(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 16bit signed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readInt16 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - if (offset+2 > this.array.byteLength) { - throw(new Error("Cannot read int16 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt16(offset, this.littleEndian); - }; - - /** - * Writes a short value. This is an alias of {@link ByteBuffer#writeInt16}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeShort = ByteBuffer.prototype.writeInt16; - - /** - * Reads a short value. This is an alias of {@link ByteBuffer#readInt16}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readShort = ByteBuffer.prototype.readInt16; - - /** - * Writes a 16bit unsigned integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeUint16 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - this.ensureCapacity(offset+2); - this.view.setUint16(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 16bit unsigned integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readUint16 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - if (offset+2 > this.array.byteLEngth) { - throw(new Error("Cannot read int16 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint16(offset, this.littleEndian); - }; - - /** - * Writes a 32bit signed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeInt32 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setInt32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit signed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readInt32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (offset+4 > this.array.byteLength) { - throw(new Error("Cannot read int32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt32(offset, this.littleEndian); - }; - - /** - * Writes an integer. This is an alias of {@link ByteBuffer#writeInt32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeInt = ByteBuffer.prototype.writeInt32; - - /** - * Reads an integer. This is an alias of {@link ByteBuffer#readInt32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readInt = ByteBuffer.prototype.readInt32; - - /** - * Writes a 32bit unsigned integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeUint32 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setUint32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit unsigned integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readUint32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (offset+4 > this.array.byteLength) { - throw(new Error("Cannot read uint32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint32(offset, this.littleEndian); - }; - - /** - * Writes a 32bit float. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeFloat32 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setFloat32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit float. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readFloat32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (this.array == null || offset+4 > this.array.byteLength) { - throw(new Error("Cannot read float32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getFloat32(offset, this.littleEndian); - }; - - /** - * Writes a float. This is an alias of {@link ByteBuffer#writeFloat32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeFloat = ByteBuffer.prototype.writeFloat32; - - /** - * Reads a float. This is an alias of {@link ByteBuffer#readFloat32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readFloat = ByteBuffer.prototype.readFloat32; - - /** - * Writes a 64bit float. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeFloat64 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - this.ensureCapacity(offset+8); - this.view.setFloat64(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 64bit float. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+8 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readFloat64 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - throw(new Error("Cannot read float64 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getFloat64(offset, this.littleEndian); - }; - - /** - * Writes a double. This is an alias of {@link ByteBuffer#writeFloat64}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeDouble = ByteBuffer.prototype.writeFloat64; - - /** - * Reads a double. This is an alias of {@link ByteBuffer#readFloat64}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+8 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readDouble = ByteBuffer.prototype.readFloat64; - - /** - * Writes a 64bit integer. Utilizes Long.js to write the low and high 32 bits separately. - * @function - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.prototype.writeInt64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - this.ensureCapacity(offset+8); - if (this.littleEndian) { - this.view.setInt32(offset, value.getLowBits(), true); - this.view.setInt32(offset+4, value.getHighBits(), true); - } else { - this.view.setInt32(offset, value.getHighBits(), false); - this.view.setInt32(offset+4, value.getLowBits(), false); - } - return this; - }; - - /** - * Reads a 64bit integer. Utilizes Long.js to construct a new Long from the low and high 32 bits. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long} - * @throws {Error} If offset+8 is larger than the capacity or long support is not available - * @expose - */ - ByteBuffer.prototype.readInt64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - this.offset -= 8; - throw(new Error("Cannot read int64 from "+this+" at "+offset+": Capacity overflow")); - } - var value; - if (this.littleEndian) { - value = Long.fromBits(this.view.getInt32(offset, true), this.view.getInt32(offset+4, true), false); - } else { - value = Long.fromBits(this.view.getInt32(offset+4, false), this.view.getInt32(offset, false), false); - } - return value; - }; - - /** - * Writes a 64bit unsigned integer. Utilizes Long.js to write the low and high 32 bits separately. - * @function - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.prototype.writeUint64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, true); - this.ensureCapacity(offset+8); - if (this.littleEndian) { - this.view.setUint32(offset, value.getLowBitsUnsigned(), true); - this.view.setUint32(offset+4, value.getHighBitsUnsigned(), true); - } else { - this.view.setUint32(offset, value.getHighBitsUnsigned(), false); - this.view.setUint32(offset+4, value.getLowBitsUnsigned(), false); - } - return this; - }; - - /** - * Reads a 64bit unsigned integer. Utilizes Long.js to construct a new Long from the low and high 32 bits. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long} - * @throws {Error} If offset+8 is larger than the capacity or long support is not available - * @expose - */ - ByteBuffer.prototype.readUint64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - this.offset -= 8; - throw(new Error("Cannot read int64 from "+this+" at "+offset+": Capacity overflow")); - } - var value; - if (this.littleEndian) { - value = Long.fromBits(this.view.getUint32(offset, true), this.view.getUint32(offset+4, true), true); - } else { - value = Long.fromBits(this.view.getUint32(offset+4, false), this.view.getUint32(offset, false), true); - } - return value; - }; - - /** - * Writes a long. This is an alias of {@link ByteBuffer#writeInt64}. - * @function - * @param {number|ByteBuffer.Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeLong = ByteBuffer.prototype.writeInt64; - - /** - * Reads a long. This is an alias of {@link ByteBuffer#readInt64}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer.Long} - * @throws {Error} If offset+8 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readLong = ByteBuffer.prototype.readInt64; - - /** - * Maximum number of bytes required to store a 32bit base 128 variable-length integer. - * @type {number} - * @const - * @expose - */ - ByteBuffer.MAX_VARINT32_BYTES = 5; - - /** - * Writes a 32bit base 128 variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeVarint32 = function(value, offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - // ref: http://code.google.com/searchframe#WTeibokF6gE/trunk/src/google/protobuf/io/coded_stream.cc - value = value >>> 0; - this.ensureCapacity(offset+ByteBuffer.calculateVarint32(value)); - var dst = this.view, - size = 0; - dst.setUint8(offset, value | 0x80); - if (value >= (1 << 7)) { - dst.setUint8(offset+1, (value >> 7) | 0x80); - if (value >= (1 << 14)) { - dst.setUint8(offset+2, (value >> 14) | 0x80); - if (value >= (1 << 21)) { - dst.setUint8(offset+3, (value >> 21) | 0x80); - if (value >= (1 << 28)) { - dst.setUint8(offset+4, (value >> 28) & 0x7F); - size = 5; - } else { - dst.setUint8(offset+3, dst.getUint8(offset+3) & 0x7F); - size = 4; - } - } else { - dst.setUint8(offset+2, dst.getUint8(offset+2) & 0x7F); - size = 3; - } - } else { - dst.setUint8(offset+1, dst.getUint8(offset+1) & 0x7F); - size = 2; - } - } else { - dst.setUint8(offset, dst.getUint8(offset) & 0x7F); - size = 1; - } - if (advance) { - this.offset += size; - return this; - } else { - return size; - } - }; - - /** - * Reads a 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - * @expose - */ - ByteBuffer.prototype.readVarint32 = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - // ref: src/google/protobuf/io/coded_stream.cc - - var count = 0, b, - src = this.view; - var value = 0 >>> 0; - do { - b = src.getUint8(offset+count); - if (count < ByteBuffer.MAX_VARINT32_BYTES) { - value |= ((b&0x7F)<<(7*count)) >>> 0; - } - ++count; - } while (b & 0x80); - value = value | 0; // Make sure to discard the higher order bits - if (advance) { - this.offset += count; - return value; - } else { - return { - "value": value, - "length": count - }; - } - }; - - /** - * Writes a zigzag encoded 32bit base 128 encoded variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeZigZagVarint32 = function(value, offset) { - return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset); - }; - - /** - * Reads a zigzag encoded 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - * @expose - */ - ByteBuffer.prototype.readZigZagVarint32 = function(offset) { - var dec = this.readVarint32(offset); - if (typeof dec === 'object') { - dec['value'] = ByteBuffer.zigZagDecode32(dec['value']); - return dec; - } - return ByteBuffer.zigZagDecode32(dec); - }; - - /** - * Maximum number of bytes required to store a 64bit base 128 variable-length integer. - * @type {number} - * @const - * @expose - */ - ByteBuffer.MAX_VARINT64_BYTES = 10; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_7_DBL = 1 << 7; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_14_DBL = TWO_PWR_7_DBL * TWO_PWR_7_DBL; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_21_DBL = TWO_PWR_7_DBL * TWO_PWR_14_DBL; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_28_DBL = TWO_PWR_14_DBL * TWO_PWR_14_DBL; - - /** - * Writes a 64bit base 128 variable-length integer as used in protobuf. - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.prototype.writeVarint64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - - var part0 = value.toInt() >>> 0, - part1 = value.shiftRightUnsigned(28).toInt() >>> 0, - part2 = value.shiftRightUnsigned(56).toInt() >>> 0, - size = ByteBuffer.calculateVarint64(value); - - this.ensureCapacity(offset+size); - var dst = this.view; - switch (size) { - case 10: dst.setUint8(offset+9, (part2 >>> 7) | 0x80); - case 9 : dst.setUint8(offset+8, (part2 ) | 0x80); - case 8 : dst.setUint8(offset+7, (part1 >>> 21) | 0x80); - case 7 : dst.setUint8(offset+6, (part1 >>> 14) | 0x80); - case 6 : dst.setUint8(offset+5, (part1 >>> 7) | 0x80); - case 5 : dst.setUint8(offset+4, (part1 ) | 0x80); - case 4 : dst.setUint8(offset+3, (part0 >>> 21) | 0x80); - case 3 : dst.setUint8(offset+2, (part0 >>> 14) | 0x80); - case 2 : dst.setUint8(offset+1, (part0 >>> 7) | 0x80); - case 1 : dst.setUint8(offset+0, (part0 ) | 0x80); - } - dst.setUint8(offset+size-1, dst.getUint8(offset+size-1) & 0x7F); - if (advance) { - this.offset += size; - return this; - } else { - return size; - } - }; - - /** - * Reads a 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long|{value: Long, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint or long support is not available - * @expose - */ - ByteBuffer.prototype.readVarint64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var start = offset; - // ref: src/google/protobuf/io/coded_stream.cc - - var src = this.view, - part0, part1 = 0, part2 = 0, b; - b = src.getUint8(offset++); part0 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 7; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 14; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 21; if (b & 0x80) { - b = src.getUint8(offset++); part1 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 7; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 14; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 21; if (b & 0x80) { - b = src.getUint8(offset++); part2 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part2 |= (b & 0x7F) << 7; if (b & 0x80) { - throw(new Error("Data must be corrupt: Buffer overrun")); }}}}}}}}}} - var value = Long.from28Bits(part0, part1, part2, false); - if (advance) { - this.offset = offset; - return value; - } else { - return { - "value": value, - "length": offset-start - }; - } - }; - - /** - * Writes a zigzag encoded 64bit base 128 encoded variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.prototype.writeZigZagVarint64 = function(value, offset) { - return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); - }; - - /** - * Reads a zigzag encoded 64bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long|{value: Long, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint or long support is not available - * @expose - */ - ByteBuffer.prototype.readZigZagVarint64 = function(offset) { - var dec = this.readVarint64(offset); - if (typeof dec === 'object' && !(dec instanceof Long)) { - dec['value'] = ByteBuffer.zigZagDecode64(dec['value']); - return dec; - } - return ByteBuffer.zigZagDecode64(dec); - }; - - /** - * Writes a base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#writeVarint32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeVarint = ByteBuffer.prototype.writeVarint32; - - /** - * Reads a base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#readVarint32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @expose - */ - ByteBuffer.prototype.readVarint = ByteBuffer.prototype.readVarint32; - - /** - * Writes a zigzag encoded base 128 encoded variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#writeZigZagVarint32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeZigZagVarint = ByteBuffer.prototype.writeZigZagVarint32; - - /** - * Reads a zigzag encoded base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#readZigZagVarint32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - * @expose - */ - ByteBuffer.prototype.readZigZagVarint = ByteBuffer.prototype.readZigZagVarint32; - - /** - * Calculates the actual number of bytes required to encode a 32bit base 128 variable-length integer. - * @param {number} value Value to encode - * @return {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES} (35bit). No overflow error. - * @expose - */ - ByteBuffer.calculateVarint32 = function(value) { - // ref: src/google/protobuf/io/coded_stream.cc - value = value >>> 0; - if (value < TWO_PWR_7_DBL) { - return 1; - } else if (value < TWO_PWR_14_DBL) { - return 2; - } else if (value < TWO_PWR_21_DBL) { - return 3; - } else if (value < TWO_PWR_28_DBL) { - return 4; - } else { - return 5; - } - }; - - /** - * Calculates the actual number of bytes required to encode a 64bit base 128 variable-length integer. - * @param {number|Long} value Value to encode - * @return {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES}. No overflow error. - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.calculateVarint64 = function(value) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/io/coded_stream.cc - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - - var part0 = value.toInt() >>> 0, - part1 = value.shiftRightUnsigned(28).toInt() >>> 0, - part2 = value.shiftRightUnsigned(56).toInt() >>> 0; - - if (part2 == 0) { - if (part1 == 0) { - if (part0 < TWO_PWR_14_DBL) { - return part0 < TWO_PWR_7_DBL ? 1 : 2; - } else { - return part0 < TWO_PWR_21_DBL ? 3 : 4; - } - } else { - if (part1 < TWO_PWR_14_DBL) { - return part1 < TWO_PWR_7_DBL ? 5 : 6; - } else { - return part1 < TWO_PWR_21_DBL ? 7 : 8; - } - } - } else { - return part2 < TWO_PWR_7_DBL ? 9 : 10; - } - }; - - /** - * Encodes a signed 32bit integer so that it can be effectively used with varint encoding. - * @param {number} n Signed 32bit integer - * @return {number} Unsigned zigzag encoded 32bit integer - * @expose - */ - ByteBuffer.zigZagEncode32 = function(n) { - // ref: src/google/protobuf/wire_format_lite.h - return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; - }; - - /** - * Decodes a zigzag encoded signed 32bit integer. - * @param {number} n Unsigned zigzag encoded 32bit integer - * @return {number} Signed 32bit integer - * @expose - */ - ByteBuffer.zigZagDecode32 = function(n) { - // ref: src/google/protobuf/wire_format_lite.h - return ((n >>> 1) ^ -(n & 1)) | 0; - }; - - /** - * Encodes a signed 64bit integer so that it can be effectively used with varint encoding. - * @param {number|Long} n Signed long - * @return {Long} Unsigned zigzag encoded long - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.zigZagEncode64 = function(n) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/wire_format_lite.h - if (typeof n === 'object' && n instanceof Long) { - if (n.unsigned) n = n.toSigned(); - } else { - n = Long.fromNumber(n, false); - } - return n.shiftLeft(1).xor(n.shiftRight(63)).toUnsigned(); - }; - - /** - * Decodes a zigzag encoded signed 64bit integer. - * @param {Long} n Unsigned zigzag encoded long - * @return {Long} Signed long - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.zigZagDecode64 = function(n) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/wire_format_lite.h - if (typeof n === 'object' && n instanceof Long) { - if (!n.unsigned) n = n.toUnsigned(); - } else { - n = Long.fromNumber(n, true); - } - return n.shiftRightUnsigned(1).xor(n.and(Long.ONE).toSigned().negate()).toSigned(); - }; - - /** - * Decodes a single UTF8 character from the specified ByteBuffer. The ByteBuffer's offsets are not modified. - * @param {ByteBuffer} src - * @param {number} offset Offset to read from - * @return {{char: number, length: number}} Decoded char code and the actual number of bytes read - * @throws {Error} If the character cannot be decoded or there is a capacity overflow - * @expose - */ - ByteBuffer.decodeUTF8Char = function(src, offset) { - var a = src.readUint8(offset), b, c, d, e, f, start = offset, charCode; - // ref: http://en.wikipedia.org/wiki/UTF-8#Description - // It's quite huge but should be pretty fast. - if ((a&0x80)==0) { - charCode = a; - offset += 1; - } else if ((a&0xE0)==0xC0) { - b = src.readUint8(offset+1); - charCode = ((a&0x1F)<<6) | (b&0x3F); - offset += 2; - } else if ((a&0xF0)==0xE0) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - charCode = ((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F); - offset += 3; - } else if ((a&0xF8)==0xF0) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - charCode = ((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F); - offset += 4; - } else if ((a&0xFC)==0xF8) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - e = src.readUint8(offset+4); - charCode = ((a&0x03)<<24) | ((b&0x3F)<<18) | ((c&0x3F)<<12) | ((d&0x3F)<<6) | (e&0x3F); - offset += 5; - } else if ((a&0xFE)==0xFC) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - e = src.readUint8(offset+4); - f = src.readUint8(offset+5); - charCode = ((a&0x01)<<30) | ((b&0x3F)<<24) | ((c&0x3F)<<18) | ((d&0x3F)<<12) | ((e&0x3F)<<6) | (f&0x3F); - offset += 6; - } else { - throw(new Error("Cannot decode UTF8 character at offset "+offset+": charCode (0x"+a.toString(16)+") is invalid")); - } - return { - "char": charCode , - "length": offset-start - }; - }; - - /** - * Encodes a single UTF8 character to the specified ByteBuffer. The ByteBuffer's offsets are not modified. - * @param {number} charCode Character to encode as char code - * @param {ByteBuffer} dst ByteBuffer to encode to - * @param {number} offset Offset to write to - * @return {number} Actual number of bytes written - * @throws {Error} If the character cannot be encoded - * @expose - */ - ByteBuffer.encodeUTF8Char = function(charCode, dst, offset) { - var start = offset; - // ref: http://en.wikipedia.org/wiki/UTF-8#Description - // It's quite huge but should be pretty fast. - if (charCode < 0) { - throw(new Error("Cannot encode UTF8 character: charCode ("+charCode+") is negative")); - } - if (charCode < 0x80) { - dst.writeUint8(charCode&0x7F, offset); - offset += 1; - } else if (charCode < 0x800) { - dst.writeUint8(((charCode>>6)&0x1F)|0xC0, offset) - .writeUint8((charCode&0x3F)|0x80, offset+1); - offset += 2; - } else if (charCode < 0x10000) { - dst.writeUint8(((charCode>>12)&0x0F)|0xE0, offset) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+1) - .writeUint8((charCode&0x3F)|0x80, offset+2); - offset += 3; - } else if (charCode < 0x200000) { - dst.writeUint8(((charCode>>18)&0x07)|0xF0, offset) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+2) - .writeUint8((charCode&0x3F)|0x80, offset+3); - offset += 4; - } else if (charCode < 0x4000000) { - dst.writeUint8(((charCode>>24)&0x03)|0xF8, offset) - .writeUint8(((charCode>>18)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+2) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+3) - .writeUint8((charCode&0x3F)|0x80, offset+4); - offset += 5; - } else if (charCode < 0x80000000) { - dst.writeUint8(((charCode>>30)&0x01)|0xFC, offset) - .writeUint8(((charCode>>24)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>18)&0x3F)|0x80, offset+2) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+3) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+4) - .writeUint8((charCode&0x3F)|0x80, offset+5); - offset += 6; - } else { - throw(new Error("Cannot encode UTF8 character: charCode (0x"+charCode.toString(16)+") is too large (>= 0x80000000)")); - } - return offset-start; - }; - - /** - * Calculates the actual number of bytes required to encode the specified char code. - * @param {number} charCode Character to encode as char code - * @return {number} Number of bytes required to encode the specified char code - * @throws {Error} If the character cannot be calculated (too large) - * @expose - */ - ByteBuffer.calculateUTF8Char = function(charCode) { - if (charCode < 0) { - throw(new Error("Cannot calculate length of UTF8 character: charCode ("+charCode+") is negative")); - } - if (charCode < 0x80) { - return 1; - } else if (charCode < 0x800) { - return 2; - } else if (charCode < 0x10000) { - return 3; - } else if (charCode < 0x200000) { - return 4; - } else if (charCode < 0x4000000) { - return 5; - } else if (charCode < 0x80000000) { - return 6; - } else { - throw(new Error("Cannot calculate length of UTF8 character: charCode (0x"+charCode.toString(16)+") is too large (>= 0x80000000)")); - } - }; - - /** - * Calculates the number of bytes required to store an UTF8 encoded string. - * @param {string} str String to calculate - * @return {number} Number of bytes required - */ - ByteBuffer.calculateUTF8String = function(str) { - str = ""+str; - var bytes = 0; - for (var i=0; i i ? bb.readUint8(i++) : 0; - o3 = bb.length > i ? bb.readUint8(i++) : 0; - bits = o1 << 16 | o2 << 8 | o3; - h1 = bits >> 18 & 0x3f; - h2 = bits >> 12 & 0x3f; - h3 = bits >> 6 & 0x3f; - h4 = bits & 0x3f; - out[oi++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); - } while (i < bb.length); - var enc = out.join(''), - r = (bb.length - bb.offset) % 3; - return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3); - }; - - /** - * Decodes a base6 encoded string to a ByteBuffer. - * @param {string} str Base64 encoded string - * @returns {!ByteBuffer} ByteBuffer - * @throws {Error} If the argument is not a valid base64 encoded string - * @expose - */ - ByteBuffer.decode64 = function(str) { - // ref: http://phpjs.org/functions/base64_decode/ - if (typeof str !== 'string') { - throw(new Error("Illegal argument: Not a string")); - } - var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, - out = new ByteBuffer(Math.ceil(str.length / 3)); - do { - h1 = b64.indexOf(str.charAt(i++)); - h2 = b64.indexOf(str.charAt(i++)); - h3 = b64.indexOf(str.charAt(i++)); - h4 = b64.indexOf(str.charAt(i++)); - if (h1 < 0 || h2 < 0 || h3 < 0 || h4 < 0) { - throw(new Error("Illegal argument: Not a valid base64 encoded string")); - } - bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; - o1 = bits >> 16 & 0xff; - o2 = bits >> 8 & 0xff; - o3 = bits & 0xff; - if (h3 == 64) { - out.writeUint8(o1); - } else if (h4 == 64) { - out.writeUint8(o1) - .writeUint8(o2); - } else { - out.writeUint8(o1) - .writeUint8(o2) - .writeUint8(o3); - } - } while (i < str.length); - return out.flip(); - }; - - - /** - * Writes an UTF8 string. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeUTF8String = function(str, offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var start = offset; - var encLen = ByteBuffer.calculateUTF8String(str), i; // See [1] - this.ensureCapacity(offset+encLen); - for (i=0; ilength ? "+" : "")+offset-length)+" bytes")); - } - if (advance) { - this.offset = offset; - return result; - } else { - return { - "string": result, - "length": offset-start - } - } - }; - - /** - * Writes a string with prepended number of characters, which is also encoded as an UTF8 character.. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeLString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = ByteBuffer.encodeUTF8Char(str.length, this, offset); - encLen += this.writeUTF8String(str, offset+encLen); - if (advance) { - this.offset += encLen; - return this; - } else { - return encLen; - } - }; - - /** - * Reads a string with a prepended number of characters, which is also encoded as an UTF8 character. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded - * @expose - */ - ByteBuffer.prototype.readLString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var lenDec = ByteBuffer.decodeUTF8Char(this, offset); - var dec = this.readUTF8String(lenDec["char"], offset+lenDec["length"]); - if (advance) { - this.offset += lenDec["length"]+dec["length"]; - return dec["string"]; - } else { - return { - "string": dec["string"], - "length": lenDec["length"]+dec["length"] - }; - } - }; - - /** - * Writes a string with prepended number of characters, which is encoded as a 32bit base 128 variable-length integer. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeVString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = this.writeVarint32(ByteBuffer.calculateUTF8String(str), offset); - encLen += this.writeUTF8String(str, offset+encLen); - if (advance) { - this.offset += encLen; - return this; - } else { - return encLen; - } - }; - - /** - * Reads a string with a prepended number of characters, which is encoded as a 32bit base 128 variable-length integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded or the delimiter is not a valid varint - * @expose - */ - ByteBuffer.prototype.readVString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var lenDec = this.readVarint32(offset); - var dec = this.readUTF8StringBytes(lenDec["value"], offset+lenDec["length"]); - if (advance) { - this.offset += lenDec["length"]+dec["length"]; - return dec["string"]; - } else { - return { - "string": dec["string"], - "length": lenDec["length"]+dec["length"] - }; - } - }; - - /** - * Writes a string followed by a NULL character (Uint8). Beware: The source string must not contain NULL characters - * unless this is actually intended. This is not checked. If you have the option it is recommended to use - * {@link ByteBuffer#writeLString} or {@link ByteBuffer#writeVString} with the corresponding reading methods instead. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeCString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = this.writeUTF8String(str, offset); - this.writeUint8(0, offset+encLen); - if (advance) { - this.offset += encLen+1; - return this; - } else { - return encLen+1; - } - }; - - /** - * Reads a string followed by a NULL character (Uint8). - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded - * @expose - */ - ByteBuffer.prototype.readCString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var dec, result = "", start = offset; - do { - dec = ByteBuffer.decodeUTF8Char(this, offset); - offset += dec["length"]; - if (dec["char"] != 0) result += String.fromCharCode(dec["char"]); - } while (dec["char"] != 0); - if (advance) { - this.offset = offset; - return result; - } else { - return { - "string": result, - "length": offset-start - }; - } - }; - - /** - * Serializes and writes a JSON payload. - * @param {*} data Data payload to serialize - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted, - * @param {function=} stringify Stringify implementation to use. Defaults to {@link JSON.stringify}. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number if bytes written, - * @expose - */ - ByteBuffer.prototype.writeJSON = function(data, offset, stringify) { - stringify = typeof stringify === 'function' ? stringify : JSON.stringify; - return this.writeLString(stringify(data), offset); - }; - - /** - * Reads a JSON payload and unserializes it. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @param {function=} parse Parse implementation to use. Defaults to {@link JSON.parse}. - * @return {*|{data: *, length: number}} Data payload if offset is omitted, else the data payload and the actual number of bytes read. - * @throws {Error} If the data cannot be decoded - * @expose - */ - ByteBuffer.prototype.readJSON = function(offset, parse) { - parse = typeof parse === 'function' ? parse : JSON.parse; - var result = this.readLString(offset); - if (typeof result === 'string') { - return parse(result); - } else { - return { - "data": parse(result["string"]), - "length": result["length"] - }; - } - }; - - /** - * Prints debug information about this ByteBuffer's contents to console. - * @param {!Function=|boolean} out Output function to call with the result or true to return the data as a string. - * Defaults to call console.log. - * @expose - */ - ByteBuffer.prototype.printDebug = function(out) { - var s = (this.array != null ? "ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")" : "ByteBuffer(DESTROYED)")+"\n"+ - "-------------------------------------------------------------------\n"; - var h = this.toHex(16, true); - var a = this.toASCII(16, true); - for (var i=0; i} Hex representation as of " 00<01 02>03..." with marked offsets - * @expose - */ - ByteBuffer.prototype.toHex = function(wrap, asArray) { - if (this.array == null) return "DESTROYED"; - asArray = !!asArray; - wrap = typeof wrap !== 'undefined' ? parseInt(wrap, 10) : 16; - if (wrap < 1) wrap = 16; - var out = "", - lines = [], - view = this.view; - if (this.offset == 0 && this.length == 0) { - out += "|"; - } else if (this.length == 0) { - out += ">"; - } else if (this.offset == 0) { - out += "<"; - } else { - out += " "; - } - for (var i=0; i0 && i%wrap == 0) { - lines.push(out); - out = " "; - } - var val = view.getUint8(i); - val = val.toString(16).toUpperCase(); - if (val.length < 2) val = "0"+val; - out += val; - if (i+1 == this.offset && i+1 == this.length) { - out += "|"; - } else if (i+1 == this.offset) { - out += "<"; - } else if (i+1 == this.length) { - out += ">"; - } else { - out += " "; - } - } - if (asArray) { - while (out.length < 3*wrap+1) out += " "; // Make it equal to maybe show something on the right - } - lines.push(out); - return asArray ? lines : lines.join("\n"); - }; - - /** - * Returns an ASCII representation of this ByteBuffer's contents. Beware: May be large. - * @param {number=} wrap Wrap length. Defaults to 16. - * @param {boolean=} asArray Set to true to return an array of lines. Defaults to false. - * @return {string|Array.} ASCII representation as of "abcdef..." (33-126, else ".", no marked offsets) - * @expose - */ - ByteBuffer.prototype.toASCII = function(wrap, asArray) { - if (this.array == null) return ""; - asArray = !!asArray; - wrap = typeof wrap !== 'undefined' ? parseInt(wrap, 10) : 16; - if (wrap < 1) wrap = 16; - var out = "", lines = [], src = this.view; - for (var i=0; i0 && i%wrap == 0) { - lines.push(out); - out = ""; - } - var val = src.getUint8(i); - if (val > 32 && val < 127) { - val = String.fromCharCode(val); - } else { - val = "."; - } - out += val; - } - lines.push(out); - return asArray ? lines : lines.join("\n")+"\n"; - }; - - /** - * Returns the base64 encoded representation of the buffer's contents. - * @returns {string} Base 64 encoded string - * @expose - */ - ByteBuffer.prototype.toBase64 = function() { - if (this.array == null || this.offset >= this.length) return ""; - return ByteBuffer.encode64(this); - }; - - /** - * Returns the contents of the buffer as an UTF8 encoded string. - * @returns {string} - * @expose - */ - ByteBuffer.prototype.toUTF8 = function() { - if (this.array == null || this.offset >= this.length) return ""; - return this.readUTF8StringBytes(this.length - this.offset, this.offset).string; - }; - - /** - * Returns a string representation. - * @param {string=} enc Output encoding. Returns a pretty printed debug table by default but also allows direct - * conversion to "utf8" and "base64" encoding. - * @return {string} String representation - * @expose - */ - ByteBuffer.prototype.toString = function(enc) { - enc = enc || "debug"; - switch (enc) { - case "utf8": - return this.toUTF8(); - case "base64": - return this.toBase64(); - default: - if (this.array == null) { - return "ByteBuffer(DESTROYED)"; - } - return "ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")"; - } - }; - - /** - * Returns an ArrayBuffer compacted to contain this ByteBuffer's actual contents. Will implicitly - * {@link ByteBuffer#flip} the ByteBuffer if its offset is larger than its length. Will return a reference to - * the unmodified backing buffer if offset=0 and length=capacity unless forceCopy is set to true. - * @param {boolean=} forceCopy Forces the creation of a copy if set to true. Defaults to false. - * @return {ArrayBuffer} Compacted ArrayBuffer - * @expose - */ - ByteBuffer.prototype.toArrayBuffer = function(forceCopy) { - var b = this.clone(); - if (b.offset > b.length) { - b.flip(); - } - var copied = false; - if (b.offset > 0 || b.length < b.array.byteLength) { - b.compact(); // Will always create a new backing buffer because of the above condition - copied = true; - } - return forceCopy && !copied ? b.copy().array : b.array; - }; - - /** - * Returns a node Buffer compacted to contain this ByteBuffer's actual contents. Will implicitly - * {@link ByteBuffer#flip} the ByteBuffer if its offset is larger than its length. Will also copy all data (not - * a reference). - * @returns {Buffer} Compacted Buffer - * @throws {Error} If not running inside of node - * @expose - */ - ByteBuffer.prototype.toBuffer = function() { - if (Buffer) { - var offset = this.offset, length = this.length; - if (offset > length) { - var temp = offset; - offset = length; - length = temp; - } - var srcView = new Uint8Array(this.array); - return new Buffer(srcView.subarray(offset, length)); - } - throw(new Error("Conversion to Buffer is available under node.js only")); - }; - - /** - * Extends the ByteBuffer prototype with additional methods. - * @param {string} name Method name - * @param {!Function} func Prototype function - * @throws {Error} If the arguments are invalid - * @expose - */ - ByteBuffer.extend = function(name, func) { - if (typeof name === 'string' && typeof func === 'function') { - ByteBuffer.prototype[name] = func; - } else { - throw(new Error("Cannot extend prototype with "+name+"="+func+" (exptected string and function)")); - } - }; - - return ByteBuffer; - } - - - - // Enable module loading if available - if (typeof module !== 'undefined' && module["exports"]) { // CommonJS - /** @expose */ - module["exports"] = loadByteBuffer(require("long")); - } else if (typeof define !== 'undefined' && define["amd"]) { // AMD - define("ByteBuffer", ["Math/Long"], function(Long) { return loadByteBuffer(Long); }); - } else { // Shim - if (!global["dcodeIO"]) { - /** @expose */ - global["dcodeIO"] = {}; - } - /** @expose */ - global["dcodeIO"]["ByteBuffer"] = loadByteBuffer(dcodeIO.Long); - } - -})(this); - diff --git a/ByteBuffer.min.js b/ByteBuffer.min.js deleted file mode 100644 index d6821da..0000000 --- a/ByteBuffer.min.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - ByteBuffer.js (c) 2013 Daniel Wirtz - Released under the Apache License, Version 2.0 - see: https://github.com/dcodeIO/ByteBuffer.js for details -*/ -(function(n){function q(l){function d(a,b){a="undefined"!==typeof a?parseInt(a,10):d.DEFAULT_CAPACITY;1>a&&(a=d.DEFAULT_CAPACITY);this.array=3==arguments.length&&!0===arguments[2]?null:new ArrayBuffer(a);this.view=null!=this.array?new DataView(this.array):null;this.offset=0;this.markedOffset=-1;this.length=0;this.littleEndian="undefined"!=typeof b?!!b:!1}var m=null;if("function"===typeof require)try{var p=require("buffer"),m=p&&"function"===typeof p.Buffer&&"function"===typeof p.Buffer.isBuffer?p.Buffer: -null}catch(n){}d.DEFAULT_CAPACITY=16;d.LITTLE_ENDIAN=!0;d.BIG_ENDIAN=!1;d.Long=l;d.allocate=function(a,b){return new d(a,b)};d.wrap=function(a,b){if("string"===typeof a)return(new d).writeUTF8String(a).flip();var c;if(m&&m.isBuffer(a)){c=(new Uint8Array(a)).buffer;if(c===a){c=a;for(var f=new ArrayBuffer(c.length),e=new Uint8Array(f),g=0;ga)return!1;null==this.array&&(this.array=new ArrayBuffer(a),this.view=new DataView(this.array));if(this.array.byteLength< -a){var b=new Uint8Array(this.array);a=new ArrayBuffer(a);(new Uint8Array(a)).set(b);this.array=a;this.view=new DataView(a);return!0}return!1};d.prototype.slice=function(a,b){if(null==this.array)throw Error(this+" cannot be sliced: Already destroyed");if(b<=a)throw Error(this+" cannot be sliced: End ("+b+") is less than begin ("+a+")");if(0>a||a>this.array.byteLength||1>b||b>this.array.byteLength)throw Error(this+" cannot be sliced: Index out of bounds (0-"+this.array.byteLength+" -> "+a+"-"+b+")"); -var c=this.clone();c.offset=a;c.length=b;return c};d.prototype.sliceAndCompact=function(a,b){return d.wrap(this.slice(a,b).toArrayBuffer(!0))};d.prototype.ensureCapacity=function(a){return null==this.array?this.resize(a):this.array.byteLength=a?2*this.array.byteLength:a):!1};d.prototype.flip=function(){this.length=null==this.array?0:this.offset;this.offset=0;return this};d.prototype.mark=function(a){if(null==this.array)throw Error(this+" cannot be marked: Already destroyed"); -a="undefined"!==typeof a?parseInt(a,10):this.offset;if(0>a||a>this.array.byteLength)throw Error(this+" cannot be marked: Offset to mark is less than 0 or bigger than the capacity ("+this.array.byteLength+"): "+a);this.markedOffset=a;return this};d.prototype.reset=function(){0<=this.markedOffset?(this.offset=this.markedOffset,this.markedOffset=-1):this.length=this.offset=0;return this};d.prototype.clone=function(){var a=new d(-1,this.littleEndian,!0);a.array=this.array;a.view=this.view;a.offset=this.offset; -a.length=this.length;return a};d.prototype.copy=function(){if(null==this.array)return this.clone();var a=new d(this.array.byteLength,this.littleEndian),b=new Uint8Array(this.array);(new Uint8Array(a.array)).set(b);a.offset=this.offset;a.length=this.length;return a};d.prototype.remaining=function(){return null==this.array?0:this.length-this.offset};d.prototype.capacity=function(){return null!=this.array?this.array.byteLength:0};d.prototype.compact=function(){if(null==this.array)throw Error(this+" cannot be compacted: Already destroyed"); -this.offset>this.length&&this.flip();if(this.offset==this.length)throw Error(this+" cannot be compacted: Offset ("+this.offset+") is equal to its length ("+this.length+")");if(0==this.offset&&this.length==this.array.byteLength)return this;var a=new Uint8Array(this.array),b=new ArrayBuffer(this.length-this.offset);(new Uint8Array(b)).set(a.subarray(this.offset,this.length));this.array=b;this.offset=0;this.length=this.array.byteLength;return this};d.prototype.destroy=function(){if(null!=this.array)return this.view= -this.array=null,this.length=this.offset=0,this};d.prototype.reverse=function(){if(null==this.array)throw Error(this+" cannot be reversed: Already destroyed");Array.prototype.reverse.call(new Uint8Array(this.array));var a=this.offset;this.offset=this.array.byteLength-this.length;this.length=this.array.byteLength-a;this.view=new DataView(this.array);return this};d.prototype.append=function(a,b){a instanceof d||(a=d.wrap(a));if(null==a.array)throw Error(a+" cannot be appended to "+this+": Already destroyed"); -var c=a.length-a.offset;if(0==c)return this;0>c&&(a=a.clone().flip(),c=a.length-a.offset);b="undefined"!==typeof b?b:(this.offset+=c)-c;this.ensureCapacity(b+c);c=new Uint8Array(a.array);(new Uint8Array(this.array)).set(c.subarray(a.offset,a.length),b);return this};d.prototype.prepend=function(a,b){a instanceof d||(a=d.wrap(a));if(null==a.array)throw a+" cannot be prepended to "+this+": Already destroyed";var c=a.length-a.offset;if(0==c)return this;0>c&&(a=a.clone().flip(),c=a.length-a.offset);var f= -"undefined"===typeof b;b="undefined"!==typeof b?b:this.offset;var e=c-b;0=this.array.byteLength)throw Error("Cannot read int8 from "+ -this+" at "+a+": Capacity overflow");return this.view.getInt8(a)};d.prototype.writeByte=d.prototype.writeInt8;d.prototype.readByte=d.prototype.readInt8;d.prototype.writeUint8=function(a,b){b="undefined"!=typeof b?b:(this.offset+=1)-1;this.ensureCapacity(b+1);this.view.setUint8(b,a);return this};d.prototype.readUint8=function(a){a="undefined"!==typeof a?a:(this.offset+=1)-1;if(a+1>this.array.byteLength)throw Error("Cannot read uint8 from "+this+" at "+a+": Capacity overflow");return this.view.getUint8(a)}; -d.prototype.writeInt16=function(a,b){b="undefined"!==typeof b?b:(this.offset+=2)-2;this.ensureCapacity(b+2);this.view.setInt16(b,a,this.littleEndian);return this};d.prototype.readInt16=function(a){a="undefined"!==typeof a?a:(this.offset+=2)-2;if(a+2>this.array.byteLength)throw Error("Cannot read int16 from "+this+" at "+a+": Capacity overflow");return this.view.getInt16(a,this.littleEndian)};d.prototype.writeShort=d.prototype.writeInt16;d.prototype.readShort=d.prototype.readInt16;d.prototype.writeUint16= -function(a,b){b="undefined"!==typeof b?b:(this.offset+=2)-2;this.ensureCapacity(b+2);this.view.setUint16(b,a,this.littleEndian);return this};d.prototype.readUint16=function(a){a="undefined"!==typeof a?a:(this.offset+=2)-2;if(a+2>this.array.b)throw Error("Cannot read int16 from "+this+" at "+a+": Capacity overflow");return this.view.getUint16(a,this.littleEndian)};d.prototype.writeInt32=function(a,b){b="undefined"!==typeof b?b:(this.offset+=4)-4;this.ensureCapacity(b+4);this.view.setInt32(b,a,this.littleEndian); -return this};d.prototype.readInt32=function(a){a="undefined"!==typeof a?a:(this.offset+=4)-4;if(a+4>this.array.byteLength)throw Error("Cannot read int32 from "+this+" at "+a+": Capacity overflow");return this.view.getInt32(a,this.littleEndian)};d.prototype.writeInt=d.prototype.writeInt32;d.prototype.readInt=d.prototype.readInt32;d.prototype.writeUint32=function(a,b){b="undefined"!=typeof b?b:(this.offset+=4)-4;this.ensureCapacity(b+4);this.view.setUint32(b,a,this.littleEndian);return this};d.prototype.readUint32= -function(a){a="undefined"!==typeof a?a:(this.offset+=4)-4;if(a+4>this.array.byteLength)throw Error("Cannot read uint32 from "+this+" at "+a+": Capacity overflow");return this.view.getUint32(a,this.littleEndian)};d.prototype.writeFloat32=function(a,b){b="undefined"!==typeof b?b:(this.offset+=4)-4;this.ensureCapacity(b+4);this.view.setFloat32(b,a,this.littleEndian);return this};d.prototype.readFloat32=function(a){a="undefined"!==typeof a?a:(this.offset+=4)-4;if(null==this.array||a+4>this.array.byteLength)throw Error("Cannot read float32 from "+ -this+" at "+a+": Capacity overflow");return this.view.getFloat32(a,this.littleEndian)};d.prototype.writeFloat=d.prototype.writeFloat32;d.prototype.readFloat=d.prototype.readFloat32;d.prototype.writeFloat64=function(a,b){b="undefined"!==typeof b?b:(this.offset+=8)-8;this.ensureCapacity(b+8);this.view.setFloat64(b,a,this.littleEndian);return this};d.prototype.readFloat64=function(a){a="undefined"!==typeof a?a:(this.offset+=8)-8;if(null==this.array||a+8>this.array.byteLength)throw Error("Cannot read float64 from "+ -this+" at "+a+": Capacity overflow");return this.view.getFloat64(a,this.littleEndian)};d.prototype.writeDouble=d.prototype.writeFloat64;d.prototype.readDouble=d.prototype.readFloat64;d.prototype.writeInt64=function(a,b){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details");b="undefined"!==typeof b?b:(this.offset+=8)-8;"object"===typeof a&&a instanceof l||(a=l.fromNumber(a,!1));this.ensureCapacity(b+8);this.littleEndian?(this.view.setInt32(b, -a.getLowBits(),!0),this.view.setInt32(b+4,a.getHighBits(),!0)):(this.view.setInt32(b,a.getHighBits(),!1),this.view.setInt32(b+4,a.getLowBits(),!1));return this};d.prototype.readInt64=function(a){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details");a="undefined"!==typeof a?a:(this.offset+=8)-8;if(null==this.array||a+8>this.array.byteLength)throw this.offset-=8,Error("Cannot read int64 from "+this+" at "+a+": Capacity overflow"); -return this.littleEndian?l.fromBits(this.view.getInt32(a,!0),this.view.getInt32(a+4,!0),!1):l.fromBits(this.view.getInt32(a+4,!1),this.view.getInt32(a,!1),!1)};d.prototype.writeUint64=function(a,b){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details");b="undefined"!==typeof b?b:(this.offset+=8)-8;"object"===typeof a&&a instanceof l||(a=l.fromNumber(a,!0));this.ensureCapacity(b+8);this.littleEndian?(this.view.setUint32(b, -a.getLowBitsUnsigned(),!0),this.view.setUint32(b+4,a.getHighBitsUnsigned(),!0)):(this.view.setUint32(b,a.getHighBitsUnsigned(),!1),this.view.setUint32(b+4,a.getLowBitsUnsigned(),!1));return this};d.prototype.readUint64=function(a){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details");a="undefined"!==typeof a?a:(this.offset+=8)-8;if(null==this.array||a+8>this.array.byteLength)throw this.offset-=8,Error("Cannot read int64 from "+ -this+" at "+a+": Capacity overflow");return this.littleEndian?l.fromBits(this.view.getUint32(a,!0),this.view.getUint32(a+4,!0),!0):l.fromBits(this.view.getUint32(a+4,!1),this.view.getUint32(a,!1),!0)};d.prototype.writeLong=d.prototype.writeInt64;d.prototype.readLong=d.prototype.readInt64;d.MAX_VARINT32_BYTES=5;d.prototype.writeVarint32=function(a,b){var c="undefined"===typeof b;b="undefined"!==typeof b?b:this.offset;a>>>=0;this.ensureCapacity(b+d.calculateVarint32(a));var f=this.view,e=0;f.setUint8(b, -a|128);128<=a?(f.setUint8(b+1,a>>7|128),16384<=a?(f.setUint8(b+2,a>>14|128),2097152<=a?(f.setUint8(b+3,a>>21|128),268435456<=a?(f.setUint8(b+4,a>>28&127),e=5):(f.setUint8(b+3,f.getUint8(b+3)&127),e=4)):(f.setUint8(b+2,f.getUint8(b+2)&127),e=3)):(f.setUint8(b+1,f.getUint8(b+1)&127),e=2)):(f.setUint8(b,f.getUint8(b)&127),e=1);return c?(this.offset+=e,this):e};d.prototype.readVarint32=function(a){var b="undefined"===typeof a;a="undefined"!==typeof a?a:this.offset;var c=0,f,e=this.view,g=0;do f=e.getUint8(a+ -c),c>>0),++c;while(f&128);g|=0;return b?(this.offset+=c,g):{value:g,length:c}};d.prototype.writeZigZagVarint32=function(a,b){return this.writeVarint32(d.zigZagEncode32(a),b)};d.prototype.readZigZagVarint32=function(a){a=this.readVarint32(a);return"object"===typeof a?(a.value=d.zigZagDecode32(a.value),a):d.zigZagDecode32(a)};d.MAX_VARINT64_BYTES=10;d.prototype.writeVarint64=function(a,b){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details"); -var c="undefined"===typeof b;b="undefined"!==typeof b?b:this.offset;"object"===typeof a&&a instanceof l||(a=l.fromNumber(a,!1));var f=a.toInt()>>>0,e=a.shiftRightUnsigned(28).toInt()>>>0,g=a.shiftRightUnsigned(56).toInt()>>>0,k=d.calculateVarint64(a);this.ensureCapacity(b+k);var h=this.view;switch(k){case 10:h.setUint8(b+9,g>>>7|128);case 9:h.setUint8(b+8,g|128);case 8:h.setUint8(b+7,e>>>21|128);case 7:h.setUint8(b+6,e>>>14|128);case 6:h.setUint8(b+5,e>>>7|128);case 5:h.setUint8(b+4,e|128);case 4:h.setUint8(b+ -3,f>>>21|128);case 3:h.setUint8(b+2,f>>>14|128);case 2:h.setUint8(b+1,f>>>7|128);case 1:h.setUint8(b+0,f|128)}h.setUint8(b+k-1,h.getUint8(b+k-1)&127);return c?(this.offset+=k,this):k};d.prototype.readVarint64=function(a){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details");var b="undefined"===typeof a,c=a="undefined"!==typeof a?a:this.offset,d=this.view,e,g=0,k=0,h;h=d.getUint8(a++);e=h&127;if(h&128&&(h=d.getUint8(a++), -e|=(h&127)<<7,h&128&&(h=d.getUint8(a++),e|=(h&127)<<14,h&128&&(h=d.getUint8(a++),e|=(h&127)<<21,h&128&&(h=d.getUint8(a++),g=h&127,h&128&&(h=d.getUint8(a++),g|=(h&127)<<7,h&128&&(h=d.getUint8(a++),g|=(h&127)<<14,h&128&&(h=d.getUint8(a++),g|=(h&127)<<21,h&128&&(h=d.getUint8(a++),k=h&127,h&128&&(h=d.getUint8(a++),k|=(h&127)<<7,h&128))))))))))throw Error("Data must be corrupt: Buffer overrun");d=l.from28Bits(e,g,k,!1);return b?(this.offset=a,d):{value:d,length:a-c}};d.prototype.writeZigZagVarint64=function(a, -b){return this.writeVarint64(d.zigZagEncode64(a),b)};d.prototype.readZigZagVarint64=function(a){a=this.readVarint64(a);return"object"!==typeof a||a instanceof l?d.zigZagDecode64(a):(a.value=d.zigZagDecode64(a.value),a)};d.prototype.writeVarint=d.prototype.writeVarint32;d.prototype.readVarint=d.prototype.readVarint32;d.prototype.writeZigZagVarint=d.prototype.writeZigZagVarint32;d.prototype.readZigZagVarint=d.prototype.readZigZagVarint32;d.calculateVarint32=function(a){a>>>=0;return 128>a?1:16384>a? -2:2097152>a?3:268435456>a?4:5};d.calculateVarint64=function(a){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details");"object"===typeof a&&a instanceof l||(a=l.fromNumber(a,!1));var b=a.toInt()>>>0,c=a.shiftRightUnsigned(28).toInt()>>>0;a=a.shiftRightUnsigned(56).toInt()>>>0;return 0==a?0==c?16384>b?128>b?1:2:2097152>b?3:4:16384>c?128>c?5:6:2097152>c?7:8:128>a?9:10};d.zigZagEncode32=function(a){return((a|=0)<<1^a>>31)>>>0}; -d.zigZagDecode32=function(a){return a>>>1^-(a&1)|0};d.zigZagEncode64=function(a){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details");"object"===typeof a&&a instanceof l?a.unsigned&&(a=a.toSigned()):a=l.fromNumber(a,!1);return a.shiftLeft(1).xor(a.shiftRight(63)).toUnsigned()};d.zigZagDecode64=function(a){if(!l)throw Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details"); -"object"===typeof a&&a instanceof l?a.unsigned||(a=a.toUnsigned()):a=l.fromNumber(a,!0);return a.shiftRightUnsigned(1).xor(a.and(l.ONE).toSigned().negate()).toSigned()};d.decodeUTF8Char=function(a,b){var c=a.readUint8(b),d,e,g,k,h,l=b;if(0==(c&128))b+=1;else if(192==(c&224))d=a.readUint8(b+1),c=(c&31)<<6|d&63,b+=2;else if(224==(c&240))d=a.readUint8(b+1),e=a.readUint8(b+2),c=(c&15)<<12|(d&63)<<6|e&63,b+=3;else if(240==(c&248))d=a.readUint8(b+1),e=a.readUint8(b+2),g=a.readUint8(b+3),c=(c&7)<<18|(d& -63)<<12|(e&63)<<6|g&63,b+=4;else if(248==(c&252))d=a.readUint8(b+1),e=a.readUint8(b+2),g=a.readUint8(b+3),k=a.readUint8(b+4),c=(c&3)<<24|(d&63)<<18|(e&63)<<12|(g&63)<<6|k&63,b+=5;else if(252==(c&254))d=a.readUint8(b+1),e=a.readUint8(b+2),g=a.readUint8(b+3),k=a.readUint8(b+4),h=a.readUint8(b+5),c=(c&1)<<30|(d&63)<<24|(e&63)<<18|(g&63)<<12|(k&63)<<6|h&63,b+=6;else throw Error("Cannot decode UTF8 character at offset "+b+": charCode (0x"+c.toString(16)+") is invalid");return{"char":c,length:b-l}};d.encodeUTF8Char= -function(a,b,c){var d=c;if(0>a)throw Error("Cannot encode UTF8 character: charCode ("+a+") is negative");if(128>a)b.writeUint8(a&127,c),c+=1;else if(2048>a)b.writeUint8(a>>6&31|192,c).writeUint8(a&63|128,c+1),c+=2;else if(65536>a)b.writeUint8(a>>12&15|224,c).writeUint8(a>>6&63|128,c+1).writeUint8(a&63|128,c+2),c+=3;else if(2097152>a)b.writeUint8(a>>18&7|240,c).writeUint8(a>>12&63|128,c+1).writeUint8(a>>6&63|128,c+2).writeUint8(a&63|128,c+3),c+=4;else if(67108864>a)b.writeUint8(a>>24&3|248,c).writeUint8(a>> -18&63|128,c+1).writeUint8(a>>12&63|128,c+2).writeUint8(a>>6&63|128,c+3).writeUint8(a&63|128,c+4),c+=5;else if(2147483648>a)b.writeUint8(a>>30&1|252,c).writeUint8(a>>24&63|128,c+1).writeUint8(a>>18&63|128,c+2).writeUint8(a>>12&63|128,c+3).writeUint8(a>>6&63|128,c+4).writeUint8(a&63|128,c+5),c+=6;else throw Error("Cannot encode UTF8 character: charCode (0x"+a.toString(16)+") is too large (>= 0x80000000)");return c-d};d.calculateUTF8Char=function(a){if(0>a)throw Error("Cannot calculate length of UTF8 character: charCode ("+ -a+") is negative");if(128>a)return 1;if(2048>a)return 2;if(65536>a)return 3;if(2097152>a)return 4;if(67108864>a)return 5;if(2147483648>a)return 6;throw Error("Cannot calculate length of UTF8 character: charCode (0x"+a.toString(16)+") is too large (>= 0x80000000)");};d.a=function(a){a=""+a;for(var b=0,c=0;cg?a.readUint8(g++):0,f=a.length>g?a.readUint8(g++):0,e=b<<16|c<<8|f,b=e>>18&63,c=e>>12&63,f=e>>6&63,e&=63,h[k++]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(b)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(c)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(f)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(e);while(gb||0>c||0>e||0>g)throw Error("Illegal argument: Not a valid base64 encoded string");f=b<<18|c<<12|e<<6|g;b=f>>16&255;c=f>>8&255;f&=255;64==e?h.writeUint8(b):64==g?h.writeUint8(b).writeUint8(c):h.writeUint8(b).writeUint8(c).writeUint8(f)}while(ka?"+":"")+b-a)+" bytes");return c?(this.offset=b,e):{string:e,length:b-g}};d.prototype.writeLString=function(a,b){a=""+a;var c="undefined"===typeof b;b="undefined"!==typeof b?b:this.offset;var f=d.encodeUTF8Char(a.length,this,b),f=f+this.writeUTF8String(a,b+f);return c?(this.offset+=f,this):f};d.prototype.readLString=function(a){var b="undefined"=== -typeof a;a="undefined"!==typeof a?a:this.offset;var c=d.decodeUTF8Char(this,a);a=this.readUTF8String(c["char"],a+c.length);return b?(this.offset+=c.length+a.length,a.string):{string:a.string,length:c.length+a.length}};d.prototype.writeVString=function(a,b){a=""+a;var c="undefined"===typeof b;b="undefined"!==typeof b?b:this.offset;var f=this.writeVarint32(d.a(a),b),f=f+this.writeUTF8String(a,b+f);return c?(this.offset+=f,this):f};d.prototype.readVString=function(a){var b="undefined"===typeof a;a="undefined"!== -typeof a?a:this.offset;var c=this.readVarint32(a);a=this.readUTF8StringBytes(c.value,a+c.length);return b?(this.offset+=c.length+a.length,a.string):{string:a.string,length:c.length+a.length}};d.prototype.writeCString=function(a,b){var c="undefined"===typeof b;b="undefined"!==typeof b?b:this.offset;var d=this.writeUTF8String(""+a,b);this.writeUint8(0,b+d);return c?(this.offset+=d+1,this):d+1};d.prototype.readCString=function(a){var b="undefined"===typeof a;a="undefined"!==typeof a?a:this.offset;var c, -f="",e=a;do c=d.decodeUTF8Char(this,a),a+=c.length,0!=c["char"]&&(f+=String.fromCharCode(c["char"]));while(0!=c["char"]);return b?(this.offset=a,f):{string:f,length:a-e}};d.prototype.writeJSON=function(a,b,c){c="function"===typeof c?c:JSON.stringify;return this.writeLString(c(a),b)};d.prototype.readJSON=function(a,b){b="function"===typeof b?b:JSON.parse;var c=this.readLString(a);return"string"===typeof c?b(c):{data:b(c.string),length:c.length}};d.prototype.printDebug=function(a){for(var b=(null!= -this.array?"ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")":"ByteBuffer(DESTROYED)")+"\n-------------------------------------------------------------------\n",c=this.toHex(16,!0),d=this.toASCII(16,!0),e=0;ea&&(a=16);for(var c="",d=[],e=this.view,c=0==this.offset&&0==this.length?c+"|":0==this.length?c+">":0==this.offset?c+"<":c+" ",g=0;gk.length&&(k="0"+k);c+=k;c=g+1==this.offset&&g+1==this.length?c+"|":g+1==this.offset?c+"<":g+1==this.length?c+">":c+" "}if(b)for(;c.length<3*a+1;)c+=" ";d.push(c);return b?d:d.join("\n")};d.prototype.toASCII=function(a,b){if(null==this.array)return""; -b=!!b;a="undefined"!==typeof a?parseInt(a,10):16;1>a&&(a=16);for(var c="",d=[],e=this.view,g=0;gk?String.fromCharCode(k):".",c=c+k}d.push(c);return b?d:d.join("\n")+"\n"};d.prototype.toBase64=function(){return null==this.array||this.offset>=this.length?"":d.encode64(this)};d.prototype.toUTF8=function(){return null==this.array||this.offset>=this.length?"":this.readUTF8StringBytes(this.length-this.offset,this.offset).c}; -d.prototype.toString=function(a){switch(a||"debug"){case "utf8":return this.toUTF8();case "base64":return this.toBase64();default:return null==this.array?"ByteBuffer(DESTROYED)":"ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")"}};d.prototype.toArrayBuffer=function(a){var b=this.clone();b.offset>b.length&&b.flip();var c=!1;if(0b)var c=a,a=b,b=c;c=new Uint8Array(this.array);return new m(c.subarray(a,b))}throw Error("Conversion to Buffer is available under node.js only");};d.extend=function(a,b){if("string"===typeof a&&"function"===typeof b)d.prototype[a]=b;else throw Error("Cannot extend prototype with "+a+"="+b+" (exptected string and function)");};return d}"undefined"!==typeof module&&module.exports?module.exports=q(require("long")):"undefined"!== -typeof define&&define.amd?define("ByteBuffer",["Math/Long"],function(l){return q(l)}):(n.dcodeIO||(n.dcodeIO={}),n.dcodeIO.ByteBuffer=q(dcodeIO.Long))})(this); diff --git a/ByteBuffer.min.map b/ByteBuffer.min.map deleted file mode 100644 index 8b4a1f3..0000000 --- a/ByteBuffer.min.map +++ /dev/null @@ -1,8 +0,0 @@ -{ -"version":3, -"file":"", -"lineCount":54, -"mappings":"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", -"sources":["ByteBuffer.js"], -"names":["global","loadByteBuffer","Long","ByteBuffer","capacity","littleEndian","parseInt","DEFAULT_CAPACITY","array","arguments","length","ArrayBuffer","view","DataView","offset","markedOffset","Buffer","require","nodeBuffer","e","LITTLE_ENDIAN","BIG_ENDIAN","allocate","ByteBuffer.allocate","wrap","ByteBuffer.wrap","buffer","writeUTF8String","flip","b","isBuffer","Uint8Array","ab","i","Error","clone","constructor","name","byteLength","prototype","LE","ByteBuffer.prototype.LE","BE","ByteBuffer.prototype.BE","resize","ByteBuffer.prototype.resize","srcView","dst","set","dstView","slice","ByteBuffer.prototype.slice","begin","end","sliceAndCompact","ByteBuffer.prototype.sliceAndCompact","toArrayBuffer","ensureCapacity","ByteBuffer.prototype.ensureCapacity","ByteBuffer.prototype.flip","mark","ByteBuffer.prototype.mark","reset","ByteBuffer.prototype.reset","ByteBuffer.prototype.clone","copy","ByteBuffer.prototype.copy","src","remaining","ByteBuffer.prototype.remaining","ByteBuffer.prototype.capacity","compact","ByteBuffer.prototype.compact","subarray","destroy","ByteBuffer.prototype.destroy","reverse","ByteBuffer.prototype.reverse","Array","call","o","append","ByteBuffer.prototype.append","n","prepend","ByteBuffer.prototype.prepend","modify","diff","writeInt8","ByteBuffer.prototype.writeInt8","value","setInt8","readInt8","ByteBuffer.prototype.readInt8","getInt8","writeByte","readByte","writeUint8","ByteBuffer.prototype.writeUint8","setUint8","readUint8","ByteBuffer.prototype.readUint8","getUint8","writeInt16","ByteBuffer.prototype.writeInt16","setInt16","readInt16","ByteBuffer.prototype.readInt16","getInt16","writeShort","readShort","writeUint16","ByteBuffer.prototype.writeUint16","setUint16","readUint16","ByteBuffer.prototype.readUint16","byteLEngth","getUint16","writeInt32","ByteBuffer.prototype.writeInt32","setInt32","readInt32","ByteBuffer.prototype.readInt32","getInt32","writeInt","readInt","writeUint32","ByteBuffer.prototype.writeUint32","setUint32","readUint32","ByteBuffer.prototype.readUint32","getUint32","writeFloat32","ByteBuffer.prototype.writeFloat32","setFloat32","readFloat32","ByteBuffer.prototype.readFloat32","getFloat32","writeFloat","readFloat","writeFloat64","ByteBuffer.prototype.writeFloat64","setFloat64","readFloat64","ByteBuffer.prototype.readFloat64","getFloat64","writeDouble","readDouble","writeInt64","ByteBuffer.prototype.writeInt64","fromNumber","getLowBits","getHighBits","readInt64","ByteBuffer.prototype.readInt64","fromBits","writeUint64","ByteBuffer.prototype.writeUint64","getLowBitsUnsigned","getHighBitsUnsigned","readUint64","ByteBuffer.prototype.readUint64","writeLong","readLong","MAX_VARINT32_BYTES","writeVarint32","ByteBuffer.prototype.writeVarint32","advance","calculateVarint32","size","readVarint32","ByteBuffer.prototype.readVarint32","count","writeZigZagVarint32","ByteBuffer.prototype.writeZigZagVarint32","zigZagEncode32","readZigZagVarint32","ByteBuffer.prototype.readZigZagVarint32","dec","zigZagDecode32","MAX_VARINT64_BYTES","writeVarint64","ByteBuffer.prototype.writeVarint64","part0","toInt","part1","shiftRightUnsigned","part2","calculateVarint64","readVarint64","ByteBuffer.prototype.readVarint64","start","from28Bits","writeZigZagVarint64","ByteBuffer.prototype.writeZigZagVarint64","zigZagEncode64","readZigZagVarint64","ByteBuffer.prototype.readZigZagVarint64","zigZagDecode64","writeVarint","readVarint","writeZigZagVarint","readZigZagVarint","ByteBuffer.calculateVarint32","TWO_PWR_7_DBL","TWO_PWR_14_DBL","TWO_PWR_21_DBL","TWO_PWR_28_DBL","ByteBuffer.calculateVarint64","ByteBuffer.zigZagEncode32","ByteBuffer.zigZagDecode32","ByteBuffer.zigZagEncode64","unsigned","toSigned","shiftLeft","xor","shiftRight","toUnsigned","ByteBuffer.zigZagDecode64","and","ONE","negate","decodeUTF8Char","ByteBuffer.decodeUTF8Char","a","c","d","f","charCode","toString","encodeUTF8Char","ByteBuffer.encodeUTF8Char","calculateUTF8Char","ByteBuffer.calculateUTF8Char","calculateUTF8String","ByteBuffer.calculateUTF8String","str","bytes","charCodeAt","encode64","ByteBuffer.encode64","bb","o1","o2","o3","h4","oi","out","bits","h1","h2","h3","b64","charAt","enc","join","r","decode64","ByteBuffer.decode64","Math","ceil","indexOf","ByteBuffer.prototype.writeUTF8String","encLen","readUTF8String","ByteBuffer.prototype.readUTF8String","chars","result","String","fromCharCode","readUTF8StringBytes","ByteBuffer.prototype.readUTF8StringBytes","writeLString","ByteBuffer.prototype.writeLString","readLString","ByteBuffer.prototype.readLString","lenDec","writeVString","ByteBuffer.prototype.writeVString","readVString","ByteBuffer.prototype.readVString","writeCString","ByteBuffer.prototype.writeCString","readCString","ByteBuffer.prototype.readCString","writeJSON","ByteBuffer.prototype.writeJSON","data","stringify","JSON","readJSON","ByteBuffer.prototype.readJSON","parse","printDebug","ByteBuffer.prototype.printDebug","s","h","toHex","toASCII","console","log","ByteBuffer.prototype.toHex","asArray","lines","push","val","toUpperCase","ByteBuffer.prototype.toASCII","toBase64","ByteBuffer.prototype.toBase64","toUTF8","ByteBuffer.prototype.toUTF8","string","ByteBuffer.prototype.toString","ByteBuffer.prototype.toArrayBuffer","forceCopy","copied","toBuffer","ByteBuffer.prototype.toBuffer","temp","extend","ByteBuffer.extend","func","module","define","dcodeIO"] -} diff --git a/ByteBuffer.noexpose.js b/ByteBuffer.noexpose.js deleted file mode 100644 index 814a6b8..0000000 --- a/ByteBuffer.noexpose.js +++ /dev/null @@ -1,2033 +0,0 @@ -/* - Copyright 2013 Daniel Wirtz - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/** - * @license ByteBuffer.js (c) 2013 Daniel Wirtz - * Released under the Apache License, Version 2.0 - * see: https://github.com/dcodeIO/ByteBuffer.js for details - */ -(function(global) { - "use strict"; - - // Note that this library carefully avoids using the array access operator - // (i.e. buffer[x]) on ArrayBufferView subclasses (e.g. Uint8Array), and - // uses DataView instead. This is required for IE 8 compatibility. - - function loadByteBuffer(Long) { - - // Support node's Buffer if available, http://nodejs.org/api/buffer.html - var Buffer = null; - if (typeof require === 'function') { - try { - var nodeBuffer = require("buffer"); - Buffer = nodeBuffer && typeof nodeBuffer['Buffer'] === 'function' && typeof nodeBuffer['Buffer']['isBuffer'] === 'function' - ? nodeBuffer['Buffer'] : null; - } catch (e) {} - } - - /** - * Constructs a new ByteBuffer. - * @exports ByteBuffer - * @class Provides a Java-like, Netty-inspired ByteBuffer implementation using typed arrays. It also tries to - * abstract a bit of the complexity away by providing convenience methods for those who just want to write stuff - * without caring about signed, unsigned and the actual bit sizes. - * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to false. - * @constructor - */ - var ByteBuffer = function(capacity, littleEndian) { - - capacity = typeof capacity !== 'undefined' ? parseInt(capacity, 10) : ByteBuffer.DEFAULT_CAPACITY; - if (capacity < 1) capacity = ByteBuffer.DEFAULT_CAPACITY; - - /** - * Underlying ArrayBuffer. - * @type {ArrayBuffer} - */ - this.array = arguments.length == 3 && arguments[2] === true ? null : new ArrayBuffer(capacity); - - /** - * DataView to mess with the ArrayBuffer. - * @type {DataView} - */ - this.view = this.array != null ? new DataView(this.array) : null; - /** - * Current read/write offset. Length- and capacity-independent index. Contents are the bytes between offset and - * length, which are both absolute indexes. There is no capacity property, use {@link ByteBuffer#capacity} - * instead. - * @type {number} - */ - this.offset = 0; - - /** - * Marked offset set through {@link ByteBuffer#mark}. Evaluates to -1 if there is no marked offset. - * @type {number} - */ - this.markedOffset = -1; - - /** - * Length of the contained data. Offset- and capacity-independent index. Contents are the bytes between offset and - * length, which are both absolute indexes. There is no capacity property, use {@link ByteBuffer#capacity} - * instead. - * @type {number} - */ - this.length = 0; - - /** - * Whether to use little endian multi byte values. - * @type {boolean} - */ - this.littleEndian = typeof littleEndian != 'undefined' ? !!littleEndian : false; - }; - - /** - * Default buffer capacity of 16 if nothing else is stated. The ByteBuffer will be automatically resized by a factor - * of 2 if required. - * @type {number} - * @const - */ - ByteBuffer.DEFAULT_CAPACITY = 16; - - /** - * Little endian constant for usage in constructors instead of a boolean value. Evaluates to true. - * @type {boolean} - * @const - */ - ByteBuffer.LITTLE_ENDIAN = true; - - /** - * Big endian constant for usage in constructors instead of a boolean value. Evaluates to false. - * @type {boolean} - * @const - */ - ByteBuffer.BIG_ENDIAN = false; - - /** - * Long class for int64 support. May be undefined if the Long class has not been loaded and int64 support is - * not available. - * @type {?Long} - * @const - */ - ByteBuffer.Long = Long; - - /** - * Allocates a new ByteBuffer. - * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to true. - * @return {ByteBuffer} - */ - ByteBuffer.allocate = function(capacity, littleEndian) { - return new ByteBuffer(capacity, littleEndian); - }; - - /** - * Converts a node.js <= 0.8 Buffer to an ArrayBuffer. - * @param {Buffer} buffer Buffer to convert - * @return {ArrayBuffer} Converted buffer - * @private - */ - function toArrayBuffer(buffer) { - var ab = new ArrayBuffer(buffer.length); - var view = new Uint8Array(ab); - for (var i = 0; i < buffer.length; ++i) { - view[i] = buffer[i]; - } - return ab; - } - - /** - * Wraps an ArrayBuffer, any object containing an ArrayBuffer or a string. Sets the created ByteBuffer's offset to 0 - * and its length to the wrapped objects byte length. - * @param {ArrayBuffer|Buffer|string|{array: ArrayBuffer}|{buffer: ArrayBuffer}|string} buffer ArrayBuffer, any object with an .array or .buffer property or a string to wrap - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to true. - * @return {ByteBuffer} - * @throws {Error} If the specified object cannot be wrapped - */ - ByteBuffer.wrap = function(buffer, littleEndian) { - // Wrap a string - if (typeof buffer === 'string') { - return new ByteBuffer().writeUTF8String(buffer).flip(); - } - var b; - // Wrap Buffer - if (Buffer && Buffer.isBuffer(buffer)) { - b = new Uint8Array(buffer).buffer; // noop on node <= 0.8 - buffer = (b === buffer) ? toArrayBuffer(buffer) : b; - } - // Refuse to wrap anything that's null or not an object - if (buffer === null || typeof buffer !== 'object') { - throw(new Error("Cannot wrap null or non-object")); - } - // Wrap ByteBuffer by cloning (preserve offsets) - if (buffer instanceof ByteBuffer) { - return buffer.clone(); - } - // Wrap any object that is or contains an ArrayBuffer - if (!!buffer["array"]) { - buffer = buffer["array"]; - } else if (!!buffer["buffer"]) { - buffer = buffer["buffer"]; - } - if (!(buffer instanceof ArrayBuffer)) { - throw(new Error("Cannot wrap buffer of type "+typeof(buffer)+", "+buffer.constructor.name)); - } - b = new ByteBuffer(0, littleEndian, /* shadow copy */ true); - b.array = buffer; - b.view = new DataView(b.array); - b.offset = 0; - b.length = buffer.byteLength; - return b; - }; - - /** - * Switches to little endian byte order. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.LE = function() { - this.littleEndian = true; - return this; - }; - - /** - * Switches to bid endian byte order. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.BE = function() { - this.littleEndian = false; - return this; - }; - - /** - * Resizes the ByteBuffer to the given capacity. - * @param {number} capacity New capacity - * @return {boolean} true if actually resized, false if already that large or larger - */ - ByteBuffer.prototype.resize = function(capacity) { - if (capacity < 1) return false; - if (this.array == null) { // Silently recreate - this.array = new ArrayBuffer(capacity); - this.view = new DataView(this.array); - } - if (this.array.byteLength < capacity) { - var src = this.array; - var srcView = new Uint8Array(src); - var dst = new ArrayBuffer(capacity); - var dstView = new Uint8Array(dst); - dstView.set(srcView); - this.array = dst; - this.view = new DataView(dst); - return true; - } - return false; - }; - - /** - * Slices the ByteBuffer. This is independent of the ByteBuffer's actual offsets. Does not compact the underlying - * ArrayBuffer (use {@link ByteBuffer#compact} and maybe {@link ByteBuffer.wrap} instead). - * @param {number} begin Begin offset - * @param {number} end End offset - * @return {ByteBuffer} Clone of this ByteBuffer with the specified slicing applied, backed by the same ArrayBuffer - * @throws {Error} If the buffer cannot be sliced - */ - ByteBuffer.prototype.slice = function(begin, end) { - if (this.array == null) { - throw(new Error(this+" cannot be sliced: Already destroyed")); - } - if (end <= begin) { - throw(new Error(this+" cannot be sliced: End ("+end+") is less than begin ("+begin+")")); - } - if (begin < 0 || begin > this.array.byteLength || end < 1 || end > this.array.byteLength) { - throw(new Error(this+" cannot be sliced: Index out of bounds (0-"+this.array.byteLength+" -> "+begin+"-"+end+")")); - } - var b = this.clone(); - b.offset = begin; - b.length = end; - return b; - }; - - /** - * Slices and compacts the ByteBuffer. The resulting ByteBuffer will have its own ArrayBuffer with the compacted contents - * of this ByteBuffer's contents. - * @param {number} begin Begin offset - * @param {number} end End offset - * @return {ByteBuffer} - * @throws {Error} If the buffer cannot be sliced - */ - ByteBuffer.prototype.sliceAndCompact = function(begin, end) { - return ByteBuffer.wrap(this.slice(begin,end).toArrayBuffer(true)); - }; - - /** - * Makes sure that the specified capacity is available. If the current capacity is exceeded, it will be doubled. If - * double the previous capacity is less than the required capacity, the required capacity will be used. - * @param {number} capacity Required capacity - * @return {boolean} true if actually resized, false if already that large or larger - */ - ByteBuffer.prototype.ensureCapacity = function(capacity) { - if (this.array == null) { - return this.resize(capacity); - } - if (this.array.byteLength < capacity) return this.resize(this.array.byteLength*2 >= capacity ? this.array.byteLength*2 : capacity); - return false; - }; - - /** - * Makes the buffer ready for a new sequence of write or relative read operations. Sets length=offset and offset=0. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.flip = function() { - this.length = this.array == null ? 0 : this.offset; - this.offset = 0; - return this; - }; - - /** - * Marks the current offset in {@link ByteBuffer#markedOffset}. - * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}. - * @return {ByteBuffer} this - * @throws {Error} If the mark cannot be set - * @see ByteBuffer#reset - */ - ByteBuffer.prototype.mark = function(offset) { - if (this.array == null) { - throw(new Error(this+" cannot be marked: Already destroyed")); - } - offset = typeof offset !== 'undefined' ? parseInt(offset, 10) : this.offset; - if (offset < 0 || offset > this.array.byteLength) { - throw(new Error(this+" cannot be marked: Offset to mark is less than 0 or bigger than the capacity ("+this.array.byteLength+"): "+offset)); - } - this.markedOffset = offset; - return this; - }; - - /** - * Resets the ByteBuffer. If an offset has been marked through {@link ByteBuffer#mark} before, the offset will be - * set to the marked offset and the marked offset will be discarded. Length will not be altered. If there is no - * marked offset, sets offset=0 and length=0. - * @return {ByteBuffer} this - * @see ByteBuffer#mark - */ - ByteBuffer.prototype.reset = function() { - if (this.markedOffset >= 0) { - this.offset = this.markedOffset; - this.markedOffset = -1; - } else { - this.offset = 0; - this.length = 0; - } - return this; - }; - - /** - * Clones this ByteBuffer. The returned cloned ByteBuffer shares the same ArrayBuffer but will have its own offsets. - * @return {ByteBuffer} - */ - ByteBuffer.prototype.clone = function() { - // When cloning, an undocumented third parameter is used to set array and view manually. - var b = new ByteBuffer(-1, this.littleEndian, /* shadow copy */ true); - b.array = this.array; - b.view = this.view; - b.offset = this.offset; - b.length = this.length; - return b; - }; - - /** - * Copies this ByteBuffer. The returned copied ByteBuffer has its own ArrayBuffer and uses the same offsets as this one. - * @return {ByteBuffer} - */ - ByteBuffer.prototype.copy = function() { - if (this.array == null) { - return this.clone(); - } - var b = new ByteBuffer(this.array.byteLength, this.littleEndian); - var src = new Uint8Array(this.array); - var dst = new Uint8Array(b.array); - dst.set(src); - b.offset = this.offset; - b.length = this.length; - return b; - }; - - /** - * Gets the number of remaining readable bytes. Contents are the bytes between offset and length, so this returns - * length-offset. - * @return {number} Remaining readable bytes (may be negative if offset is larger than length) - */ - ByteBuffer.prototype.remaining = function() { - if (this.array == null) return 0; - return this.length - this.offset; - }; - - /** - * Gets the capacity of the backing buffer. May be larger but not less than the contents actual length. Contents are the - * bytes between offset and length, which is independent of the actual capacity. - * @return {number} Capacity of the backing buffer or 0 if destroyed - */ - ByteBuffer.prototype.capacity = function() { - return this.array != null ? this.array.byteLength : 0; - }; - - /** - * Compacts the ByteBuffer to be backed by an ArrayBuffer of its actual length. Will {@link ByteBuffer#flip} the - * ByteBuffer if its offset is larger than its length. If the ByteBuffer's offset is less than its length, only the - * portion between its offset and length will be contained in the compacted backing buffer. Will set offset=0 and - * length=capacity. Will do nothing but flipping, if required, if already compacted. - * @return {ByteBuffer} this - * @throws {Error} If the buffer cannot be compacted - */ - ByteBuffer.prototype.compact = function() { - if (this.array == null) { - throw(new Error(this+" cannot be compacted: Already destroyed")); - } - if (this.offset > this.length) { - this.flip(); - } - if (this.offset == this.length) { - throw(new Error(this+" cannot be compacted: Offset ("+this.offset+") is equal to its length ("+this.length+")")); - } - if (this.offset == 0 && this.length == this.array.byteLength) { - return this; // Already compacted - } - var srcView = new Uint8Array(this.array); - var dst = new ArrayBuffer(this.length-this.offset); - var dstView = new Uint8Array(dst); - dstView.set(srcView.subarray(this.offset, this.length)); - this.array = dst; - this.offset = 0; - this.length = this.array.byteLength; - return this; - }; - - /** - * Destroys the ByteBuffer, releasing all references to the backing array. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.destroy = function() { - if (this.array == null) return; // Already destroyed - this.array = null; - this.view = null; - this.offset = 0; - this.length = 0; - return this; - }; - - /** - * Reverses the underlying back buffer and adapts offset and length to retain the same relative position on the - * reversed data in inverse order. Example: "00<01 02>03 04".reverse() = "04 03<02 01>00". - * @return {ByteBuffer} this - * @throws {Error} If the buffer is already destroyed - */ - ByteBuffer.prototype.reverse = function() { - if (this.array == null) { - throw(new Error(this+" cannot be reversed: Already destroyed")); - } - // Not sure what for, but other implementations seem to have it :-) - Array.prototype.reverse.call(new Uint8Array(this.array)); - var o = this.offset; - this.offset = this.array.byteLength - this.length; - this.length = this.array.byteLength - o; - this.view = new DataView(this.array); - return this; - }; - - /** - * Appends another ByteBuffer to this one. Appends only the portion between offset and length of the specified - * ByteBuffer and overwrites any contents behind the specified offset up to the number of bytes appended from - * the specified ByteBuffer in this ByteBuffer. Will clone and flip the specified ByteBuffer if its offset is - * larger than its length (its offsets remain untouched through cloning). - * @param {*} src ByteBuffer or any object that can be wrapped by one to prepend - * @param {number=} offset Offset to append behind. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the specified buffer is already destroyed - */ - ByteBuffer.prototype.append = function(src, offset) { - if (!(src instanceof ByteBuffer)) { - src = ByteBuffer.wrap(src); - } - if (src.array == null) { - throw(new Error(src+" cannot be appended to "+this+": Already destroyed")); - } - var n = src.length - src.offset; - if (n == 0) return this; // Nothing to append - if (n < 0) { - src = src.clone().flip(); - n = src.length - src.offset; - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=n)-n; - this.ensureCapacity(offset+n); - var srcView = new Uint8Array(src.array); - var dstView = new Uint8Array(this.array); - dstView.set(srcView.subarray(src.offset, src.length), offset); - return this; - }; - - /** - * Prepends another ByteBuffer to this one. Prepends only the portion between offset and length of the specified - * ByteBuffer and overwrites any contents before the specified offsets up to the number of bytes prepended from - * the specified ByteBuffer in this ByteBuffer. Will clone and flip the specified ByteBuffer if its offset is - * larger than its length (its offsets remain untouched through cloning). - * @param {*} src ByteBuffer or any object that can be wrapped by one to prepend - * @param {number=} offset Offset to prepend before. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the specified buffer is already destroyed - */ - ByteBuffer.prototype.prepend = function(src, offset) { - if (!(src instanceof ByteBuffer)) { - src = ByteBuffer.wrap(src); - } - if (src.array == null) { - throw(src+" cannot be prepended to "+this+": Already destroyed"); - } - var n = src.length - src.offset; - if (n == 0) return this; // Nothing to prepend - if (n < 0) { - src = src.clone().flip(); - n = src.length - src.offset; - } - var modify = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var diff = n-offset; - if (diff > 0) { - // Doesn't fit, so maybe resize and move the contents that are already contained - this.ensureCapacity(this.length+diff); - this.append(this, n); - this.offset += diff; - this.length += diff; - this.append(src, 0); - } else { - this.append(src, offset-n); - } - if (modify) { - this.offset -= n; - } - return this; - }; - - /** - * Writes an 8bit singed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeInt8 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=1)-1; - this.ensureCapacity(offset+1); - this.view.setInt8(offset, value); - return this; - }; - - /** - * Reads an 8bit singed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - */ - ByteBuffer.prototype.readInt8 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=1)-1; - if (offset >= this.array.byteLength) { - throw(new Error("Cannot read int8 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt8(offset); - }; - - /** - * Writes a byte. This is an alias of {ByteBuffer#writeInt8}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeByte = ByteBuffer.prototype.writeInt8; - - /** - * Reads a byte. This is an alias of {@link ByteBuffer#readInt8}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - */ - ByteBuffer.prototype.readByte = ByteBuffer.prototype.readInt8; - - /** - * Writes an 8bit unsinged integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the offset is equal to or larger than the capacity - */ - ByteBuffer.prototype.writeUint8 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=1)-1; - this.ensureCapacity(offset+1); - this.view.setUint8(offset, value); - return this; - }; - - /** - * Reads an 8bit unsinged integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - */ - ByteBuffer.prototype.readUint8 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=1)-1; - if (offset+1 > this.array.byteLength) { - throw(new Error("Cannot read uint8 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint8(offset); - }; - - /** - * Writes a 16bit signed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeInt16 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - this.ensureCapacity(offset+2); - this.view.setInt16(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 16bit signed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - */ - ByteBuffer.prototype.readInt16 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - if (offset+2 > this.array.byteLength) { - throw(new Error("Cannot read int16 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt16(offset, this.littleEndian); - }; - - /** - * Writes a short value. This is an alias of {@link ByteBuffer#writeInt16}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeShort = ByteBuffer.prototype.writeInt16; - - /** - * Reads a short value. This is an alias of {@link ByteBuffer#readInt16}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - */ - ByteBuffer.prototype.readShort = ByteBuffer.prototype.readInt16; - - /** - * Writes a 16bit unsigned integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeUint16 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - this.ensureCapacity(offset+2); - this.view.setUint16(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 16bit unsigned integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - */ - ByteBuffer.prototype.readUint16 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - if (offset+2 > this.array.byteLEngth) { - throw(new Error("Cannot read int16 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint16(offset, this.littleEndian); - }; - - /** - * Writes a 32bit signed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeInt32 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setInt32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit signed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - */ - ByteBuffer.prototype.readInt32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (offset+4 > this.array.byteLength) { - throw(new Error("Cannot read int32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt32(offset, this.littleEndian); - }; - - /** - * Writes an integer. This is an alias of {@link ByteBuffer#writeInt32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeInt = ByteBuffer.prototype.writeInt32; - - /** - * Reads an integer. This is an alias of {@link ByteBuffer#readInt32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - */ - ByteBuffer.prototype.readInt = ByteBuffer.prototype.readInt32; - - /** - * Writes a 32bit unsigned integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeUint32 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setUint32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit unsigned integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - */ - ByteBuffer.prototype.readUint32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (offset+4 > this.array.byteLength) { - throw(new Error("Cannot read uint32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint32(offset, this.littleEndian); - }; - - /** - * Writes a 32bit float. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeFloat32 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setFloat32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit float. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - */ - ByteBuffer.prototype.readFloat32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (this.array == null || offset+4 > this.array.byteLength) { - throw(new Error("Cannot read float32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getFloat32(offset, this.littleEndian); - }; - - /** - * Writes a float. This is an alias of {@link ByteBuffer#writeFloat32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeFloat = ByteBuffer.prototype.writeFloat32; - - /** - * Reads a float. This is an alias of {@link ByteBuffer#readFloat32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - */ - ByteBuffer.prototype.readFloat = ByteBuffer.prototype.readFloat32; - - /** - * Writes a 64bit float. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeFloat64 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - this.ensureCapacity(offset+8); - this.view.setFloat64(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 64bit float. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+8 is larger than the capacity - */ - ByteBuffer.prototype.readFloat64 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - throw(new Error("Cannot read float64 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getFloat64(offset, this.littleEndian); - }; - - /** - * Writes a double. This is an alias of {@link ByteBuffer#writeFloat64}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeDouble = ByteBuffer.prototype.writeFloat64; - - /** - * Reads a double. This is an alias of {@link ByteBuffer#readFloat64}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+8 is larger than the capacity - */ - ByteBuffer.prototype.readDouble = ByteBuffer.prototype.readFloat64; - - /** - * Writes a 64bit integer. Utilizes Long.js to write the low and high 32 bits separately. - * @function - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If long support is not available - */ - ByteBuffer.prototype.writeInt64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - this.ensureCapacity(offset+8); - if (this.littleEndian) { - this.view.setInt32(offset, value.getLowBits(), true); - this.view.setInt32(offset+4, value.getHighBits(), true); - } else { - this.view.setInt32(offset, value.getHighBits(), false); - this.view.setInt32(offset+4, value.getLowBits(), false); - } - return this; - }; - - /** - * Reads a 64bit integer. Utilizes Long.js to construct a new Long from the low and high 32 bits. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long} - * @throws {Error} If offset+8 is larger than the capacity or long support is not available - */ - ByteBuffer.prototype.readInt64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - this.offset -= 8; - throw(new Error("Cannot read int64 from "+this+" at "+offset+": Capacity overflow")); - } - var value; - if (this.littleEndian) { - value = Long.fromBits(this.view.getInt32(offset, true), this.view.getInt32(offset+4, true), false); - } else { - value = Long.fromBits(this.view.getInt32(offset+4, false), this.view.getInt32(offset, false), false); - } - return value; - }; - - /** - * Writes a 64bit unsigned integer. Utilizes Long.js to write the low and high 32 bits separately. - * @function - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If long support is not available - */ - ByteBuffer.prototype.writeUint64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, true); - this.ensureCapacity(offset+8); - if (this.littleEndian) { - this.view.setUint32(offset, value.getLowBitsUnsigned(), true); - this.view.setUint32(offset+4, value.getHighBitsUnsigned(), true); - } else { - this.view.setUint32(offset, value.getHighBitsUnsigned(), false); - this.view.setUint32(offset+4, value.getLowBitsUnsigned(), false); - } - return this; - }; - - /** - * Reads a 64bit unsigned integer. Utilizes Long.js to construct a new Long from the low and high 32 bits. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long} - * @throws {Error} If offset+8 is larger than the capacity or long support is not available - */ - ByteBuffer.prototype.readUint64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - this.offset -= 8; - throw(new Error("Cannot read int64 from "+this+" at "+offset+": Capacity overflow")); - } - var value; - if (this.littleEndian) { - value = Long.fromBits(this.view.getUint32(offset, true), this.view.getUint32(offset+4, true), true); - } else { - value = Long.fromBits(this.view.getUint32(offset+4, false), this.view.getUint32(offset, false), true); - } - return value; - }; - - /** - * Writes a long. This is an alias of {@link ByteBuffer#writeInt64}. - * @function - * @param {number|ByteBuffer.Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - */ - ByteBuffer.prototype.writeLong = ByteBuffer.prototype.writeInt64; - - /** - * Reads a long. This is an alias of {@link ByteBuffer#readInt64}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer.Long} - * @throws {Error} If offset+8 is larger than the capacity - */ - ByteBuffer.prototype.readLong = ByteBuffer.prototype.readInt64; - - /** - * Maximum number of bytes required to store a 32bit base 128 variable-length integer. - * @type {number} - * @const - */ - ByteBuffer.MAX_VARINT32_BYTES = 5; - - /** - * Writes a 32bit base 128 variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - */ - ByteBuffer.prototype.writeVarint32 = function(value, offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - // ref: http://code.google.com/searchframe#WTeibokF6gE/trunk/src/google/protobuf/io/coded_stream.cc - value = value >>> 0; - this.ensureCapacity(offset+ByteBuffer.calculateVarint32(value)); - var dst = this.view, - size = 0; - dst.setUint8(offset, value | 0x80); - if (value >= (1 << 7)) { - dst.setUint8(offset+1, (value >> 7) | 0x80); - if (value >= (1 << 14)) { - dst.setUint8(offset+2, (value >> 14) | 0x80); - if (value >= (1 << 21)) { - dst.setUint8(offset+3, (value >> 21) | 0x80); - if (value >= (1 << 28)) { - dst.setUint8(offset+4, (value >> 28) & 0x7F); - size = 5; - } else { - dst.setUint8(offset+3, dst.getUint8(offset+3) & 0x7F); - size = 4; - } - } else { - dst.setUint8(offset+2, dst.getUint8(offset+2) & 0x7F); - size = 3; - } - } else { - dst.setUint8(offset+1, dst.getUint8(offset+1) & 0x7F); - size = 2; - } - } else { - dst.setUint8(offset, dst.getUint8(offset) & 0x7F); - size = 1; - } - if (advance) { - this.offset += size; - return this; - } else { - return size; - } - }; - - /** - * Reads a 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - */ - ByteBuffer.prototype.readVarint32 = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - // ref: src/google/protobuf/io/coded_stream.cc - - var count = 0, b, - src = this.view; - var value = 0 >>> 0; - do { - b = src.getUint8(offset+count); - if (count < ByteBuffer.MAX_VARINT32_BYTES) { - value |= ((b&0x7F)<<(7*count)) >>> 0; - } - ++count; - } while (b & 0x80); - value = value | 0; // Make sure to discard the higher order bits - if (advance) { - this.offset += count; - return value; - } else { - return { - "value": value, - "length": count - }; - } - }; - - /** - * Writes a zigzag encoded 32bit base 128 encoded variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - */ - ByteBuffer.prototype.writeZigZagVarint32 = function(value, offset) { - return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset); - }; - - /** - * Reads a zigzag encoded 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - */ - ByteBuffer.prototype.readZigZagVarint32 = function(offset) { - var dec = this.readVarint32(offset); - if (typeof dec === 'object') { - dec['value'] = ByteBuffer.zigZagDecode32(dec['value']); - return dec; - } - return ByteBuffer.zigZagDecode32(dec); - }; - - /** - * Maximum number of bytes required to store a 64bit base 128 variable-length integer. - * @type {number} - * @const - */ - ByteBuffer.MAX_VARINT64_BYTES = 10; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_7_DBL = 1 << 7; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_14_DBL = TWO_PWR_7_DBL * TWO_PWR_7_DBL; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_21_DBL = TWO_PWR_7_DBL * TWO_PWR_14_DBL; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_28_DBL = TWO_PWR_14_DBL * TWO_PWR_14_DBL; - - /** - * Writes a 64bit base 128 variable-length integer as used in protobuf. - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @throws {Error} If long support is not available - */ - ByteBuffer.prototype.writeVarint64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - - var part0 = value.toInt() >>> 0, - part1 = value.shiftRightUnsigned(28).toInt() >>> 0, - part2 = value.shiftRightUnsigned(56).toInt() >>> 0, - size = ByteBuffer.calculateVarint64(value); - - this.ensureCapacity(offset+size); - var dst = this.view; - switch (size) { - case 10: dst.setUint8(offset+9, (part2 >>> 7) | 0x80); - case 9 : dst.setUint8(offset+8, (part2 ) | 0x80); - case 8 : dst.setUint8(offset+7, (part1 >>> 21) | 0x80); - case 7 : dst.setUint8(offset+6, (part1 >>> 14) | 0x80); - case 6 : dst.setUint8(offset+5, (part1 >>> 7) | 0x80); - case 5 : dst.setUint8(offset+4, (part1 ) | 0x80); - case 4 : dst.setUint8(offset+3, (part0 >>> 21) | 0x80); - case 3 : dst.setUint8(offset+2, (part0 >>> 14) | 0x80); - case 2 : dst.setUint8(offset+1, (part0 >>> 7) | 0x80); - case 1 : dst.setUint8(offset+0, (part0 ) | 0x80); - } - dst.setUint8(offset+size-1, dst.getUint8(offset+size-1) & 0x7F); - if (advance) { - this.offset += size; - return this; - } else { - return size; - } - }; - - /** - * Reads a 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long|{value: Long, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint or long support is not available - */ - ByteBuffer.prototype.readVarint64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var start = offset; - // ref: src/google/protobuf/io/coded_stream.cc - - var src = this.view, - part0, part1 = 0, part2 = 0, b; - b = src.getUint8(offset++); part0 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 7; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 14; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 21; if (b & 0x80) { - b = src.getUint8(offset++); part1 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 7; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 14; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 21; if (b & 0x80) { - b = src.getUint8(offset++); part2 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part2 |= (b & 0x7F) << 7; if (b & 0x80) { - throw(new Error("Data must be corrupt: Buffer overrun")); }}}}}}}}}} - var value = Long.from28Bits(part0, part1, part2, false); - if (advance) { - this.offset = offset; - return value; - } else { - return { - "value": value, - "length": offset-start - }; - } - }; - - /** - * Writes a zigzag encoded 64bit base 128 encoded variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @throws {Error} If long support is not available - */ - ByteBuffer.prototype.writeZigZagVarint64 = function(value, offset) { - return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); - }; - - /** - * Reads a zigzag encoded 64bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long|{value: Long, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint or long support is not available - */ - ByteBuffer.prototype.readZigZagVarint64 = function(offset) { - var dec = this.readVarint64(offset); - if (typeof dec === 'object' && !(dec instanceof Long)) { - dec['value'] = ByteBuffer.zigZagDecode64(dec['value']); - return dec; - } - return ByteBuffer.zigZagDecode64(dec); - }; - - /** - * Writes a base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#writeVarint32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - */ - ByteBuffer.prototype.writeVarint = ByteBuffer.prototype.writeVarint32; - - /** - * Reads a base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#readVarint32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - */ - ByteBuffer.prototype.readVarint = ByteBuffer.prototype.readVarint32; - - /** - * Writes a zigzag encoded base 128 encoded variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#writeZigZagVarint32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - */ - ByteBuffer.prototype.writeZigZagVarint = ByteBuffer.prototype.writeZigZagVarint32; - - /** - * Reads a zigzag encoded base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#readZigZagVarint32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - */ - ByteBuffer.prototype.readZigZagVarint = ByteBuffer.prototype.readZigZagVarint32; - - /** - * Calculates the actual number of bytes required to encode a 32bit base 128 variable-length integer. - * @param {number} value Value to encode - * @return {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES} (35bit). No overflow error. - */ - ByteBuffer.calculateVarint32 = function(value) { - // ref: src/google/protobuf/io/coded_stream.cc - value = value >>> 0; - if (value < TWO_PWR_7_DBL) { - return 1; - } else if (value < TWO_PWR_14_DBL) { - return 2; - } else if (value < TWO_PWR_21_DBL) { - return 3; - } else if (value < TWO_PWR_28_DBL) { - return 4; - } else { - return 5; - } - }; - - /** - * Calculates the actual number of bytes required to encode a 64bit base 128 variable-length integer. - * @param {number|Long} value Value to encode - * @return {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES}. No overflow error. - * @throws {Error} If long support is not available - */ - ByteBuffer.calculateVarint64 = function(value) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/io/coded_stream.cc - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - - var part0 = value.toInt() >>> 0, - part1 = value.shiftRightUnsigned(28).toInt() >>> 0, - part2 = value.shiftRightUnsigned(56).toInt() >>> 0; - - if (part2 == 0) { - if (part1 == 0) { - if (part0 < TWO_PWR_14_DBL) { - return part0 < TWO_PWR_7_DBL ? 1 : 2; - } else { - return part0 < TWO_PWR_21_DBL ? 3 : 4; - } - } else { - if (part1 < TWO_PWR_14_DBL) { - return part1 < TWO_PWR_7_DBL ? 5 : 6; - } else { - return part1 < TWO_PWR_21_DBL ? 7 : 8; - } - } - } else { - return part2 < TWO_PWR_7_DBL ? 9 : 10; - } - }; - - /** - * Encodes a signed 32bit integer so that it can be effectively used with varint encoding. - * @param {number} n Signed 32bit integer - * @return {number} Unsigned zigzag encoded 32bit integer - */ - ByteBuffer.zigZagEncode32 = function(n) { - // ref: src/google/protobuf/wire_format_lite.h - return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; - }; - - /** - * Decodes a zigzag encoded signed 32bit integer. - * @param {number} n Unsigned zigzag encoded 32bit integer - * @return {number} Signed 32bit integer - */ - ByteBuffer.zigZagDecode32 = function(n) { - // ref: src/google/protobuf/wire_format_lite.h - return ((n >>> 1) ^ -(n & 1)) | 0; - }; - - /** - * Encodes a signed 64bit integer so that it can be effectively used with varint encoding. - * @param {number|Long} n Signed long - * @return {Long} Unsigned zigzag encoded long - * @throws {Error} If long support is not available - */ - ByteBuffer.zigZagEncode64 = function(n) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/wire_format_lite.h - if (typeof n === 'object' && n instanceof Long) { - if (n.unsigned) n = n.toSigned(); - } else { - n = Long.fromNumber(n, false); - } - return n.shiftLeft(1).xor(n.shiftRight(63)).toUnsigned(); - }; - - /** - * Decodes a zigzag encoded signed 64bit integer. - * @param {Long} n Unsigned zigzag encoded long - * @return {Long} Signed long - * @throws {Error} If long support is not available - */ - ByteBuffer.zigZagDecode64 = function(n) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/wire_format_lite.h - if (typeof n === 'object' && n instanceof Long) { - if (!n.unsigned) n = n.toUnsigned(); - } else { - n = Long.fromNumber(n, true); - } - return n.shiftRightUnsigned(1).xor(n.and(Long.ONE).toSigned().negate()).toSigned(); - }; - - /** - * Decodes a single UTF8 character from the specified ByteBuffer. The ByteBuffer's offsets are not modified. - * @param {ByteBuffer} src - * @param {number} offset Offset to read from - * @return {{char: number, length: number}} Decoded char code and the actual number of bytes read - * @throws {Error} If the character cannot be decoded or there is a capacity overflow - */ - ByteBuffer.decodeUTF8Char = function(src, offset) { - var a = src.readUint8(offset), b, c, d, e, f, start = offset, charCode; - // ref: http://en.wikipedia.org/wiki/UTF-8#Description - // It's quite huge but should be pretty fast. - if ((a&0x80)==0) { - charCode = a; - offset += 1; - } else if ((a&0xE0)==0xC0) { - b = src.readUint8(offset+1); - charCode = ((a&0x1F)<<6) | (b&0x3F); - offset += 2; - } else if ((a&0xF0)==0xE0) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - charCode = ((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F); - offset += 3; - } else if ((a&0xF8)==0xF0) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - charCode = ((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F); - offset += 4; - } else if ((a&0xFC)==0xF8) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - e = src.readUint8(offset+4); - charCode = ((a&0x03)<<24) | ((b&0x3F)<<18) | ((c&0x3F)<<12) | ((d&0x3F)<<6) | (e&0x3F); - offset += 5; - } else if ((a&0xFE)==0xFC) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - e = src.readUint8(offset+4); - f = src.readUint8(offset+5); - charCode = ((a&0x01)<<30) | ((b&0x3F)<<24) | ((c&0x3F)<<18) | ((d&0x3F)<<12) | ((e&0x3F)<<6) | (f&0x3F); - offset += 6; - } else { - throw(new Error("Cannot decode UTF8 character at offset "+offset+": charCode (0x"+a.toString(16)+") is invalid")); - } - return { - "char": charCode , - "length": offset-start - }; - }; - - /** - * Encodes a single UTF8 character to the specified ByteBuffer. The ByteBuffer's offsets are not modified. - * @param {number} charCode Character to encode as char code - * @param {ByteBuffer} dst ByteBuffer to encode to - * @param {number} offset Offset to write to - * @return {number} Actual number of bytes written - * @throws {Error} If the character cannot be encoded - */ - ByteBuffer.encodeUTF8Char = function(charCode, dst, offset) { - var start = offset; - // ref: http://en.wikipedia.org/wiki/UTF-8#Description - // It's quite huge but should be pretty fast. - if (charCode < 0) { - throw(new Error("Cannot encode UTF8 character: charCode ("+charCode+") is negative")); - } - if (charCode < 0x80) { - dst.writeUint8(charCode&0x7F, offset); - offset += 1; - } else if (charCode < 0x800) { - dst.writeUint8(((charCode>>6)&0x1F)|0xC0, offset) - .writeUint8((charCode&0x3F)|0x80, offset+1); - offset += 2; - } else if (charCode < 0x10000) { - dst.writeUint8(((charCode>>12)&0x0F)|0xE0, offset) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+1) - .writeUint8((charCode&0x3F)|0x80, offset+2); - offset += 3; - } else if (charCode < 0x200000) { - dst.writeUint8(((charCode>>18)&0x07)|0xF0, offset) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+2) - .writeUint8((charCode&0x3F)|0x80, offset+3); - offset += 4; - } else if (charCode < 0x4000000) { - dst.writeUint8(((charCode>>24)&0x03)|0xF8, offset) - .writeUint8(((charCode>>18)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+2) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+3) - .writeUint8((charCode&0x3F)|0x80, offset+4); - offset += 5; - } else if (charCode < 0x80000000) { - dst.writeUint8(((charCode>>30)&0x01)|0xFC, offset) - .writeUint8(((charCode>>24)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>18)&0x3F)|0x80, offset+2) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+3) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+4) - .writeUint8((charCode&0x3F)|0x80, offset+5); - offset += 6; - } else { - throw(new Error("Cannot encode UTF8 character: charCode (0x"+charCode.toString(16)+") is too large (>= 0x80000000)")); - } - return offset-start; - }; - - /** - * Calculates the actual number of bytes required to encode the specified char code. - * @param {number} charCode Character to encode as char code - * @return {number} Number of bytes required to encode the specified char code - * @throws {Error} If the character cannot be calculated (too large) - */ - ByteBuffer.calculateUTF8Char = function(charCode) { - if (charCode < 0) { - throw(new Error("Cannot calculate length of UTF8 character: charCode ("+charCode+") is negative")); - } - if (charCode < 0x80) { - return 1; - } else if (charCode < 0x800) { - return 2; - } else if (charCode < 0x10000) { - return 3; - } else if (charCode < 0x200000) { - return 4; - } else if (charCode < 0x4000000) { - return 5; - } else if (charCode < 0x80000000) { - return 6; - } else { - throw(new Error("Cannot calculate length of UTF8 character: charCode (0x"+charCode.toString(16)+") is too large (>= 0x80000000)")); - } - }; - - /** - * Calculates the number of bytes required to store an UTF8 encoded string. - * @param {string} str String to calculate - * @return {number} Number of bytes required - */ - ByteBuffer.calculateUTF8String = function(str) { - str = ""+str; - var bytes = 0; - for (var i=0; i i ? bb.readUint8(i++) : 0; - o3 = bb.length > i ? bb.readUint8(i++) : 0; - bits = o1 << 16 | o2 << 8 | o3; - h1 = bits >> 18 & 0x3f; - h2 = bits >> 12 & 0x3f; - h3 = bits >> 6 & 0x3f; - h4 = bits & 0x3f; - out[oi++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); - } while (i < bb.length); - var enc = out.join(''), - r = (bb.length - bb.offset) % 3; - return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3); - }; - - /** - * Decodes a base6 encoded string to a ByteBuffer. - * @param {string} str Base64 encoded string - * @returns {!ByteBuffer} ByteBuffer - * @throws {Error} If the argument is not a valid base64 encoded string - */ - ByteBuffer.decode64 = function(str) { - // ref: http://phpjs.org/functions/base64_decode/ - if (typeof str !== 'string') { - throw(new Error("Illegal argument: Not a string")); - } - var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, - out = new ByteBuffer(Math.ceil(str.length / 3)); - do { - h1 = b64.indexOf(str.charAt(i++)); - h2 = b64.indexOf(str.charAt(i++)); - h3 = b64.indexOf(str.charAt(i++)); - h4 = b64.indexOf(str.charAt(i++)); - if (h1 < 0 || h2 < 0 || h3 < 0 || h4 < 0) { - throw(new Error("Illegal argument: Not a valid base64 encoded string")); - } - bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; - o1 = bits >> 16 & 0xff; - o2 = bits >> 8 & 0xff; - o3 = bits & 0xff; - if (h3 == 64) { - out.writeUint8(o1); - } else if (h4 == 64) { - out.writeUint8(o1) - .writeUint8(o2); - } else { - out.writeUint8(o1) - .writeUint8(o2) - .writeUint8(o3); - } - } while (i < str.length); - return out.flip(); - }; - - - /** - * Writes an UTF8 string. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - */ - ByteBuffer.prototype.writeUTF8String = function(str, offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var start = offset; - var encLen = ByteBuffer.calculateUTF8String(str), i; // See [1] - this.ensureCapacity(offset+encLen); - for (i=0; ilength ? "+" : "")+offset-length)+" bytes")); - } - if (advance) { - this.offset = offset; - return result; - } else { - return { - "string": result, - "length": offset-start - } - } - }; - - /** - * Writes a string with prepended number of characters, which is also encoded as an UTF8 character.. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - */ - ByteBuffer.prototype.writeLString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = ByteBuffer.encodeUTF8Char(str.length, this, offset); - encLen += this.writeUTF8String(str, offset+encLen); - if (advance) { - this.offset += encLen; - return this; - } else { - return encLen; - } - }; - - /** - * Reads a string with a prepended number of characters, which is also encoded as an UTF8 character. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded - */ - ByteBuffer.prototype.readLString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var lenDec = ByteBuffer.decodeUTF8Char(this, offset); - var dec = this.readUTF8String(lenDec["char"], offset+lenDec["length"]); - if (advance) { - this.offset += lenDec["length"]+dec["length"]; - return dec["string"]; - } else { - return { - "string": dec["string"], - "length": lenDec["length"]+dec["length"] - }; - } - }; - - /** - * Writes a string with prepended number of characters, which is encoded as a 32bit base 128 variable-length integer. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - */ - ByteBuffer.prototype.writeVString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = this.writeVarint32(ByteBuffer.calculateUTF8String(str), offset); - encLen += this.writeUTF8String(str, offset+encLen); - if (advance) { - this.offset += encLen; - return this; - } else { - return encLen; - } - }; - - /** - * Reads a string with a prepended number of characters, which is encoded as a 32bit base 128 variable-length integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded or the delimiter is not a valid varint - */ - ByteBuffer.prototype.readVString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var lenDec = this.readVarint32(offset); - var dec = this.readUTF8StringBytes(lenDec["value"], offset+lenDec["length"]); - if (advance) { - this.offset += lenDec["length"]+dec["length"]; - return dec["string"]; - } else { - return { - "string": dec["string"], - "length": lenDec["length"]+dec["length"] - }; - } - }; - - /** - * Writes a string followed by a NULL character (Uint8). Beware: The source string must not contain NULL characters - * unless this is actually intended. This is not checked. If you have the option it is recommended to use - * {@link ByteBuffer#writeLString} or {@link ByteBuffer#writeVString} with the corresponding reading methods instead. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - */ - ByteBuffer.prototype.writeCString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = this.writeUTF8String(str, offset); - this.writeUint8(0, offset+encLen); - if (advance) { - this.offset += encLen+1; - return this; - } else { - return encLen+1; - } - }; - - /** - * Reads a string followed by a NULL character (Uint8). - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded - */ - ByteBuffer.prototype.readCString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var dec, result = "", start = offset; - do { - dec = ByteBuffer.decodeUTF8Char(this, offset); - offset += dec["length"]; - if (dec["char"] != 0) result += String.fromCharCode(dec["char"]); - } while (dec["char"] != 0); - if (advance) { - this.offset = offset; - return result; - } else { - return { - "string": result, - "length": offset-start - }; - } - }; - - /** - * Serializes and writes a JSON payload. - * @param {*} data Data payload to serialize - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted, - * @param {function=} stringify Stringify implementation to use. Defaults to {@link JSON.stringify}. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number if bytes written, - */ - ByteBuffer.prototype.writeJSON = function(data, offset, stringify) { - stringify = typeof stringify === 'function' ? stringify : JSON.stringify; - return this.writeLString(stringify(data), offset); - }; - - /** - * Reads a JSON payload and unserializes it. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @param {function=} parse Parse implementation to use. Defaults to {@link JSON.parse}. - * @return {*|{data: *, length: number}} Data payload if offset is omitted, else the data payload and the actual number of bytes read. - * @throws {Error} If the data cannot be decoded - */ - ByteBuffer.prototype.readJSON = function(offset, parse) { - parse = typeof parse === 'function' ? parse : JSON.parse; - var result = this.readLString(offset); - if (typeof result === 'string') { - return parse(result); - } else { - return { - "data": parse(result["string"]), - "length": result["length"] - }; - } - }; - - /** - * Prints debug information about this ByteBuffer's contents to console. - * @param {!Function=|boolean} out Output function to call with the result or true to return the data as a string. - * Defaults to call console.log. - */ - ByteBuffer.prototype.printDebug = function(out) { - var s = (this.array != null ? "ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")" : "ByteBuffer(DESTROYED)")+"\n"+ - "-------------------------------------------------------------------\n"; - var h = this.toHex(16, true); - var a = this.toASCII(16, true); - for (var i=0; i} Hex representation as of " 00<01 02>03..." with marked offsets - */ - ByteBuffer.prototype.toHex = function(wrap, asArray) { - if (this.array == null) return "DESTROYED"; - asArray = !!asArray; - wrap = typeof wrap !== 'undefined' ? parseInt(wrap, 10) : 16; - if (wrap < 1) wrap = 16; - var out = "", - lines = [], - view = this.view; - if (this.offset == 0 && this.length == 0) { - out += "|"; - } else if (this.length == 0) { - out += ">"; - } else if (this.offset == 0) { - out += "<"; - } else { - out += " "; - } - for (var i=0; i0 && i%wrap == 0) { - lines.push(out); - out = " "; - } - var val = view.getUint8(i); - val = val.toString(16).toUpperCase(); - if (val.length < 2) val = "0"+val; - out += val; - if (i+1 == this.offset && i+1 == this.length) { - out += "|"; - } else if (i+1 == this.offset) { - out += "<"; - } else if (i+1 == this.length) { - out += ">"; - } else { - out += " "; - } - } - if (asArray) { - while (out.length < 3*wrap+1) out += " "; // Make it equal to maybe show something on the right - } - lines.push(out); - return asArray ? lines : lines.join("\n"); - }; - - /** - * Returns an ASCII representation of this ByteBuffer's contents. Beware: May be large. - * @param {number=} wrap Wrap length. Defaults to 16. - * @param {boolean=} asArray Set to true to return an array of lines. Defaults to false. - * @return {string|Array.} ASCII representation as of "abcdef..." (33-126, else ".", no marked offsets) - */ - ByteBuffer.prototype.toASCII = function(wrap, asArray) { - if (this.array == null) return ""; - asArray = !!asArray; - wrap = typeof wrap !== 'undefined' ? parseInt(wrap, 10) : 16; - if (wrap < 1) wrap = 16; - var out = "", lines = [], src = this.view; - for (var i=0; i0 && i%wrap == 0) { - lines.push(out); - out = ""; - } - var val = src.getUint8(i); - if (val > 32 && val < 127) { - val = String.fromCharCode(val); - } else { - val = "."; - } - out += val; - } - lines.push(out); - return asArray ? lines : lines.join("\n")+"\n"; - }; - - /** - * Returns the base64 encoded representation of the buffer's contents. - * @returns {string} Base 64 encoded string - */ - ByteBuffer.prototype.toBase64 = function() { - if (this.array == null || this.offset >= this.length) return ""; - return ByteBuffer.encode64(this); - }; - - /** - * Returns the contents of the buffer as an UTF8 encoded string. - * @returns {string} - */ - ByteBuffer.prototype.toUTF8 = function() { - if (this.array == null || this.offset >= this.length) return ""; - return this.readUTF8StringBytes(this.length - this.offset, this.offset).string; - }; - - /** - * Returns a string representation. - * @param {string=} enc Output encoding. Returns a pretty printed debug table by default but also allows direct - * conversion to "utf8" and "base64" encoding. - * @return {string} String representation - */ - ByteBuffer.prototype.toString = function(enc) { - enc = enc || "debug"; - switch (enc) { - case "utf8": - return this.toUTF8(); - case "base64": - return this.toBase64(); - default: - if (this.array == null) { - return "ByteBuffer(DESTROYED)"; - } - return "ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")"; - } - }; - - /** - * Returns an ArrayBuffer compacted to contain this ByteBuffer's actual contents. Will implicitly - * {@link ByteBuffer#flip} the ByteBuffer if its offset is larger than its length. Will return a reference to - * the unmodified backing buffer if offset=0 and length=capacity unless forceCopy is set to true. - * @param {boolean=} forceCopy Forces the creation of a copy if set to true. Defaults to false. - * @return {ArrayBuffer} Compacted ArrayBuffer - */ - ByteBuffer.prototype.toArrayBuffer = function(forceCopy) { - var b = this.clone(); - if (b.offset > b.length) { - b.flip(); - } - var copied = false; - if (b.offset > 0 || b.length < b.array.byteLength) { - b.compact(); // Will always create a new backing buffer because of the above condition - copied = true; - } - return forceCopy && !copied ? b.copy().array : b.array; - }; - - /** - * Returns a node Buffer compacted to contain this ByteBuffer's actual contents. Will implicitly - * {@link ByteBuffer#flip} the ByteBuffer if its offset is larger than its length. Will also copy all data (not - * a reference). - * @returns {Buffer} Compacted Buffer - * @throws {Error} If not running inside of node - */ - ByteBuffer.prototype.toBuffer = function() { - if (Buffer) { - var offset = this.offset, length = this.length; - if (offset > length) { - var temp = offset; - offset = length; - length = temp; - } - var srcView = new Uint8Array(this.array); - return new Buffer(srcView.subarray(offset, length)); - } - throw(new Error("Conversion to Buffer is available under node.js only")); - }; - - /** - * Extends the ByteBuffer prototype with additional methods. - * @param {string} name Method name - * @param {!Function} func Prototype function - * @throws {Error} If the arguments are invalid - */ - ByteBuffer.extend = function(name, func) { - if (typeof name === 'string' && typeof func === 'function') { - ByteBuffer.prototype[name] = func; - } else { - throw(new Error("Cannot extend prototype with "+name+"="+func+" (exptected string and function)")); - } - }; - - return ByteBuffer; - } - - - - // Enable module loading if available - if (typeof module !== 'undefined' && module["exports"]) { // CommonJS - module["exports"] = loadByteBuffer(require("long")); - } else if (typeof define !== 'undefined' && define["amd"]) { // AMD - define("ByteBuffer", ["Math/Long"], function(Long) { return loadByteBuffer(Long); }); - } else { // Shim - if (!global["dcodeIO"]) { - global["dcodeIO"] = {}; - } - global["dcodeIO"]["ByteBuffer"] = loadByteBuffer(dcodeIO.Long); - } - -})(this); - diff --git a/ByteBuffer.png b/ByteBuffer.png deleted file mode 100644 index 3166934..0000000 Binary files a/ByteBuffer.png and /dev/null differ diff --git a/NOTICE b/NOTICE deleted file mode 100644 index dcddcf3..0000000 --- a/NOTICE +++ /dev/null @@ -1,2 +0,0 @@ -This software includes (portions of) ByteBuffer.js by Daniel 'dcode' Wirtz. -See: https://github.com/dcodeIO/ByteBuffer.js for details diff --git a/README.md b/README.md index 65e74e4..8f2c1e9 100644 --- a/README.md +++ b/README.md @@ -1,186 +1,64 @@ -![ByteBuffer.js - A Java-like ByteBuffer](https://raw.github.com/dcodeIO/ByteBuffer.js/master/ByteBuffer.png) +![bytebuffer.js - The swiss army knife for binary data in JavaScript.](https://raw.github.com/dcodeIO/bytebuffer.js/master/bytebuffer.png) ====================================== -Provides a Java-like, Netty-inspired ByteBuffer implementation using typed arrays. It also tries to abstract a bit of -the complexity away by providing convenience methods for those who just want to write stuff without caring about signed, -unsigned and the actual bit sizes. It's also one of the components driving [ProtoBuf.js](https://github.com/dcodeIO/ProtoBuf.js). +A fast and complete ByteBuffer implementation using either ArrayBuffers in the browser or node Buffers under node.js, +generated from a single source tree through [MetaScript](https://github.com/dcodeIO/MetaScript). -ByteBuffer ----------- -* Mimics [Java ByteBuffers](http://docs.oracle.com/javase/1.5.0/docs/api/java/nio/ByteBuffer.html) as close as reasonable while using typed array terms -* Full 64bit support via [Long.js](https://github.com/dcodeIO/Long.js) (optional) -* Simple allocation (`new ByteBuffer(capacity[, littleEndian])` or `ByteBuffer.allocate(capacity[, littleEndian])`) -* Wrapping of quite everything which is or includes an ArrayBuffer (`ByteBuffer.wrap(buffer[, littleEndian])`) -* Cloning using the same (`ByteBuffer#clone()`) and copying using an independent backing buffer (`ByteBuffer#copy()`) -* Slicing using the same (`ByteBuffer#slice(begin, end)`) and using an indepentent backing buffer (`ByteBuffer#sliceAndCompact(begin, end)`) -* Manual offset (`ByteBuffer#offset` and `ByteBuffer#length`) and array manipulation (`ByteBuffer#array`) -* Remaining readable bytes (`ByteBuffer#remaining()`) and backing buffer capacity getters (`ByteBuffer#capacity()`) -* Explicit (`ByteBuffer#resize(capacity)`) and implicit resizing (`ByteBuffer#ensureCapacity(capacity)`) -* Efficient implicit resizing by doubling the current capacity -* Flipping (`ByteBuffer#flip()`), marking (`ByteBuffer#mark([offset])`) and resetting (`ByteBuffer#reset()`) -* Compacting of the backing buffer (`ByteBuffer#compact()`) -* Conversion to ArrayBuffer (`ByteBuffer#toArrayBuffer([forceCopy])`) (i.e. to send data over the wire, e.g. a WebSocket - with `binaryType="arraybuffer"`) -* Conversion to Buffer (`ByteBuffer#toBuffer()`) if running inside of node.js -* Reversing (`ByteBuffer#reverse()`), appending (`ByteBuffer#append(src[, offset])`) and prepending - (`ByteBuffer#prepend(src[, offset])`) of other ByteBuffers with implicit capacity management -* Explicit destruction (`ByteBuffer#destroy()`) -* `ByteBuffer#writeUint/Int8/16/32/64(value[, offset])` and `ByteBuffer#readUint/Int8/16/32/64([offset])` -* `ByteBuffer#writeVarint32/64(value[, offset])` and `ByteBuffer#readVarint32/64([offset])` to write a base 128 - variable-length integer as used in [protobuf](https://developers.google.com/protocol-buffers/docs/encoding#varints) -* `ByteBuffer#writeZigZagVarint32/64(value[, offset])` and `ByteBuffer#readZigZagVarint32/64([offset])` to write a - zig-zag encoded base 128 variable-length integer as used in protobuf for efficient encoding of signed values -* `ByteBuffer#writeFloat32/64(value[, offset])` and `ByteBuffer#readFloat32/64([offset])` -* `ByteBuffer#write/readByte`, `ByteBuffer#write/readShort`, `ByteBuffer#write/readInt`, `ByteBuffer#write/readLong` - (all signed), `ByteBuffer#write/readVarint` and `ByteBuffer#write/readZigZagVarint` (both 32bit signed), - `ByteBuffer#write/readFloat`, `ByteBuffer#write/readDouble` aliases for the above for convenience -* `ByteBuffer#writeUTF8String(str[, offset])`, `ByteBuffer#readUTF8String(chars[, offset])` and - `ByteBuffer#readUTF8StringBytes(length[, offset])` using the included UTF8 en-/decoder (full 6 bytes, - [ref](http://en.wikipedia.org/wiki/UTF-8#Description)) -* `ByteBuffer.encode64(bb)`, `ByteBuffer.decode64(str)` and `ByteBuffer#toBase64()` using the included Base64 - en/-decoder. -* `ByteBuffer#writeLString(str[, offset]))` and `ByteBuffer#readLString([offset])` to write respectively read a - length-prepended (number of characters as UTF8 char) string -* `ByteBuffer#writeVString(str[, offset]))` and `ByteBuffer#readVString([offset])` to write respectively read a - length-prepended (number of bytes as base 128 variable-length 32bit integer) string -* `ByteBuffer#writeCString(str[, offset])` and `ByteBuffer#readCString([offset])` to write respectively read a - NULL-terminated (Uint8 0x00) string -* `ByteBuffer#writeJSON(data[, offset[, stringify]])` and `ByteBuffer#readJSON([offset[, parse]])` to write respectively - read arbitraty object data. Allows overriding the default stringify (default: JSON.stringify) and parse (default: - JSON.parse) implementations. -* All with implicit offset advance if the offset parameter is omitted or without, if specified -* Chaining of all operations that allow this (i.e. do not return some specific value like in read operations), e.g. +[![Build Status](https://travis-ci.org/dcodeIO/bytebuffer.js.svg?branch=master)](https://travis-ci.org/dcodeIO/bytebuffer.js) +[![Donate](https://raw.githubusercontent.com/dcodeIO/bytebuffer.js/master/donate.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=dcode%40dcode.io&item_name=%3C3%20bytebuffer.js) - ```javascript - var bb = new ByteBuffer(); - ... - bb.reset().writeInt(1).writeLString("Hello world!").flip().compact()... - ``` - -* Switching between little endian and big endian byte order through `ByteBuffer#LE()` and `ByteBuffer#BE()`, e.g. - - ```javascript - var bb = new ByteBuffer(8).LE().writeInt(1).BE().writeInt(2).flip(); // toHex: <01 00 00 00 00 00 00 02> - ``` - -* `ByteBuffer#toString([enc])`, `ByteBuffer#toHex([wrap])`, `ByteBuffer#toASCII([wrap])`, `ByteBuffer#toUTF8()`, - `ByteBuffer#toBase64()` and `ByteBuffer#printDebug()` (emits hex + ASCII + offsets to console, looks like your - favourite hex editor) for pain-free debugging - Features -------- -* [CommonJS](http://www.commonjs.org/) compatible -* [RequireJS](http://requirejs.org/)/AMD compatible -* [node.js](http://nodejs.org) compatible, also available via [npm](https://npmjs.org/package/bytebuffer) -* Browser compatible -* [Closure Compiler](https://developers.google.com/closure/compiler/) ADVANCED_OPTIMIZATIONS compatible (fully annotated, - `ByteBuffer.min.js` has been compiled this way, `ByteBuffer.min.map` is the source map) -* Fully documented using [jsdoc3](https://github.com/jsdoc3/jsdoc) -* Well tested through [nodeunit](https://github.com/caolan/nodeunit) -* Zero production dependencies (Long.js is optional) -* Small footprint +* Three API-compatible versions: + * **bytebuffer**   Backing buffer: ArrayBuffer, Accessor: Uint8Array + * **bytebuffer-dataview**   Backing buffer: ArrayBuffer, Accessor: DataView + * **bytebuffer-node**   Backing buffer / Accessor: node Buffer +* 8, 16, 32 and 64 bit (through [long.js](https://github.com/dcodeIO/long.js)) signed and unsigned integers +* 32 and 64 bit floats +* Varints as used in protobuf (32 and 64 bit, zig-zag) +* [Base64](https://github.com/dcodeIO/lxiv), [utf8](https://github.com/dcodeIO/utfx), binary, hex and debug encodings +* Handy string and debugging utilities +* Big and little endianness +* Relative and absolute zero-copy operations wherever possible +* Transparent resizing when using unknown-length data +* Chaining of all operations that do not return a specific value +* Slicing, appending, prepending, reversing, flip, mark, reset, etc. Usage ----- -### Node.js / CommonJS ### -* Install: `npm install bytebuffer` +The library is compatible with CommonJS and AMD loaders and is exposed globally as `dcodeIO.ByteBuffer` if neither is +available. ```javascript var ByteBuffer = require("bytebuffer"); -var bb = new ByteBuffer(); -bb.writeLString("Hello world!"); -bb.flip(); -console.log(bb.readLString()+" from ByteBuffer.js"); -``` - -### Browser ### - -Optionally depends on [Long.js](https://github.com/dcodeIO/Long.js) for long (int64) support. If you do not require long -support, you can skip the Long.js include. - -```html - - -``` -```javascript -var ByteBuffer = dcodeIO.ByteBuffer; -var bb = new ByteBuffer(); -bb.writeLString("Hello world!"); -bb.flip(); -alert(bb.readLString()+" from ByteBuffer.js"); +var bb = new ByteBuffer() + .writeIString("Hello world!") + .flip(); +console.log(bb.readIString()+" from bytebuffer.js"); ``` -### Require.js / AMD ### +In the browser, 64 bit integer support is optional and present only if [Long.js](https://github.com/dcodeIO/long.js) has +been loaded prior to bytebuffer.js. -Optionally depends on [Long.js](https://github.com/dcodeIO/Long.js) for long (int64) support. If you do not require long -support, you can skip the Long.js config. [Require.js](http://requirejs.org/) example: - -```javascript -require.config({ - "paths": { - "Long": "/path/to/Long.js" - "ByteBuffer": "/path/to/ByteBuffer.js" - } -}); -require(["ByteBuffer"], function(ByteBuffer) { - var bb = new ByteBuffer(); - bb.writeLString("Hello world!"); - bb.flip(); - alert(bb.readLString()+" from ByteBuffer.js"); -}); -``` - -On long (int64) support ------------------------ -As of the [ECMAScript specification](http://ecma262-5.com/ELS5_HTML.htm#Section_8.5), number types have a maximum value -of 2^53. Beyond that, behaviour might be unexpected. However, real long support requires the full 64 bits -with the possibility to perform bitwise operations on the value for varint en-/decoding. So, to enable true long support -in ByteBuffer.js, it optionally depends on [Long.js](https://github.com/dcodeIO/Long.js), which actually utilizes two -32 bit numbers internally. If you do not require long support at all, you can skip it and save the additional bandwidth. -On node, long support is available by default through the [long](https://npmjs.org/package/long) dependency. +API +--- +* [View the API documentation](https://github.com/dcodeIO/bytebuffer.js/wiki/API) +* [Check the wiki](https://github.com/dcodeIO/bytebuffer.js/wiki) Downloads --------- -* [ZIP-Archive](https://github.com/dcodeIO/ByteBuffer.js/archive/master.zip) -* [Tarball](https://github.com/dcodeIO/ByteBuffer.js/tarball/master) - -Documentation -------------- -* [View documentation](http://htmlpreview.github.com/?http://github.com/dcodeIO/ByteBuffer.js/master/docs/ByteBuffer.html) - -Tests (& Examples) [![Build Status](https://travis-ci.org/dcodeIO/ByteBuffer.js.png?branch=master)](https://travis-ci.org/dcodeIO/ByteBuffer.js) ------------------- -* [View source](https://github.com/dcodeIO/ByteBuffer.js/blob/master/tests/suite.js) -* [View report](https://travis-ci.org/dcodeIO/ByteBuffer.js) - -Prerequisites to run it against IE<10, FF<15, Chrome<9 etc. ------------------------------------------------------------ -* Working ArrayBuffer & DataView implementations (i.e. use a [polyfill](https://github.com/inexorabletash/polyfill#typed-arrays-polyfill)) - -Usage with Closure Compiler's advanced optimizations ----------------------------------------------------- -You basically have the following three options: - -#### ByteBuffer.js as external dependency #### -If you compile your code but want to use ByteBuffer.js as an external dependency that's not actually compiled "into" -your project, add the provided [externs file](https://github.com/dcodeIO/ByteBuffer.js/blob/master/externs/ByteBuffer.js) -to your compilation step (which usually excludes compilation of ByteBuffer.js). - -#### ByteBuffer.js compiled into your project and exposed #### -Use [ByteBuffer.js](https://github.com/dcodeIO/ByteBuffer.js/blob/master/ByteBuffer.js) if you want the ByteBuffer class -to be exposed to the outside world (of JavaScript) so it can be called by external scripts. This also removes the -requirement of using externs but the compiler will also keep possibly unused code. +* [Distributions](https://github.com/dcodeIO/bytebuffer.js/tree/master/dist) +* [ZIP-Archive](https://github.com/dcodeIO/bytebuffer.js/archive/master.zip) +* [Tarball](https://github.com/dcodeIO/bytebuffer.js/tarball/master) -#### ByteBuffer.js fully compiled into your project #### -Use [ByteBuffer.noexpose.js](https://github.com/dcodeIO/ByteBuffer.js/blob/master/ByteBuffer.noexpose.js) if you want -the ByteBuffer class to be fully integrated into your (single file) project. Of course no external scripts will be able -to call it or its method (trivially) because quite everything will become renamed, some parts inlined and moved around. -This will also allow the compiler to actually remove unused code. +Support for IE<10, FF<15, Chrome<9 etc. +--------------------------------------- +* Use bytebuffer-dataview with a polyfill ([see](https://github.com/dcodeIO/bytebuffer.js/tree/master/dist)) Contributors ------------ -[Dretch](https://github.com/Dretch) (IE8 comp.) +[Dretch](https://github.com/Dretch) (IE8 compatibility) License ------- -Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.html \ No newline at end of file +**License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) - Logo derived from [W3C HTML5 Logos](http://www.w3.org/html/logo/) (CC A 3.0) diff --git a/bower.json b/bower.json index c1cc5d9..a6cee3a 100644 --- a/bower.json +++ b/bower.json @@ -1,12 +1,12 @@ { "name": "bytebuffer", - "version": "1.4.0", + "version": "5.0.1", "author": "Daniel Wirtz ", - "description": "ByteBuffer.js: A Java-like, Netty-inspired ByteBuffer implementation using typed arrays.", - "main": "ByteBuffer.js", + "description": "A full-featured ByteBuffer implementation using typed arrays.", + "main": "dist/bytebuffer.js", "keywords": ["net", "array", "buffer", "arraybuffer", "typed array", "bytebuffer", "json", "websocket", "webrtc"], "dependencies": { "long": "latest" }, "license": "Apache-2.0" -} \ No newline at end of file +} diff --git a/build.js b/build.js deleted file mode 100644 index fd1e7d5..0000000 --- a/build.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright 2013 Daniel Wirtz - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/** - * ByteBuffer.js Build Script (c) 2013 Daniel Wirtz - * Released under the Apache License, Version 2.0 - * see: https://github.com/dcodeIO/ByteBuffer.js for details - */ - -var Preprocessor = require("preprocessor"), - fs = require("fs"); - -var pp = new Preprocessor(fs.readFileSync(__dirname+"/src/ByteBuffer.js"), __dirname+"/src"); -fs.writeFileSync(__dirname+"/ByteBuffer.js", pp.process()); diff --git a/bytebuffer.png b/bytebuffer.png new file mode 100644 index 0000000..d31cd6b Binary files /dev/null and b/bytebuffer.png differ diff --git a/dist/README.md b/dist/README.md new file mode 100644 index 0000000..8303d70 --- /dev/null +++ b/dist/README.md @@ -0,0 +1,47 @@ +Distributions +============= + +ByteBuffer.js uses either ArrayBuffers in the browser or Buffers under node.js. + +### Browser: [ArrayBuffer](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)-backed + +##### Accessed through Typed Arrays + +Using Typed Arrays here is pretty much ideal, but it [requires a somewhat recent browser](http://caniuse.com/#feat=typedarrays). + +* **[bytebuffer.js](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer.js)** + uses an ArrayBuffer as its backing buffer, accessed through an [Uint8Array](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array). + +* **[bytebuffer.min.js](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer.min.js)** + has been compiled with Closure Compiler using advanced optimizations. + +* **[bytebuffer.min.js.gz](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer.min.js.gz)** + has also been gzipped using `-9`. + +* **[bytebuffer.min.map](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer.min.map)** + is the source map generated by Closure Compiler. + +##### Accessed through a DataView ([polyfill](https://github.com/inexorabletash/polyfill/blob/master/typedarray.js) compatible) + +Using DataViews is [generally slower](https://github.com/dcodeIO/ByteBuffer.js/issues/16) but works well with common polyfills for +older browsers (avoids array access operators on Typed Arrays). + +* **[bytebuffer-dataview.js](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer-dataview.js)** + uses an ArrayBuffer as its backing buffer, accessed through a [DataView](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/DataView). + +* **[bytebuffer-dataview.min.js](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer-dataview.min.js)** + has been compiled with Closure Compiler using advanced optimizations. + +* **[bytebuffer-dataview.min.js.gz](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer-dataview.min.js.gz)** + has also been gzipped using `-9`. + +* **[bytebuffer-dataview.min.map](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer-dataview.min.map)** + is the source map generated by Closure Compiler. + +### node.js: [Buffer](https://nodejs.org/api/buffer.html)-backed + +* **[bytebuffer-node.js](https://raw.githubusercontent.com/dcodeIO/ByteBuffer.js/master/dist/bytebuffer-node.js)** + uses a [node Buffer](https://nodejs.org/api/buffer.html) as its backing buffer and accessor. + +Also available as `bytebuffer` on [npm](https://www.npmjs.org/package/bytebuffer) and +[bower](http://bower.io/search/?q=bytebuffer). diff --git a/dist/bytebuffer-dataview.js b/dist/bytebuffer-dataview.js new file mode 100644 index 0000000..c4d04a2 --- /dev/null +++ b/dist/bytebuffer-dataview.js @@ -0,0 +1,3461 @@ +/* + Copyright 2013-2014 Daniel Wirtz + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +/** + * @license bytebuffer.js (c) 2015 Daniel Wirtz + * Backing buffer: ArrayBuffer, Accessor: DataView + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/bytebuffer.js for details + */ +(function(global, factory) { + + /* AMD */ if (typeof define === 'function' && define["amd"]) + define(["long"], factory); + /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) + module['exports'] = (function() { + var Long; try { Long = require("long"); } catch (e) {} + return factory(Long); + })(); + /* Global */ else + (global["dcodeIO"] = global["dcodeIO"] || {})["ByteBuffer"] = factory(global["dcodeIO"]["Long"]); + +})(this, function(Long) { + "use strict"; + + /** + * Constructs a new ByteBuffer. + * @class The swiss army knife for binary data in JavaScript. + * @exports ByteBuffer + * @constructor + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @expose + */ + var ByteBuffer = function(capacity, littleEndian, noAssert) { + if (typeof capacity === 'undefined') + capacity = ByteBuffer.DEFAULT_CAPACITY; + if (typeof littleEndian === 'undefined') + littleEndian = ByteBuffer.DEFAULT_ENDIAN; + if (typeof noAssert === 'undefined') + noAssert = ByteBuffer.DEFAULT_NOASSERT; + if (!noAssert) { + capacity = capacity | 0; + if (capacity < 0) + throw RangeError("Illegal capacity"); + littleEndian = !!littleEndian; + noAssert = !!noAssert; + } + + /** + * Backing ArrayBuffer. + * @type {!ArrayBuffer} + * @expose + */ + this.buffer = capacity === 0 ? EMPTY_BUFFER : new ArrayBuffer(capacity); + + /** + * DataView utilized to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`. + * @type {?DataView} + * @expose + */ + this.view = capacity === 0 ? null : new DataView(this.buffer); + + /** + * Absolute read/write offset. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.offset = 0; + + /** + * Marked offset. + * @type {number} + * @expose + * @see ByteBuffer#mark + * @see ByteBuffer#reset + */ + this.markedOffset = -1; + + /** + * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.limit = capacity; + + /** + * Whether to use little endian byte order, defaults to `false` for big endian. + * @type {boolean} + * @expose + */ + this.littleEndian = littleEndian; + + /** + * Whether to skip assertions of offsets and values, defaults to `false`. + * @type {boolean} + * @expose + */ + this.noAssert = noAssert; + }; + + /** + * ByteBuffer version. + * @type {string} + * @const + * @expose + */ + ByteBuffer.VERSION = "5.0.1"; + + /** + * Little endian constant that can be used instead of its boolean value. Evaluates to `true`. + * @type {boolean} + * @const + * @expose + */ + ByteBuffer.LITTLE_ENDIAN = true; + + /** + * Big endian constant that can be used instead of its boolean value. Evaluates to `false`. + * @type {boolean} + * @const + * @expose + */ + ByteBuffer.BIG_ENDIAN = false; + + /** + * Default initial capacity of `16`. + * @type {number} + * @expose + */ + ByteBuffer.DEFAULT_CAPACITY = 16; + + /** + * Default endianess of `false` for big endian. + * @type {boolean} + * @expose + */ + ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN; + + /** + * Default no assertions flag of `false`. + * @type {boolean} + * @expose + */ + ByteBuffer.DEFAULT_NOASSERT = false; + + /** + * A `Long` class for representing a 64-bit two's-complement integer value. May be `null` if Long.js has not been loaded + * and int64 support is not available. + * @type {?Long} + * @const + * @see https://github.com/dcodeIO/long.js + * @expose + */ + ByteBuffer.Long = Long || null; + + /** + * @alias ByteBuffer.prototype + * @inner + */ + var ByteBufferPrototype = ByteBuffer.prototype; + + /** + * An indicator used to reliably determine if an object is a ByteBuffer or not. + * @type {boolean} + * @const + * @expose + * @private + */ + ByteBufferPrototype.__isByteBuffer__; + + Object.defineProperty(ByteBufferPrototype, "__isByteBuffer__", { + value: true, + enumerable: false, + configurable: false + }); + + // helpers + + /** + * @type {!ArrayBuffer} + * @inner + */ + var EMPTY_BUFFER = new ArrayBuffer(0); + + /** + * String.fromCharCode reference for compile-time renaming. + * @type {function(...number):string} + * @inner + */ + var stringFromCharCode = String.fromCharCode; + + /** + * Creates a source function for a string. + * @param {string} s String to read from + * @returns {function():number|null} Source function returning the next char code respectively `null` if there are + * no more characters left. + * @throws {TypeError} If the argument is invalid + * @inner + */ + function stringSource(s) { + var i=0; return function() { + return i < s.length ? s.charCodeAt(i++) : null; + }; + } + + /** + * Creates a destination function for a string. + * @returns {function(number=):undefined|string} Destination function successively called with the next char code. + * Returns the final string when called without arguments. + * @inner + */ + function stringDestination() { + var cs = [], ps = []; return function() { + if (arguments.length === 0) + return ps.join('')+stringFromCharCode.apply(String, cs); + if (cs.length + arguments.length > 1024) + ps.push(stringFromCharCode.apply(String, cs)), + cs.length = 0; + Array.prototype.push.apply(cs, arguments); + }; + } + + /** + * Gets the accessor type. + * @returns {Function} `Buffer` under node.js, `Uint8Array` respectively `DataView` in the browser (classes) + * @expose + */ + ByteBuffer.accessor = function() { + return DataView; + }; + /** + * Allocates a new ByteBuffer backed by a buffer of the specified capacity. + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} + * @expose + */ + ByteBuffer.allocate = function(capacity, littleEndian, noAssert) { + return new ByteBuffer(capacity, littleEndian, noAssert); + }; + + /** + * Concatenates multiple ByteBuffers into one. + * @param {!Array.} buffers Buffers to concatenate + * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary", + * defaults to "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults + * to {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} Concatenated ByteBuffer + * @expose + */ + ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) { + if (typeof encoding === 'boolean' || typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + var capacity = 0; + for (var i=0, k=buffers.length, length; i 0) capacity += length; + } + if (capacity === 0) + return new ByteBuffer(0, littleEndian, noAssert); + var bb = new ByteBuffer(capacity, littleEndian, noAssert), + bi; + var view = new Uint8Array(bb.buffer); + i=0; while (i} buffer Anything that can be wrapped + * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to + * "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer` + * @expose + */ + ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) { + if (typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + if (typeof buffer === 'string') { + if (typeof encoding === 'undefined') + encoding = "utf8"; + switch (encoding) { + case "base64": + return ByteBuffer.fromBase64(buffer, littleEndian); + case "hex": + return ByteBuffer.fromHex(buffer, littleEndian); + case "binary": + return ByteBuffer.fromBinary(buffer, littleEndian); + case "utf8": + return ByteBuffer.fromUTF8(buffer, littleEndian); + case "debug": + return ByteBuffer.fromDebug(buffer, littleEndian); + default: + throw Error("Unsupported encoding: "+encoding); + } + } + if (buffer === null || typeof buffer !== 'object') + throw TypeError("Illegal buffer"); + var bb; + if (ByteBuffer.isByteBuffer(buffer)) { + bb = ByteBufferPrototype.clone.call(buffer); + bb.markedOffset = -1; + return bb; + } + if (buffer instanceof Uint8Array) { // Extract ArrayBuffer from Uint8Array + bb = new ByteBuffer(0, littleEndian, noAssert); + if (buffer.length > 0) { // Avoid references to more than one EMPTY_BUFFER + bb.buffer = buffer.buffer; + bb.offset = buffer.byteOffset; + bb.limit = buffer.byteOffset + buffer.byteLength; + bb.view = new DataView(buffer.buffer); + } + } else if (buffer instanceof ArrayBuffer) { // Reuse ArrayBuffer + bb = new ByteBuffer(0, littleEndian, noAssert); + if (buffer.byteLength > 0) { + bb.buffer = buffer; + bb.offset = 0; + bb.limit = buffer.byteLength; + bb.view = buffer.byteLength > 0 ? new DataView(buffer) : null; + } + } else if (Object.prototype.toString.call(buffer) === "[object Array]") { // Create from octets + bb = new ByteBuffer(buffer.length, littleEndian, noAssert); + bb.limit = buffer.length; + for (var i=0; i} value Array of booleans to write + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ + ByteBufferPrototype.writeBitSet = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (!(value instanceof Array)) + throw TypeError("Illegal BitSet: Not an array"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + + var start = offset, + bits = value.length, + bytes = (bits >> 3), + bit = 0, + k; + + offset += this.writeVarint32(bits,offset); + + while(bytes--) { + k = (!!value[bit++] & 1) | + ((!!value[bit++] & 1) << 1) | + ((!!value[bit++] & 1) << 2) | + ((!!value[bit++] & 1) << 3) | + ((!!value[bit++] & 1) << 4) | + ((!!value[bit++] & 1) << 5) | + ((!!value[bit++] & 1) << 6) | + ((!!value[bit++] & 1) << 7); + this.writeByte(k,offset++); + } + + if(bit < bits) { + var m = 0; k = 0; + while(bit < bits) k = k | ((!!value[bit++] & 1) << (m++)); + this.writeByte(k,offset++); + } + + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + } + + /** + * Reads a BitSet as an array of booleans. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {Array + * @expose + */ + ByteBufferPrototype.readBitSet = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + + var ret = this.readVarint32(offset), + bits = ret.value, + bytes = (bits >> 3), + bit = 0, + value = [], + k; + + offset += ret.length; + + while(bytes--) { + k = this.readByte(offset++); + value[bit++] = !!(k & 0x01); + value[bit++] = !!(k & 0x02); + value[bit++] = !!(k & 0x04); + value[bit++] = !!(k & 0x08); + value[bit++] = !!(k & 0x10); + value[bit++] = !!(k & 0x20); + value[bit++] = !!(k & 0x40); + value[bit++] = !!(k & 0x80); + } + + if(bit < bits) { + var m = 0; + k = this.readByte(offset++); + while(bit < bits) value[bit++] = !!((k >> (m++)) & 1); + } + + if (relative) { + this.offset = offset; + } + return value; + } + /** + * Reads the specified number of bytes. + * @param {number} length Number of bytes to read + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ + ByteBufferPrototype.readBytes = function(length, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + length > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength); + } + var slice = this.slice(offset, offset + length); + if (relative) this.offset += length; + return slice; + }; + + + // types/ints/int8 + + /** + * Writes an 8bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt8 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 1; + var capacity0 = this.buffer.byteLength; + if (offset > capacity0) + this.resize((capacity0 *= 2) > offset ? capacity0 : offset); + offset -= 1; + this.view.setInt8(offset, value); + if (relative) this.offset += 1; + return this; + }; + + /** + * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8; + + /** + * Reads an 8bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt8 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var value = this.view.getInt8(offset); + if (relative) this.offset += 1; + return value; + }; + + /** + * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8; + + /** + * Writes an 8bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint8 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 1; + var capacity1 = this.buffer.byteLength; + if (offset > capacity1) + this.resize((capacity1 *= 2) > offset ? capacity1 : offset); + offset -= 1; + this.view.setUint8(offset, value); + if (relative) this.offset += 1; + return this; + }; + + /** + * Writes an 8bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt8 = ByteBufferPrototype.writeUint8; + + /** + * Reads an 8bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUint8 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var value = this.view.getUint8(offset); + if (relative) this.offset += 1; + return value; + }; + + /** + * Reads an 8bit unsigned integer. This is an alias of {@link ByteBuffer#readUint8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUInt8 = ByteBufferPrototype.readUint8; + + // types/ints/int16 + + /** + * Writes a 16bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeInt16 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 2; + var capacity2 = this.buffer.byteLength; + if (offset > capacity2) + this.resize((capacity2 *= 2) > offset ? capacity2 : offset); + offset -= 2; + this.view.setInt16(offset, value, this.littleEndian); + if (relative) this.offset += 2; + return this; + }; + + /** + * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16; + + /** + * Reads a 16bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readInt16 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 2 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength); + } + var value = this.view.getInt16(offset, this.littleEndian); + if (relative) this.offset += 2; + return value; + }; + + /** + * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16; + + /** + * Writes a 16bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeUint16 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 2; + var capacity3 = this.buffer.byteLength; + if (offset > capacity3) + this.resize((capacity3 *= 2) > offset ? capacity3 : offset); + offset -= 2; + this.view.setUint16(offset, value, this.littleEndian); + if (relative) this.offset += 2; + return this; + }; + + /** + * Writes a 16bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeUInt16 = ByteBufferPrototype.writeUint16; + + /** + * Reads a 16bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readUint16 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 2 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength); + } + var value = this.view.getUint16(offset, this.littleEndian); + if (relative) this.offset += 2; + return value; + }; + + /** + * Reads a 16bit unsigned integer. This is an alias of {@link ByteBuffer#readUint16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readUInt16 = ByteBufferPrototype.readUint16; + + // types/ints/int32 + + /** + * Writes a 32bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeInt32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity4 = this.buffer.byteLength; + if (offset > capacity4) + this.resize((capacity4 *= 2) > offset ? capacity4 : offset); + offset -= 4; + this.view.setInt32(offset, value, this.littleEndian); + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32; + + /** + * Reads a 32bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = this.view.getInt32(offset, this.littleEndian); + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32; + + /** + * Writes a 32bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeUint32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity5 = this.buffer.byteLength; + if (offset > capacity5) + this.resize((capacity5 *= 2) > offset ? capacity5 : offset); + offset -= 4; + this.view.setUint32(offset, value, this.littleEndian); + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeUInt32 = ByteBufferPrototype.writeUint32; + + /** + * Reads a 32bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUint32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = this.view.getUint32(offset, this.littleEndian); + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit unsigned integer. This is an alias of {@link ByteBuffer#readUint32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUInt32 = ByteBufferPrototype.readUint32; + + // types/ints/int64 + + if (Long) { + + /** + * Writes a 64bit signed integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + offset += 8; + var capacity6 = this.buffer.byteLength; + if (offset > capacity6) + this.resize((capacity6 *= 2) > offset ? capacity6 : offset); + offset -= 8; + if (this.littleEndian) { + this.view.setInt32(offset , value.low , true); + this.view.setInt32(offset+4, value.high, true); + } else { + this.view.setInt32(offset , value.high, false); + this.view.setInt32(offset+4, value.low , false); + } + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64; + + /** + * Reads a 64bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readInt64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var value = this.littleEndian + ? new Long(this.view.getInt32(offset , true ), this.view.getInt32(offset+4, true ), false) + : new Long(this.view.getInt32(offset+4, false), this.view.getInt32(offset , false), false); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64; + + /** + * Writes a 64bit unsigned integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + offset += 8; + var capacity7 = this.buffer.byteLength; + if (offset > capacity7) + this.resize((capacity7 *= 2) > offset ? capacity7 : offset); + offset -= 8; + if (this.littleEndian) { + this.view.setInt32(offset , value.low , true); + this.view.setInt32(offset+4, value.high, true); + } else { + this.view.setInt32(offset , value.high, false); + this.view.setInt32(offset+4, value.low , false); + } + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint64}. + * @function + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt64 = ByteBufferPrototype.writeUint64; + + /** + * Reads a 64bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUint64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var value = this.littleEndian + ? new Long(this.view.getInt32(offset , true ), this.view.getInt32(offset+4, true ), true) + : new Long(this.view.getInt32(offset+4, false), this.view.getInt32(offset , false), true); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit unsigned integer. This is an alias of {@link ByteBuffer#readUint64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUInt64 = ByteBufferPrototype.readUint64; + + } // Long + + + // types/floats/float32 + + /** + * Writes a 32bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity8 = this.buffer.byteLength; + if (offset > capacity8) + this.resize((capacity8 *= 2) > offset ? capacity8 : offset); + offset -= 4; + this.view.setFloat32(offset, value, this.littleEndian); + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32; + + /** + * Reads a 32bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = this.view.getFloat32(offset, this.littleEndian); + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32; + + // types/floats/float64 + + /** + * Writes a 64bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 8; + var capacity9 = this.buffer.byteLength; + if (offset > capacity9) + this.resize((capacity9 *= 2) > offset ? capacity9 : offset); + offset -= 8; + this.view.setFloat64(offset, value, this.littleEndian); + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64; + + /** + * Reads a 64bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var value = this.view.getFloat64(offset, this.littleEndian); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64; + + + // types/varints/varint32 + + /** + * Maximum number of bytes required to store a 32bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT32_BYTES = 5; + + /** + * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer. + * @param {number} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES} + * @expose + */ + ByteBuffer.calculateVarint32 = function(value) { + // ref: src/google/protobuf/io/coded_stream.cc + value = value >>> 0; + if (value < 1 << 7 ) return 1; + else if (value < 1 << 14) return 2; + else if (value < 1 << 21) return 3; + else if (value < 1 << 28) return 4; + else return 5; + }; + + /** + * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding. + * @param {number} n Signed 32bit integer + * @returns {number} Unsigned zigzag encoded 32bit integer + * @expose + */ + ByteBuffer.zigZagEncode32 = function(n) { + return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h + }; + + /** + * Decodes a zigzag encoded signed 32bit integer. + * @param {number} n Unsigned zigzag encoded 32bit integer + * @returns {number} Signed 32bit integer + * @expose + */ + ByteBuffer.zigZagDecode32 = function(n) { + return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h + }; + + /** + * Writes a 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeVarint32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var size = ByteBuffer.calculateVarint32(value), + b; + offset += size; + var capacity10 = this.buffer.byteLength; + if (offset > capacity10) + this.resize((capacity10 *= 2) > offset ? capacity10 : offset); + offset -= size; + value >>>= 0; + while (value >= 0x80) { + b = (value & 0x7f) | 0x80; + this.view.setUint8(offset++, b); + value >>>= 7; + } + this.view.setUint8(offset++, value); + if (relative) { + this.offset = offset; + return this; + } + return size; + }; + + /** + * Writes a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) { + return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset); + }; + + /** + * Reads a 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available + * to fully decode the varint. + * @expose + */ + ByteBufferPrototype.readVarint32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var c = 0, + value = 0 >>> 0, + b; + do { + if (!this.noAssert && offset > this.limit) { + var err = Error("Truncated"); + err['truncated'] = true; + throw err; + } + b = this.view.getUint8(offset++); + if (c < 5) + value |= (b & 0x7f) << (7*c); + ++c; + } while ((b & 0x80) !== 0); + value |= 0; + if (relative) { + this.offset = offset; + return value; + } + return { + "value": value, + "length": c + }; + }; + + /** + * Reads a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint32ZigZag = function(offset) { + var val = this.readVarint32(offset); + if (typeof val === 'object') + val["value"] = ByteBuffer.zigZagDecode32(val["value"]); + else + val = ByteBuffer.zigZagDecode32(val); + return val; + }; + + // types/varints/varint64 + + if (Long) { + + /** + * Maximum number of bytes required to store a 64bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT64_BYTES = 10; + + /** + * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer. + * @param {number|!Long} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES} + * @expose + */ + ByteBuffer.calculateVarint64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + // ref: src/google/protobuf/io/coded_stream.cc + var part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + if (part2 == 0) { + if (part1 == 0) { + if (part0 < 1 << 14) + return part0 < 1 << 7 ? 1 : 2; + else + return part0 < 1 << 21 ? 3 : 4; + } else { + if (part1 < 1 << 14) + return part1 < 1 << 7 ? 5 : 6; + else + return part1 < 1 << 21 ? 7 : 8; + } + } else + return part2 < 1 << 7 ? 9 : 10; + }; + + /** + * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding. + * @param {number|!Long} value Signed long + * @returns {!Long} Unsigned zigzag encoded long + * @expose + */ + ByteBuffer.zigZagEncode64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned(); + }; + + /** + * Decodes a zigzag encoded signed 64bit integer. + * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number + * @returns {!Long} Signed long + * @expose + */ + ByteBuffer.zigZagDecode64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned(); + }; + + /** + * Writes a 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + var size = ByteBuffer.calculateVarint64(value), + part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + offset += size; + var capacity11 = this.buffer.byteLength; + if (offset > capacity11) + this.resize((capacity11 *= 2) > offset ? capacity11 : offset); + offset -= size; + switch (size) { + case 10: this.view.setUint8(offset+9, (part2 >>> 7) & 0x01); + case 9 : this.view.setUint8(offset+8, size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F); + case 8 : this.view.setUint8(offset+7, size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F); + case 7 : this.view.setUint8(offset+6, size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F); + case 6 : this.view.setUint8(offset+5, size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F); + case 5 : this.view.setUint8(offset+4, size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F); + case 4 : this.view.setUint8(offset+3, size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F); + case 3 : this.view.setUint8(offset+2, size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F); + case 2 : this.view.setUint8(offset+1, size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F); + case 1 : this.view.setUint8(offset , size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F); + } + if (relative) { + this.offset += size; + return this; + } else { + return size; + } + }; + + /** + * Writes a zig-zag encoded 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) { + return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); + }; + + /** + * Reads a 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + // ref: src/google/protobuf/io/coded_stream.cc + var start = offset, + part0 = 0, + part1 = 0, + part2 = 0, + b = 0; + b = this.view.getUint8(offset++); part0 = (b & 0x7F) ; if (b & 0x80) { + b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 7; if (b & 0x80) { + b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 14; if (b & 0x80) { + b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 21; if (b & 0x80) { + b = this.view.getUint8(offset++); part1 = (b & 0x7F) ; if (b & 0x80) { + b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 7; if (b & 0x80) { + b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 14; if (b & 0x80) { + b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 21; if (b & 0x80) { + b = this.view.getUint8(offset++); part2 = (b & 0x7F) ; if (b & 0x80) { + b = this.view.getUint8(offset++); part2 |= (b & 0x7F) << 7; if (b & 0x80) { + throw Error("Buffer overrun"); }}}}}}}}}} + var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false); + if (relative) { + this.offset = offset; + return value; + } else { + return { + 'value': value, + 'length': offset-start + }; + } + }; + + /** + * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64ZigZag = function(offset) { + var val = this.readVarint64(offset); + if (val && val['value'] instanceof Long) + val["value"] = ByteBuffer.zigZagDecode64(val["value"]); + else + val = ByteBuffer.zigZagDecode64(val); + return val; + }; + + } // Long + + + // types/strings/cstring + + /** + * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL + * characters itself. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * contained in `str` + 1 if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeCString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + var i, + k = str.length; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + for (i=0; i>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + // UTF8 strings do not contain zero bytes in between except for the zero character, so: + k = utfx.calculateUTF16asUTF8(stringSource(str))[1]; + offset += k+1; + var capacity12 = this.buffer.byteLength; + if (offset > capacity12) + this.resize((capacity12 *= 2) > offset ? capacity12 : offset); + offset -= k+1; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view.setUint8(offset++, b); + }.bind(this)); + this.view.setUint8(offset++, 0); + if (relative) { + this.offset = offset; + return this; + } + return k; + }; + + /** + * Reads a NULL-terminated UTF8 encoded string. For this to work the string read must not contain any NULL characters + * itself. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readCString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var start = offset, + temp; + // UTF8 strings do not contain zero bytes in between except for the zero character itself, so: + var sd, b = -1; + utfx.decodeUTF8toUTF16(function() { + if (b === 0) return null; + if (offset >= this.limit) + throw RangeError("Illegal range: Truncated data, "+offset+" < "+this.limit); + b = this.view.getUint8(offset++); + return b === 0 ? null : b; + }.bind(this), sd = stringDestination(), true); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + }; + + // types/strings/istring + + /** + * Writes a length as uint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ + ByteBufferPrototype.writeIString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var start = offset, + k; + k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1]; + offset += 4+k; + var capacity13 = this.buffer.byteLength; + if (offset > capacity13) + this.resize((capacity13 *= 2) > offset ? capacity13 : offset); + offset -= 4+k; + this.view.setUint32(offset, k, this.littleEndian); + offset += 4; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view.setUint8(offset++, b); + }.bind(this)); + if (offset !== start + 4 + k) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+4+k)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Reads a length as uint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ + ByteBufferPrototype.readIString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var start = offset; + var len = this.readUint32(offset); + var str = this.readUTF8String(len, ByteBuffer.METRICS_BYTES, offset += 4); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } + }; + + // types/strings/utf8string + + /** + * Metrics representing number of UTF8 characters. Evaluates to `c`. + * @type {string} + * @const + * @expose + */ + ByteBuffer.METRICS_CHARS = 'c'; + + /** + * Metrics representing number of bytes. Evaluates to `b`. + * @type {string} + * @const + * @expose + */ + ByteBuffer.METRICS_BYTES = 'b'; + + /** + * Writes an UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeUTF8String = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var k; + var start = offset; + k = utfx.calculateUTF16asUTF8(stringSource(str))[1]; + offset += k; + var capacity14 = this.buffer.byteLength; + if (offset > capacity14) + this.resize((capacity14 *= 2) > offset ? capacity14 : offset); + offset -= k; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view.setUint8(offset++, b); + }.bind(this)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}. + * @function + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String; + + /** + * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's + * `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 characters + * @expose + */ + ByteBuffer.calculateUTF8Chars = function(str) { + return utfx.calculateUTF16asUTF8(stringSource(str))[0]; + }; + + /** + * Calculates the number of UTF8 bytes of a string. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ + ByteBuffer.calculateUTF8Bytes = function(str) { + return utfx.calculateUTF16asUTF8(stringSource(str))[1]; + }; + + /** + * Calculates the number of UTF8 bytes of a string. This is an alias of {@link ByteBuffer.calculateUTF8Bytes}. + * @function + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ + ByteBuffer.calculateString = ByteBuffer.calculateUTF8Bytes; + + /** + * Reads an UTF8 encoded string. + * @param {number} length Number of characters or bytes to read. + * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readUTF8String = function(length, metrics, offset) { + if (typeof metrics === 'number') { + offset = metrics; + metrics = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS; + if (!this.noAssert) { + if (typeof length !== 'number' || length % 1 !== 0) + throw TypeError("Illegal length: "+length+" (not an integer)"); + length |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var i = 0, + start = offset, + sd; + if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser + sd = stringDestination(); + utfx.decodeUTF8(function() { + return i < length && offset < this.limit ? this.view.getUint8(offset++) : null; + }.bind(this), function(cp) { + ++i; utfx.UTF8toUTF16(cp, sd); + }); + if (i !== length) + throw RangeError("Illegal range: Truncated data, "+i+" == "+length); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + } else if (metrics === ByteBuffer.METRICS_BYTES) { + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + length > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength); + } + var k = offset + length; + utfx.decodeUTF8toUTF16(function() { + return offset < k ? this.view.getUint8(offset++) : null; + }.bind(this), sd = stringDestination(), this.noAssert); + if (offset !== k) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+k); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + 'string': sd(), + 'length': offset - start + }; + } + } else + throw TypeError("Unsupported metrics: "+metrics); + }; + + /** + * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}. + * @function + * @param {number} length Number of characters or bytes to read + * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String; + + // types/strings/vstring + + /** + * Writes a length as varint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ + ByteBufferPrototype.writeVString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var start = offset, + k, l; + k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1]; + l = ByteBuffer.calculateVarint32(k); + offset += l+k; + var capacity15 = this.buffer.byteLength; + if (offset > capacity15) + this.resize((capacity15 *= 2) > offset ? capacity15 : offset); + offset -= l+k; + offset += this.writeVarint32(k, offset); + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view.setUint8(offset++, b); + }.bind(this)); + if (offset !== start+k+l) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+k+l)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Reads a length as varint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ + ByteBufferPrototype.readVString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var start = offset; + var len = this.readVarint32(offset); + var str = this.readUTF8String(len['value'], ByteBuffer.METRICS_BYTES, offset += len['length']); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } + }; + + + /** + * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended + * data's length. + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its offsets + * will be modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|` + * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|` + */ + ByteBufferPrototype.append = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var length = source.limit - source.offset; + if (length <= 0) return this; // Nothing to append + offset += length; + var capacity16 = this.buffer.byteLength; + if (offset > capacity16) + this.resize((capacity16 *= 2) > offset ? capacity16 : offset); + offset -= length; + new Uint8Array(this.buffer, offset).set(new Uint8Array(source.buffer).subarray(source.offset, source.limit)); + source.offset += length; + if (relative) this.offset += length; + return this; + }; + + /** + * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents at and after the + specified offset up to the length of this ByteBuffer's data. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#append + */ + ByteBufferPrototype.appendTo = function(target, offset) { + target.append(this, offset); + return this; + }; + + /** + * Writes a payload of bytes. This is an alias of {@link ByteBuffer#append}. + * @function + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to write. If `source` is a ByteBuffer, its offsets + * will be modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeBytes = ByteBufferPrototype.append; + /** + * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to + * disable them if your code already makes sure that everything is valid. + * @param {boolean} assert `true` to enable assertions, otherwise `false` + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.assert = function(assert) { + this.noAssert = !assert; + return this; + }; + + /** + * Gets the capacity of this ByteBuffer's backing buffer. + * @returns {number} Capacity of the backing buffer + * @expose + */ + ByteBufferPrototype.capacity = function() { + return this.buffer.byteLength; + }; + /** + * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the + * backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.clear = function() { + this.offset = 0; + this.limit = this.buffer.byteLength; + this.markedOffset = -1; + return this; + }; + + /** + * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset}, + * {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}. + * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false` + * @returns {!ByteBuffer} Cloned instance + * @expose + */ + ByteBufferPrototype.clone = function(copy) { + var bb = new ByteBuffer(0, this.littleEndian, this.noAssert); + if (copy) { + bb.buffer = new ArrayBuffer(this.buffer.byteLength); + new Uint8Array(bb.buffer).set(this.buffer); + bb.view = new DataView(bb.buffer); + } else { + bb.buffer = this.buffer; + bb.view = this.view; + } + bb.offset = this.offset; + bb.markedOffset = this.markedOffset; + bb.limit = this.limit; + return bb; + }; + + /** + * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes + * between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and + * adapt {@link ByteBuffer#markedOffset} to the same relative position if set. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.compact = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === 0 && end === this.buffer.byteLength) + return this; // Already compacted + var len = end - begin; + if (len === 0) { + this.buffer = EMPTY_BUFFER; + this.view = null; + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = 0; + return this; + } + var buffer = new ArrayBuffer(len); + new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(begin, end)); + this.buffer = buffer; + this.view = new DataView(buffer); + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = len; + return this; + }; + + /** + * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Copy + * @expose + */ + ByteBufferPrototype.copy = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === end) + return new ByteBuffer(0, this.littleEndian, this.noAssert); + var capacity = end - begin, + bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert); + bb.offset = 0; + bb.limit = capacity; + if (bb.markedOffset >= 0) bb.markedOffset -= begin; + this.copyTo(bb, 0, begin, end); + return bb; + }; + + /** + * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset} + * by the number of bytes copied if omitted. + * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the + * number of bytes copied if omitted. + * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) { + var relative, + targetRelative; + if (!this.noAssert) { + if (!ByteBuffer.isByteBuffer(target)) + throw TypeError("Illegal target: Not a ByteBuffer"); + } + targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0; + sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0; + sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0; + + if (targetOffset < 0 || targetOffset > target.buffer.byteLength) + throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+target.buffer.byteLength); + if (sourceOffset < 0 || sourceLimit > this.buffer.byteLength) + throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+this.buffer.byteLength); + + var len = sourceLimit - sourceOffset; + if (len === 0) + return target; // Nothing to copy + + target.ensureCapacity(targetOffset + len); + + new Uint8Array(target.buffer).set(new Uint8Array(this.buffer).subarray(sourceOffset, sourceLimit), targetOffset); + + if (relative) this.offset += len; + if (targetRelative) target.offset += len; + + return this; + }; + + /** + * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the + * current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity, + * the required capacity will be used instead. + * @param {number} capacity Required capacity + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.ensureCapacity = function(capacity) { + var current = this.buffer.byteLength; + if (current < capacity) + return this.resize((current *= 2) > capacity ? current : capacity); + return this; + }; + + /** + * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {number|string} value Byte value to fill with. If given as a string, the first character is used. + * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} this + * @expose + * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes + */ + ByteBufferPrototype.fill = function(value, begin, end) { + var relative = typeof begin === 'undefined'; + if (relative) begin = this.offset; + if (typeof value === 'string' && value.length > 0) + value = value.charCodeAt(0); + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin >= end) + return this; // Nothing to fill + while (begin < end) this.view.setUint8(begin++, value); + if (relative) this.offset = begin; + return this; + }; + + /** + * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and + * `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.flip = function() { + this.limit = this.offset; + this.offset = 0; + return this; + }; + /** + * Marks an offset on this ByteBuffer to be used later. + * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}. + * @returns {!ByteBuffer} this + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @see ByteBuffer#reset + * @expose + */ + ByteBufferPrototype.mark = function(offset) { + offset = typeof offset === 'undefined' ? this.offset : offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + this.markedOffset = offset; + return this; + }; + /** + * Sets the byte order. + * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.order = function(littleEndian) { + if (!this.noAssert) { + if (typeof littleEndian !== 'boolean') + throw TypeError("Illegal littleEndian: Not a boolean"); + } + this.littleEndian = !!littleEndian; + return this; + }; + + /** + * Switches (to) little endian byte order. + * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.LE = function(littleEndian) { + this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true; + return this; + }; + + /** + * Switches (to) big endian byte order. + * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.BE = function(bigEndian) { + this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false; + return this; + }; + /** + * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer|string|!ArrayBuffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be + * modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|` + * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|` + */ + ByteBufferPrototype.prepend = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var len = source.limit - source.offset; + if (len <= 0) return this; // Nothing to prepend + var diff = len - offset; + if (diff > 0) { // Not enough space before offset, so resize + move + var buffer = new ArrayBuffer(this.buffer.byteLength + diff); + var arrayView = new Uint8Array(buffer); + arrayView.set(new Uint8Array(this.buffer).subarray(offset, this.buffer.byteLength), len); + this.buffer = buffer; + this.view = new DataView(buffer); + this.offset += diff; + if (this.markedOffset >= 0) this.markedOffset += diff; + this.limit += diff; + offset += diff; + } else { + var arrayView = new Uint8Array(this.buffer); + } + arrayView.set(new Uint8Array(source.buffer).subarray(source.offset, source.limit), offset - len); + + source.offset = source.limit; + if (relative) + this.offset -= len; + return this; + }; + + /** + * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#prepend + */ + ByteBufferPrototype.prependTo = function(target, offset) { + target.prepend(this, offset); + return this; + }; + /** + * Prints debug information about this ByteBuffer's contents. + * @param {function(string)=} out Output function to call, defaults to console.log + * @expose + */ + ByteBufferPrototype.printDebug = function(out) { + if (typeof out !== 'function') out = console.log.bind(console); + out( + this.toString()+"\n"+ + "-------------------------------------------------------------------\n"+ + this.toDebug(/* columns */ true) + ); + }; + + /** + * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}, so this returns `limit - offset`. + * @returns {number} Remaining readable bytes. May be negative if `offset > limit`. + * @expose + */ + ByteBufferPrototype.remaining = function() { + return this.limit - this.offset; + }; + /** + * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark} + * before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been + * marked, sets `offset = 0`. + * @returns {!ByteBuffer} this + * @see ByteBuffer#mark + * @expose + */ + ByteBufferPrototype.reset = function() { + if (this.markedOffset >= 0) { + this.offset = this.markedOffset; + this.markedOffset = -1; + } else { + this.offset = 0; + } + return this; + }; + /** + * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that + * large or larger. + * @param {number} capacity Capacity required + * @returns {!ByteBuffer} this + * @throws {TypeError} If `capacity` is not a number + * @throws {RangeError} If `capacity < 0` + * @expose + */ + ByteBufferPrototype.resize = function(capacity) { + if (!this.noAssert) { + if (typeof capacity !== 'number' || capacity % 1 !== 0) + throw TypeError("Illegal capacity: "+capacity+" (not an integer)"); + capacity |= 0; + if (capacity < 0) + throw RangeError("Illegal capacity: 0 <= "+capacity); + } + if (this.buffer.byteLength < capacity) { + var buffer = new ArrayBuffer(capacity); + new Uint8Array(buffer).set(new Uint8Array(this.buffer)); + this.buffer = buffer; + this.view = new DataView(buffer); + } + return this; + }; + /** + * Reverses this ByteBuffer's contents. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.reverse = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === end) + return this; // Nothing to reverse + Array.prototype.reverse.call(new Uint8Array(this.buffer).subarray(begin, end)); + this.view = new DataView(this.buffer); // FIXME: Why exactly is this necessary? + return this; + }; + /** + * Skips the next `length` bytes. This will just advance + * @param {number} length Number of bytes to skip. May also be negative to move the offset back. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.skip = function(length) { + if (!this.noAssert) { + if (typeof length !== 'number' || length % 1 !== 0) + throw TypeError("Illegal length: "+length+" (not an integer)"); + length |= 0; + } + var offset = this.offset + length; + if (!this.noAssert) { + if (offset < 0 || offset > this.buffer.byteLength) + throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+this.buffer.byteLength); + } + this.offset = offset; + return this; + }; + + /** + * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer} + * @expose + */ + ByteBufferPrototype.slice = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var bb = this.clone(); + bb.offset = begin; + bb.limit = end; + return bb; + }; + /** + * Returns a copy of the backing buffer that contains this ByteBuffer's contents. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory if + * possible. Defaults to `false` + * @returns {!ArrayBuffer} Contents as an ArrayBuffer + * @expose + */ + ByteBufferPrototype.toBuffer = function(forceCopy) { + var offset = this.offset, + limit = this.limit; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: Not an integer"); + offset >>>= 0; + if (typeof limit !== 'number' || limit % 1 !== 0) + throw TypeError("Illegal limit: Not an integer"); + limit >>>= 0; + if (offset < 0 || offset > limit || limit > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.byteLength); + } + // NOTE: It's not possible to have another ArrayBuffer reference the same memory as the backing buffer. This is + // possible with Uint8Array#subarray only, but we have to return an ArrayBuffer by contract. So: + if (!forceCopy && offset === 0 && limit === this.buffer.byteLength) + return this.buffer; + if (offset === limit) + return EMPTY_BUFFER; + var buffer = new ArrayBuffer(limit - offset); + new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(offset, limit), 0); + return buffer; + }; + + /** + * Returns a raw buffer compacted to contain this ByteBuffer's contents. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. This is an alias of {@link ByteBuffer#toBuffer}. + * @function + * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory. + * Defaults to `false` + * @returns {!ArrayBuffer} Contents as an ArrayBuffer + * @expose + */ + ByteBufferPrototype.toArrayBuffer = ByteBufferPrototype.toBuffer; + + /** + * Converts the ByteBuffer's contents to a string. + * @param {string=} encoding Output encoding. Returns an informative string representation if omitted but also allows + * direct conversion to "utf8", "hex", "base64" and "binary" encoding. "debug" returns a hex representation with + * highlighted offsets. + * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {string} String representation + * @throws {Error} If `encoding` is invalid + * @expose + */ + ByteBufferPrototype.toString = function(encoding, begin, end) { + if (typeof encoding === 'undefined') + return "ByteBufferAB_DataView(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")"; + if (typeof encoding === 'number') + encoding = "utf8", + begin = encoding, + end = begin; + switch (encoding) { + case "utf8": + return this.toUTF8(begin, end); + case "base64": + return this.toBase64(begin, end); + case "hex": + return this.toHex(begin, end); + case "binary": + return this.toBinary(begin, end); + case "debug": + return this.toDebug(); + case "columns": + return this.toColumns(); + default: + throw Error("Unsupported encoding: "+encoding); + } + }; + + // lxiv-embeddable + + /** + * lxiv-embeddable (c) 2014 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/lxiv for details + */ + var lxiv = function() { + "use strict"; + + /** + * lxiv namespace. + * @type {!Object.} + * @exports lxiv + */ + var lxiv = {}; + + /** + * Character codes for output. + * @type {!Array.} + * @inner + */ + var aout = [ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47 + ]; + + /** + * Character codes for input. + * @type {!Array.} + * @inner + */ + var ain = []; + for (var i=0, k=aout.length; i>2)&0x3f]); + t = (b&0x3)<<4; + if ((b = src()) !== null) { + t |= (b>>4)&0xf; + dst(aout[(t|((b>>4)&0xf))&0x3f]); + t = (b&0xf)<<2; + if ((b = src()) !== null) + dst(aout[(t|((b>>6)&0x3))&0x3f]), + dst(aout[b&0x3f]); + else + dst(aout[t&0x3f]), + dst(61); + } else + dst(aout[t&0x3f]), + dst(61), + dst(61); + } + }; + + /** + * Decodes base64 char codes to bytes. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. + * @throws {Error} If a character code is invalid + */ + lxiv.decode = function(src, dst) { + var c, t1, t2; + function fail(c) { + throw Error("Illegal character code: "+c); + } + while ((c = src()) !== null) { + t1 = ain[c]; + if (typeof t1 === 'undefined') fail(c); + if ((c = src()) !== null) { + t2 = ain[c]; + if (typeof t2 === 'undefined') fail(c); + dst((t1<<2)>>>0|(t2&0x30)>>4); + if ((c = src()) !== null) { + t1 = ain[c]; + if (typeof t1 === 'undefined') + if (c === 61) break; else fail(c); + dst(((t2&0xf)<<4)>>>0|(t1&0x3c)>>2); + if ((c = src()) !== null) { + t2 = ain[c]; + if (typeof t2 === 'undefined') + if (c === 61) break; else fail(c); + dst(((t1&0x3)<<6)>>>0|t2); + } + } + } + } + }; + + /** + * Tests if a string is valid base64. + * @param {string} str String to test + * @returns {boolean} `true` if valid, otherwise `false` + */ + lxiv.test = function(str) { + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(str); + }; + + return lxiv; + }(); + + // encodings/base64 + + /** + * Encodes this ByteBuffer's contents to a base64 encoded string. + * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}. + * @returns {string} Base64 encoded string + * @throws {RangeError} If `begin` or `end` is out of bounds + * @expose + */ + ByteBufferPrototype.toBase64 = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin = begin | 0; end = end | 0; + if (begin < 0 || end > this.capacity || begin > end) + throw RangeError("begin, end"); + var sd; lxiv.encode(function() { + return begin < end ? this.view.getUint8(begin++) : null; + }.bind(this), sd = stringDestination()); + return sd(); + }; + + /** + * Decodes a base64 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromBase64 = function(str, littleEndian) { + if (typeof str !== 'string') + throw TypeError("str"); + var bb = new ByteBuffer(str.length/4*3, littleEndian), + i = 0; + lxiv.decode(stringSource(str), function(b) { + bb.view.setUint8(i++, b); + }); + bb.limit = i; + return bb; + }; + + /** + * Encodes a binary string to base64 like `window.btoa` does. + * @param {string} str Binary string + * @returns {string} Base64 encoded string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa + * @expose + */ + ByteBuffer.btoa = function(str) { + return ByteBuffer.fromBinary(str).toBase64(); + }; + + /** + * Decodes a base64 encoded string to binary like `window.atob` does. + * @param {string} b64 Base64 encoded string + * @returns {string} Binary string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob + * @expose + */ + ByteBuffer.atob = function(b64) { + return ByteBuffer.fromBase64(b64).toBinary(); + }; + + // encodings/binary + + /** + * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes. + * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}. + * @returns {string} Binary encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ + ByteBufferPrototype.toBinary = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin |= 0; end |= 0; + if (begin < 0 || end > this.capacity() || begin > end) + throw RangeError("begin, end"); + if (begin === end) + return ""; + var chars = [], + parts = []; + while (begin < end) { + chars.push(this.view.getUint8(begin++)); + if (chars.length >= 1024) + parts.push(String.fromCharCode.apply(String, chars)), + chars = []; + } + return parts.join('') + String.fromCharCode.apply(String, chars); + }; + + /** + * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromBinary = function(str, littleEndian) { + if (typeof str !== 'string') + throw TypeError("str"); + var i = 0, + k = str.length, + charCode, + bb = new ByteBuffer(k, littleEndian); + while (i 0xff) + throw RangeError("illegal char code: "+charCode); + bb.view.setUint8(i++, charCode); + } + bb.limit = k; + return bb; + }; + + // encodings/debug + + /** + * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are: + * * `<` : offset, + * * `'` : markedOffset, + * * `>` : limit, + * * `|` : offset and limit, + * * `[` : offset and markedOffset, + * * `]` : markedOffset and limit, + * * `!` : offset, markedOffset and limit + * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false` + * @returns {string|!Array.} Debug string or array of lines if `asArray = true` + * @expose + * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3` + * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4` + * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1` + * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1` + */ + ByteBufferPrototype.toDebug = function(columns) { + var i = -1, + k = this.buffer.byteLength, + b, + hex = "", + asc = "", + out = ""; + while (i 32 && b < 127 ? String.fromCharCode(b) : '.'; + } + ++i; + if (columns) { + if (i > 0 && i % 16 === 0 && i !== k) { + while (hex.length < 3*16+3) hex += " "; + out += hex+asc+"\n"; + hex = asc = ""; + } + } + if (i === this.offset && i === this.limit) + hex += i === this.markedOffset ? "!" : "|"; + else if (i === this.offset) + hex += i === this.markedOffset ? "[" : "<"; + else if (i === this.limit) + hex += i === this.markedOffset ? "]" : ">"; + else + hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : ""); + } + if (columns && hex !== " ") { + while (hex.length < 3*16+3) + hex += " "; + out += hex + asc + "\n"; + } + return columns ? out : hex; + }; + + /** + * Decodes a hex encoded string with marked offsets to a ByteBuffer. + * @param {string} str Debug string to decode (not be generated with `columns = true`) + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + * @see ByteBuffer#toDebug + */ + ByteBuffer.fromDebug = function(str, littleEndian, noAssert) { + var k = str.length, + bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert); + var i = 0, j = 0, ch, b, + rs = false, // Require symbol next + ho = false, hm = false, hl = false, // Already has offset (ho), markedOffset (hm), limit (hl)? + fail = false; + while (i': + if (!noAssert) { + if (hl) { + fail = true; + break; + } + hl = true; + } + bb.limit = j; + rs = false; + break; + case "'": + if (!noAssert) { + if (hm) { + fail = true; + break; + } + hm = true; + } + bb.markedOffset = j; + rs = false; + break; + case ' ': + rs = false; + break; + default: + if (!noAssert) { + if (rs) { + fail = true; + break; + } + } + b = parseInt(ch+str.charAt(i++), 16); + if (!noAssert) { + if (isNaN(b) || b < 0 || b > 255) + throw TypeError("Illegal str: Not a debug encoded string"); + } + bb.view.setUint8(j++, b); + rs = true; + } + if (fail) + throw TypeError("Illegal str: Invalid symbol at "+i); + } + if (!noAssert) { + if (!ho || !hl) + throw TypeError("Illegal str: Missing offset or limit"); + if (j>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var out = new Array(end - begin), + b; + while (begin < end) { + b = this.view.getUint8(begin++); + if (b < 0x10) + out.push("0", b.toString(16)); + else out.push(b.toString(16)); + } + return out.join(''); + }; + + /** + * Decodes a hex encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromHex = function(str, littleEndian, noAssert) { + if (!noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (str.length % 2 !== 0) + throw TypeError("Illegal str: Length not a multiple of 2"); + } + var k = str.length, + bb = new ByteBuffer((k / 2) | 0, littleEndian), + b; + for (var i=0, j=0; i 255) + throw TypeError("Illegal str: Contains non-hex characters"); + bb.view.setUint8(j++, b); + } + bb.limit = j; + return bb; + }; + + // utfx-embeddable + + /** + * utfx-embeddable (c) 2014 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/utfx for details + */ + var utfx = function() { + "use strict"; + + /** + * utfx namespace. + * @inner + * @type {!Object.} + */ + var utfx = {}; + + /** + * Maximum valid code point. + * @type {number} + * @const + */ + utfx.MAX_CODEPOINT = 0x10FFFF; + + /** + * Encodes UTF8 code points to UTF8 bytes. + * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point + * respectively `null` if there are no more code points left or a single numeric code point. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte + */ + utfx.encodeUTF8 = function(src, dst) { + var cp = null; + if (typeof src === 'number') + cp = src, + src = function() { return null; }; + while (cp !== null || (cp = src()) !== null) { + if (cp < 0x80) + dst(cp&0x7F); + else if (cp < 0x800) + dst(((cp>>6)&0x1F)|0xC0), + dst((cp&0x3F)|0x80); + else if (cp < 0x10000) + dst(((cp>>12)&0x0F)|0xE0), + dst(((cp>>6)&0x3F)|0x80), + dst((cp&0x3F)|0x80); + else + dst(((cp>>18)&0x07)|0xF0), + dst(((cp>>12)&0x3F)|0x80), + dst(((cp>>6)&0x3F)|0x80), + dst((cp&0x3F)|0x80); + cp = null; + } + }; + + /** + * Decodes UTF8 bytes to UTF8 code points. + * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there + * are no more bytes left. + * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point. + * @throws {RangeError} If a starting byte is invalid in UTF8 + * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the + * remaining bytes. + */ + utfx.decodeUTF8 = function(src, dst) { + var a, b, c, d, fail = function(b) { + b = b.slice(0, b.indexOf(null)); + var err = Error(b.toString()); + err.name = "TruncatedError"; + err['bytes'] = b; + throw err; + }; + while ((a = src()) !== null) { + if ((a&0x80) === 0) + dst(a); + else if ((a&0xE0) === 0xC0) + ((b = src()) === null) && fail([a, b]), + dst(((a&0x1F)<<6) | (b&0x3F)); + else if ((a&0xF0) === 0xE0) + ((b=src()) === null || (c=src()) === null) && fail([a, b, c]), + dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F)); + else if ((a&0xF8) === 0xF0) + ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]), + dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F)); + else throw RangeError("Illegal starting byte: "+a); + } + }; + + /** + * Converts UTF16 characters to UTF8 code points. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @param {!function(number)} dst Code points destination as a function successively called with each converted code + * point. + */ + utfx.UTF16toUTF8 = function(src, dst) { + var c1, c2 = null; + while (true) { + if ((c1 = c2 !== null ? c2 : src()) === null) + break; + if (c1 >= 0xD800 && c1 <= 0xDFFF) { + if ((c2 = src()) !== null) { + if (c2 >= 0xDC00 && c2 <= 0xDFFF) { + dst((c1-0xD800)*0x400+c2-0xDC00+0x10000); + c2 = null; continue; + } + } + } + dst(c1); + } + if (c2 !== null) dst(c2); + }; + + /** + * Converts UTF8 code points to UTF16 characters. + * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point + * respectively `null` if there are no more code points left or a single numeric code point. + * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. + * @throws {RangeError} If a code point is out of range + */ + utfx.UTF8toUTF16 = function(src, dst) { + var cp = null; + if (typeof src === 'number') + cp = src, src = function() { return null; }; + while (cp !== null || (cp = src()) !== null) { + if (cp <= 0xFFFF) + dst(cp); + else + cp -= 0x10000, + dst((cp>>10)+0xD800), + dst((cp%0x400)+0xDC00); + cp = null; + } + }; + + /** + * Converts and encodes UTF16 characters to UTF8 bytes. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null` + * if there are no more characters left. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. + */ + utfx.encodeUTF16toUTF8 = function(src, dst) { + utfx.UTF16toUTF8(src, function(cp) { + utfx.encodeUTF8(cp, dst); + }); + }; + + /** + * Decodes and converts UTF8 bytes to UTF16 characters. + * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there + * are no more bytes left. + * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. + * @throws {RangeError} If a starting byte is invalid in UTF8 + * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes. + */ + utfx.decodeUTF8toUTF16 = function(src, dst) { + utfx.decodeUTF8(src, function(cp) { + utfx.UTF8toUTF16(cp, dst); + }); + }; + + /** + * Calculates the byte length of an UTF8 code point. + * @param {number} cp UTF8 code point + * @returns {number} Byte length + */ + utfx.calculateCodePoint = function(cp) { + return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + }; + + /** + * Calculates the number of UTF8 bytes required to store UTF8 code points. + * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively + * `null` if there are no more code points left. + * @returns {number} The number of UTF8 bytes required + */ + utfx.calculateUTF8 = function(src) { + var cp, l=0; + while ((cp = src()) !== null) + l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + return l; + }; + + /** + * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes. + * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @returns {!Array.} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1. + */ + utfx.calculateUTF16asUTF8 = function(src) { + var n=0, l=0; + utfx.UTF16toUTF8(src, function(cp) { + ++n; l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + }); + return [n,l]; + }; + + return utfx; + }(); + + // encodings/utf8 + + /** + * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded + * string. + * @returns {string} Hex encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ + ByteBufferPrototype.toUTF8 = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var sd; try { + utfx.decodeUTF8toUTF16(function() { + return begin < end ? this.view.getUint8(begin++) : null; + }.bind(this), sd = stringDestination()); + } catch (e) { + if (begin !== end) + throw RangeError("Illegal range: Truncated data, "+begin+" != "+end); + } + return sd(); + }; + + /** + * Decodes an UTF8 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) { + if (!noAssert) + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + var bb = new ByteBuffer(utfx.calculateUTF16asUTF8(stringSource(str), true)[1], littleEndian, noAssert), + i = 0; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + bb.view.setUint8(i++, b); + }); + bb.limit = i; + return bb; + }; + + return ByteBuffer; +}); diff --git a/dist/bytebuffer-dataview.min.js b/dist/bytebuffer-dataview.min.js new file mode 100644 index 0000000..6290102 --- /dev/null +++ b/dist/bytebuffer-dataview.min.js @@ -0,0 +1,88 @@ +/* + bytebuffer.js (c) 2015 Daniel Wirtz + Backing buffer: ArrayBuffer, Accessor: DataView + Released under the Apache License, Version 2.0 + see: https://github.com/dcodeIO/bytebuffer.js for details +*/ +(function(h,l){if("function"===typeof define&&define.amd)define(["long"],l);else if("function"===typeof require&&"object"===typeof module&&module&&module.exports){h=module;try{var t=require("long")}catch(f){}l=l(t);h.exports=l}else(h.dcodeIO=h.dcodeIO||{}).ByteBuffer=l(h.dcodeIO.Long)})(this,function(h){function l(a){var b=0;return function(){return ba)throw RangeError("Illegal capacity");b=!!b;c=!!c}this.buffer=0===a?u:new ArrayBuffer(a);this.view=0===a?null:new DataView(this.buffer);this.offset=0;this.markedOffset=-1;this.limit=a;this.littleEndian=b;this.noAssert=c};f.VERSION= +"5.0.1";f.LITTLE_ENDIAN=!0;f.BIG_ENDIAN=!1;f.DEFAULT_CAPACITY=16;f.DEFAULT_ENDIAN=f.BIG_ENDIAN;f.DEFAULT_NOASSERT=!1;f.Long=h||null;var d=f.prototype;Object.defineProperty(d,"__isByteBuffer__",{value:!0,enumerable:!1,configurable:!1});var u=new ArrayBuffer(0),v=String.fromCharCode;f.accessor=function(){return DataView};f.allocate=function(a,b,c){return new f(a,b,c)};f.concat=function(a,b,c,e){if("boolean"===typeof b||"string"!==typeof b)e=c,c=b,b=void 0;for(var n=0,g=0,d=a.length,p;g=p||(e.set((new Uint8Array(c.buffer)).subarray(c.offset,c.limit),b.offset),b.offset+=p);b.limit=b.offset;b.offset=0;return b};f.isByteBuffer=function(a){return!0===(a&&a.__isByteBuffer__)};f.type=function(){return ArrayBuffer};f.wrap=function(a,b,c,e){"string"!==typeof b&&(e=c,c=b,b=void 0);if("string"===typeof a)switch("undefined"=== +typeof b&&(b="utf8"),b){case "base64":return f.fromBase64(a,c);case "hex":return f.fromHex(a,c);case "binary":return f.fromBinary(a,c);case "utf8":return f.fromUTF8(a,c);case "debug":return f.fromDebug(a,c);default:throw Error("Unsupported encoding: "+b);}if(null===a||"object"!==typeof a)throw TypeError("Illegal buffer");if(f.isByteBuffer(a))return b=d.clone.call(a),b.markedOffset=-1,b;if(a instanceof Uint8Array)b=new f(0,c,e),0>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var e=b,n=a.length,g=n>>3,d=0;for(b+=this.writeVarint32(n,b);g--;){var f=!!a[d++]&1|(!!a[d++]&1)<<1|(!!a[d++]&1)<<2|(!!a[d++]&1)<<3|(!!a[d++]&1)<<4|(!!a[d++]&1)<<5|(!!a[d++]&1)<<6|(!!a[d++]&1)<<7;this.writeByte(f,b++)}if(d>3,d=0,f=[];for(a+=c.length;n--;)c=this.readByte(a++),f[d++]=!!(c&1),f[d++]=!!(c&2),f[d++]=!!(c&4),f[d++]=!!(c&8),f[d++]=!!(c&16),f[d++]=!!(c&32),f[d++]=!!(c&64),f[d++]=!!(c&128);if(d>n++&1);b&&(this.offset=a);return f};d.readBytes=function(a,b){var c="undefined"=== +typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+a>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+"+a+") <= "+this.buffer.byteLength);}b=this.slice(b,b+a);c&&(this.offset+=a);return b};d.writeInt8=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!== +typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=1;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);this.view.setInt8(b-1,a);c&&(this.offset+=1);return this};d.writeByte=d.writeInt8;d.readInt8=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+ +a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}a=this.view.getInt8(a);b&&(this.offset+=1);return a};d.readByte=d.readInt8;d.writeUint8=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>= +0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=1;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);this.view.setUint8(b-1,a);c&&(this.offset+=1);return this};d.writeUInt8=d.writeUint8;d.readUint8=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +a+" (+1) <= "+this.buffer.byteLength);}a=this.view.getUint8(a);b&&(this.offset+=1);return a};d.readUInt8=d.readUint8;d.writeInt16=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength); +}b+=2;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);this.view.setInt16(b-2,a,this.littleEndian);c&&(this.offset+=2);return this};d.writeShort=d.writeInt16;d.readInt16=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+2>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+2) <= "+this.buffer.byteLength);}a=this.view.getInt16(a,this.littleEndian); +b&&(this.offset+=2);return a};d.readShort=d.readInt16;d.writeUint16=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=2;var e=this.buffer.byteLength;b>e&&this.resize((e*= +2)>b?e:b);this.view.setUint16(b-2,a,this.littleEndian);c&&(this.offset+=2);return this};d.writeUInt16=d.writeUint16;d.readUint16=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+2>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+2) <= "+this.buffer.byteLength);}a=this.view.getUint16(a,this.littleEndian);b&&(this.offset+=2);return a};d.readUInt16= +d.readUint16;d.writeInt32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=4;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);this.view.setInt32(b-4, +a,this.littleEndian);c&&(this.offset+=4);return this};d.writeInt=d.writeInt32;d.readInt32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}a=this.view.getInt32(a,this.littleEndian);b&&(this.offset+=4);return a};d.readInt=d.readInt32;d.writeUint32=function(a,b){var c= +"undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=4;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);this.view.setUint32(b-4,a,this.littleEndian);c&&(this.offset+=4);return this}; +d.writeUInt32=d.writeUint32;d.readUint32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}a=this.view.getUint32(a,this.littleEndian);b&&(this.offset+=4);return a};d.readUInt32=d.readUint32;h&&(d.writeInt64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset); +if(!this.noAssert){if("number"===typeof a)a=h.fromNumber(a);else if("string"===typeof a)a=h.fromString(a);else if(!(a&&a instanceof h))throw TypeError("Illegal value: "+a+" (not an integer or Long)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=h.fromNumber(a):"string"===typeof a&&(a=h.fromString(a));b+=8;var e= +this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=8;this.littleEndian?(this.view.setInt32(b,a.low,!0),this.view.setInt32(b+4,a.high,!0)):(this.view.setInt32(b,a.high,!1),this.view.setInt32(b+4,a.low,!1));c&&(this.offset+=8);return this},d.writeLong=d.writeInt64,d.readInt64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +a+" (+8) <= "+this.buffer.byteLength);}a=this.littleEndian?new h(this.view.getInt32(a,!0),this.view.getInt32(a+4,!0),!1):new h(this.view.getInt32(a+4,!1),this.view.getInt32(a,!1),!1);b&&(this.offset+=8);return a},d.readLong=d.readInt64,d.writeUint64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"===typeof a)a=h.fromNumber(a);else if("string"===typeof a)a=h.fromString(a);else if(!(a&&a instanceof h))throw TypeError("Illegal value: "+a+" (not an integer or Long)"); +if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=h.fromNumber(a):"string"===typeof a&&(a=h.fromString(a));b+=8;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=8;this.littleEndian?(this.view.setInt32(b,a.low,!0),this.view.setInt32(b+4,a.high,!0)):(this.view.setInt32(b,a.high,!1),this.view.setInt32(b+4, +a.low,!1));c&&(this.offset+=8);return this},d.writeUInt64=d.writeUint64,d.readUint64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+8) <= "+this.buffer.byteLength);}a=this.littleEndian?new h(this.view.getInt32(a,!0),this.view.getInt32(a+4,!0),!0):new h(this.view.getInt32(a+4,!1),this.view.getInt32(a, +!1),!0);b&&(this.offset+=8);return a},d.readUInt64=d.readUint64);d.writeFloat32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a)throw TypeError("Illegal value: "+a+" (not a number)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=4;var e=this.buffer.byteLength;b>e&&this.resize((e*= +2)>b?e:b);this.view.setFloat32(b-4,a,this.littleEndian);c&&(this.offset+=4);return this};d.writeFloat=d.writeFloat32;d.readFloat32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}a=this.view.getFloat32(a,this.littleEndian);b&&(this.offset+=4);return a};d.readFloat= +d.readFloat32;d.writeFloat64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a)throw TypeError("Illegal value: "+a+" (not a number)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=8;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);this.view.setFloat64(b-8,a,this.littleEndian); +c&&(this.offset+=8);return this};d.writeDouble=d.writeFloat64;d.readFloat64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+8) <= "+this.buffer.byteLength);}a=this.view.getFloat64(a,this.littleEndian);b&&(this.offset+=8);return a};d.readDouble=d.readFloat64;f.MAX_VARINT32_BYTES=5;f.calculateVarint32= +function(a){a>>>=0;return 128>a?1:16384>a?2:2097152>a?3:268435456>a?4:5};f.zigZagEncode32=function(a){return((a|=0)<<1^a>>31)>>>0};f.zigZagDecode32=function(a){return a>>>1^-(a&1)|0};d.writeVarint32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +b+" (+0) <= "+this.buffer.byteLength);}var e=f.calculateVarint32(a);b+=e;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);b-=e;for(a>>>=0;128<=a;)d=a&127|128,this.view.setUint8(b++,d),a>>>=7;this.view.setUint8(b++,a);return c?(this.offset=b,this):e};d.writeVarint32ZigZag=function(a,b){return this.writeVarint32(f.zigZagEncode32(a),b)};d.readVarint32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+ +a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=0,e=0;do{if(!this.noAssert&&a>this.limit)throw a=Error("Truncated"),a.truncated=!0,a;var d=this.view.getUint8(a++);5>c&&(e|=(d&127)<<7*c);++c}while(0!==(d&128));e|=0;return b?(this.offset=a,e):{value:e,length:c}};d.readVarint32ZigZag=function(a){a=this.readVarint32(a);"object"===typeof a?a.value=f.zigZagDecode32(a.value):a=f.zigZagDecode32(a);return a}; +h&&(f.MAX_VARINT64_BYTES=10,f.calculateVarint64=function(a){"number"===typeof a?a=h.fromNumber(a):"string"===typeof a&&(a=h.fromString(a));var b=a.toInt()>>>0,c=a.shiftRightUnsigned(28).toInt()>>>0;a=a.shiftRightUnsigned(56).toInt()>>>0;return 0==a?0==c?16384>b?128>b?1:2:2097152>b?3:4:16384>c?128>c?5:6:2097152>c?7:8:128>a?9:10},f.zigZagEncode64=function(a){"number"===typeof a?a=h.fromNumber(a,!1):"string"===typeof a?a=h.fromString(a,!1):!1!==a.unsigned&&(a=a.toSigned());return a.shiftLeft(1).xor(a.shiftRight(63)).toUnsigned()}, +f.zigZagDecode64=function(a){"number"===typeof a?a=h.fromNumber(a,!1):"string"===typeof a?a=h.fromString(a,!1):!1!==a.unsigned&&(a=a.toSigned());return a.shiftRightUnsigned(1).xor(a.and(h.ONE).toSigned().negate()).toSigned()},d.writeVarint64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"===typeof a)a=h.fromNumber(a);else if("string"===typeof a)a=h.fromString(a);else if(!(a&&a instanceof h))throw TypeError("Illegal value: "+a+" (not an integer or Long)"); +if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=h.fromNumber(a,!1):"string"===typeof a?a=h.fromString(a,!1):!1!==a.unsigned&&(a=a.toSigned());var e=f.calculateVarint64(a),d=a.toInt()>>>0,g=a.shiftRightUnsigned(28).toInt()>>>0;a=a.shiftRightUnsigned(56).toInt()>>>0;b+=e;var k=this.buffer.byteLength;b>k&&this.resize((k*= +2)>b?k:b);b-=e;switch(e){case 10:this.view.setUint8(b+9,a>>>7&1);case 9:this.view.setUint8(b+8,9!==e?a|128:a&127);case 8:this.view.setUint8(b+7,8!==e?g>>>21|128:g>>>21&127);case 7:this.view.setUint8(b+6,7!==e?g>>>14|128:g>>>14&127);case 6:this.view.setUint8(b+5,6!==e?g>>>7|128:g>>>7&127);case 5:this.view.setUint8(b+4,5!==e?g|128:g&127);case 4:this.view.setUint8(b+3,4!==e?d>>>21|128:d>>>21&127);case 3:this.view.setUint8(b+2,3!==e?d>>>14|128:d>>>14&127);case 2:this.view.setUint8(b+1,2!==e?d>>>7|128: +d>>>7&127);case 1:this.view.setUint8(b,1!==e?d|128:d&127)}return c?(this.offset+=e,this):e},d.writeVarint64ZigZag=function(a,b){return this.writeVarint64(f.zigZagEncode64(a),b)},d.readVarint64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,e=0,d=0;var g= +this.view.getUint8(a++);var f=g&127;if(g&128&&(g=this.view.getUint8(a++),f|=(g&127)<<7,g&128&&(g=this.view.getUint8(a++),f|=(g&127)<<14,g&128&&(g=this.view.getUint8(a++),f|=(g&127)<<21,g&128&&(g=this.view.getUint8(a++),e=g&127,g&128&&(g=this.view.getUint8(a++),e|=(g&127)<<7,g&128&&(g=this.view.getUint8(a++),e|=(g&127)<<14,g&128&&(g=this.view.getUint8(a++),e|=(g&127)<<21,g&128&&(g=this.view.getUint8(a++),d=g&127,g&128&&(g=this.view.getUint8(a++),d|=(g&127)<<7,g&128))))))))))throw Error("Buffer overrun"); +f=h.fromBits(f|e<<28,e>>>4|d<<24,!1);return b?(this.offset=a,f):{value:f,length:a-c}},d.readVarint64ZigZag=function(a){(a=this.readVarint64(a))&&a.value instanceof h?a.value=f.zigZagDecode64(a.value):a=f.zigZagDecode64(a);return a});d.writeCString=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);var e,d=a.length;if(!this.noAssert){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");for(e=0;e>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}d=m.calculateUTF16asUTF8(l(a))[1];b+=d+1;e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=d+1;m.encodeUTF16toUTF8(l(a),function(a){this.view.setUint8(b++,a)}.bind(this));this.view.setUint8(b++,0);return c?(this.offset=b,this):d};d.readCString=function(a){var b="undefined"===typeof a; +b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,e,d=-1;m.decodeUTF8toUTF16(function(){if(0===d)return null;if(a>=this.limit)throw RangeError("Illegal range: Truncated data, "+a+" < "+this.limit);d=this.view.getUint8(a++);return 0===d?null:d}.bind(this),e=t(),!0);return b?(this.offset=a,e()): +{string:e(),length:a-c}};d.writeIString=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var e=b;var d=m.calculateUTF16asUTF8(l(a),this.noAssert)[1];b+=4+d;var g=this.buffer.byteLength;b>g&& +this.resize((g*=2)>b?g:b);b-=4+d;this.view.setUint32(b,d,this.littleEndian);b+=4;m.encodeUTF16toUTF8(l(a),function(a){this.view.setUint8(b++,a)}.bind(this));if(b!==e+4+d)throw RangeError("Illegal range: Truncated data, "+b+" == "+(b+4+d));return c?(this.offset=b,this):b-e};d.readIString=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +a+" (+4) <= "+this.buffer.byteLength);}var c=a,e=this.readUint32(a);e=this.readUTF8String(e,f.METRICS_BYTES,a+=4);a+=e.length;return b?(this.offset=a,e.string):{string:e.string,length:a-c}};f.METRICS_CHARS="c";f.METRICS_BYTES="b";d.writeUTF8String=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +b+" (+0) <= "+this.buffer.byteLength);}var e=b;var d=m.calculateUTF16asUTF8(l(a))[1];b+=d;var g=this.buffer.byteLength;b>g&&this.resize((g*=2)>b?g:b);b-=d;m.encodeUTF16toUTF8(l(a),function(a){this.view.setUint8(b++,a)}.bind(this));return c?(this.offset=b,this):b-e};d.writeString=d.writeUTF8String;f.calculateUTF8Chars=function(a){return m.calculateUTF16asUTF8(l(a))[0]};f.calculateUTF8Bytes=function(a){return m.calculateUTF16asUTF8(l(a))[1]};f.calculateString=f.calculateUTF8Bytes;d.readUTF8String=function(a, +b,c){"number"===typeof b&&(c=b,b=void 0);var e="undefined"===typeof c;e&&(c=this.offset);"undefined"===typeof b&&(b=f.METRICS_CHARS);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal length: "+a+" (not an integer)");a|=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+0) <= "+this.buffer.byteLength);}var d=0,g=c;if(b===f.METRICS_CHARS){var k= +t();m.decodeUTF8(function(){return d>>=0;if(0>c||c+a>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+"+a+") <= "+this.buffer.byteLength); +}var p=c+a;m.decodeUTF8toUTF16(function(){return c>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var e=b;var d=m.calculateUTF16asUTF8(l(a),this.noAssert)[1];var g=f.calculateVarint32(d);b+=g+d;var k=this.buffer.byteLength;b>k&&this.resize((k*=2)>b?k:b);b-=g+d;b+=this.writeVarint32(d,b);m.encodeUTF16toUTF8(l(a),function(a){this.view.setUint8(b++,a)}.bind(this));if(b!==e+d+g)throw RangeError("Illegal range: Truncated data, "+ +b+" == "+(b+d+g));return c?(this.offset=b,this):b-e};d.readVString=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,e=this.readVarint32(a);e=this.readUTF8String(e.value,f.METRICS_BYTES,a+=e.length);a+=e.length;return b?(this.offset=a,e.string):{string:e.string, +length:a-c}};d.append=function(a,b,c){if("number"===typeof b||"string"!==typeof b)c=b,b=void 0;var e="undefined"===typeof c;e&&(c=this.offset);if(!this.noAssert){if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+0) <= "+this.buffer.byteLength);}a instanceof f||(a=f.wrap(a,b));b=a.limit-a.offset;if(0>=b)return this;c+=b;var d=this.buffer.byteLength;c>d&&this.resize((d*=2)> +c?d:c);(new Uint8Array(this.buffer,c-b)).set((new Uint8Array(a.buffer)).subarray(a.offset,a.limit));a.offset+=b;e&&(this.offset+=b);return this};d.appendTo=function(a,b){a.append(this,b);return this};d.writeBytes=d.append;d.assert=function(a){this.noAssert=!a;return this};d.capacity=function(){return this.buffer.byteLength};d.clear=function(){this.offset=0;this.limit=this.buffer.byteLength;this.markedOffset=-1;return this};d.clone=function(a){var b=new f(0,this.littleEndian,this.noAssert);a?(b.buffer= +new ArrayBuffer(this.buffer.byteLength),(new Uint8Array(b.buffer)).set(this.buffer),b.view=new DataView(b.buffer)):(b.buffer=this.buffer,b.view=this.view);b.offset=this.offset;b.markedOffset=this.markedOffset;b.limit=this.limit;return b};d.compact=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer"); +b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}if(0===a&&b===this.buffer.byteLength)return this;var c=b-a;if(0===c)return this.buffer=u,this.view=null,0<=this.markedOffset&&(this.markedOffset-=a),this.limit=this.offset=0,this;var e=new ArrayBuffer(c);(new Uint8Array(e)).set((new Uint8Array(this.buffer)).subarray(a,b));this.buffer=e;this.view=new DataView(e);0<=this.markedOffset&&(this.markedOffset-=a);this.offset=0;this.limit= +c;return this};d.copy=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}if(a===b)return new f(0,this.littleEndian,this.noAssert);var c=b-a,e=new f(c, +this.littleEndian,this.noAssert);e.offset=0;e.limit=c;0<=e.markedOffset&&(e.markedOffset-=a);this.copyTo(e,0,a,b);return e};d.copyTo=function(a,b,c,e){var d,g;if(!this.noAssert&&!f.isByteBuffer(a))throw TypeError("Illegal target: Not a ByteBuffer");b=(g="undefined"===typeof b)?a.offset:b|0;c=(d="undefined"===typeof c)?this.offset:c|0;e="undefined"===typeof e?this.limit:e|0;if(0>b||b>a.buffer.byteLength)throw RangeError("Illegal target range: 0 <= "+b+" <= "+a.buffer.byteLength);if(0>c||e>this.buffer.byteLength)throw RangeError("Illegal source range: 0 <= "+ +c+" <= "+this.buffer.byteLength);var k=e-c;if(0===k)return a;a.ensureCapacity(b+k);(new Uint8Array(a.buffer)).set((new Uint8Array(this.buffer)).subarray(c,e),b);d&&(this.offset+=k);g&&(a.offset+=k);return this};d.ensureCapacity=function(a){var b=this.buffer.byteLength;return ba?b:a):this};d.fill=function(a,b,c){var e="undefined"===typeof b;e&&(b=this.offset);"string"===typeof a&&0>>=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal end: Not an integer");c>>>=0;if(0>b||b>c||c>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+b+" <= "+c+" <= "+this.buffer.byteLength);}if(b>=c)return this;for(;b>>=0;if(0>a||a+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+0) <= "+this.buffer.byteLength);}this.markedOffset=a;return this};d.order=function(a){if(!this.noAssert&&"boolean"!==typeof a)throw TypeError("Illegal littleEndian: Not a boolean"); +this.littleEndian=!!a;return this};d.LE=function(a){this.littleEndian="undefined"!==typeof a?!!a:!0;return this};d.BE=function(a){this.littleEndian="undefined"!==typeof a?!a:!1;return this};d.prepend=function(a,b,c){if("number"===typeof b||"string"!==typeof b)c=b,b=void 0;var e="undefined"===typeof c;e&&(c=this.offset);if(!this.noAssert){if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +c+" (+0) <= "+this.buffer.byteLength);}a instanceof f||(a=f.wrap(a,b));b=a.limit-a.offset;if(0>=b)return this;var d=b-c;if(0a)throw RangeError("Illegal capacity: 0 <= "+a);}this.buffer.byteLength>>=0; +if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}if(a===b)return this;Array.prototype.reverse.call((new Uint8Array(this.buffer)).subarray(a,b));this.view=new DataView(this.buffer);return this};d.skip=function(a){if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal length: "+a+" (not an integer)");a|=0}var b=this.offset+ +a;if(!this.noAssert&&(0>b||b>this.buffer.byteLength))throw RangeError("Illegal length: 0 <= "+this.offset+" + "+a+" <= "+this.buffer.byteLength);this.offset=b;return this};d.slice=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+ +a+" <= "+b+" <= "+this.buffer.byteLength);}var c=this.clone();c.offset=a;c.limit=b;return c};d.toBuffer=function(a){var b=this.offset,c=this.limit;if(!this.noAssert){if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: Not an integer");b>>>=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal limit: Not an integer");c>>>=0;if(0>b||b>c||c>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+b+" <= "+c+" <= "+this.buffer.byteLength);}if(!a&&0===b&&c===this.buffer.byteLength)return this.buffer; +if(b===c)return u;a=new ArrayBuffer(c-b);(new Uint8Array(a)).set((new Uint8Array(this.buffer)).subarray(b,c),0);return a};d.toArrayBuffer=d.toBuffer;d.toString=function(a,b,c){if("undefined"===typeof a)return"ByteBufferAB_DataView(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")";"number"===typeof a&&(c=b=a="utf8");switch(a){case "utf8":return this.toUTF8(b,c);case "base64":return this.toBase64(b,c);case "hex":return this.toHex(b,c);case "binary":return this.toBinary(b, +c);case "debug":return this.toDebug();case "columns":return this.toColumns();default:throw Error("Unsupported encoding: "+a);}};var w=function(){for(var a={},b=[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,54,55,56,57,43,47],c=[],e=0,d=b.length;e>2&63]),d=(e&3)<<4,null!==(e= +a())?(d|=e>>4&15,c(b[(d|e>>4&15)&63]),d=(e&15)<<2,null!==(e=a())?(c(b[(d|e>>6&3)&63]),c(b[e&63])):(c(b[d&63]),c(61))):(c(b[d&63]),c(61),c(61))};a.decode=function(a,b){function e(a){throw Error("Illegal character code: "+a);}for(var d,f,g;null!==(d=a());)if(f=c[d],"undefined"===typeof f&&e(d),null!==(d=a())&&(g=c[d],"undefined"===typeof g&&e(d),b(f<<2>>>0|(g&48)>>4),null!==(d=a()))){f=c[d];if("undefined"===typeof f)if(61===d)break;else e(d);b((g&15)<<4>>>0|(f&60)>>2);if(null!==(d=a())){g=c[d];if("undefined"=== +typeof g)if(61===d)break;else e(d);b((f&3)<<6>>>0|g)}}};a.test=function(a){return/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(a)};return a}();d.toBase64=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);a|=0;b|=0;if(0>a||b>this.capacity||a>b)throw RangeError("begin, end");var c;w.encode(function(){return aa||b>this.capacity()||a>b)throw RangeError("begin, end");if(a===b)return"";for(var c=[],e=[];ae?d+("0"+e.toString(16).toUpperCase()):d+e.toString(16).toUpperCase(),a&&(f+=32e? +String.fromCharCode(e):"."));++b;if(a&&0d.length;)d+=" ";k+=d+f+"\n";d=f=""}d=b===this.offset&&b===this.limit?d+(b===this.markedOffset?"!":"|"):b===this.offset?d+(b===this.markedOffset?"[":"<"):b===this.limit?d+(b===this.markedOffset?"]":">"):d+(b===this.markedOffset?"'":a||0!==b&&b!==c?" ":"")}if(a&&" "!==d){for(;51>d.length;)d+=" ";k+=d+f+"\n"}return a?k:d};f.fromDebug=function(a,b,c){var e=a.length;b=new f((e+1)/3|0,b,c);for(var d=0,g=0,k,h=!1,l=!1,m=!1,r=!1,q=!1;d< +e;){switch(k=a.charAt(d++)){case "!":if(!c){if(l||m||r){q=!0;break}l=m=r=!0}b.offset=b.markedOffset=b.limit=g;h=!1;break;case "|":if(!c){if(l||r){q=!0;break}l=r=!0}b.offset=b.limit=g;h=!1;break;case "[":if(!c){if(l||m){q=!0;break}l=m=!0}b.offset=b.markedOffset=g;h=!1;break;case "<":if(!c){if(l){q=!0;break}l=!0}b.offset=g;h=!1;break;case "]":if(!c){if(r||m){q=!0;break}r=m=!0}b.limit=b.markedOffset=g;h=!1;break;case ">":if(!c){if(r){q=!0;break}r=!0}b.limit=g;h=!1;break;case "'":if(!c){if(m){q=!0;break}m= +!0}b.markedOffset=g;h=!1;break;case " ":h=!1;break;default:if(!c&&h)q=!0;else{k=parseInt(k+a.charAt(d++),16);if(!c&&(isNaN(k)||0>k||255>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}for(var c=Array(b-a),d;ad?c.push("0",d.toString(16)):c.push(d.toString(16));return c.join("")}; +f.fromHex=function(a,b,c){if(!c){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");if(0!==a.length%2)throw TypeError("Illegal str: Length not a multiple of 2");}var d=a.length;b=new f(d/2|0,b);for(var h,g=0,k=0;gh||255b?c(b&127):(2048>b?c(b>>6&31|192):65536>b?(c(b>>12&15|224),c(b>>6&63|128)):(c(b>>18&7|240),c(b>>12&63|128),c(b>>6&63|128)),c(b&63|128)),b=null},decodeUTF8:function(a,c){for(var b,d,f,h,l=function(a){a=a.slice(0,a.indexOf(null));var b=Error(a.toString());b.name="TruncatedError";b.bytes=a;throw b;};null!==(b=a());)if(0===(b&128))c(b);else if(192===(b&224))null===(d=a())&&l([b,d]),c((b&31)<<6|d&63);else if(224===(b&240))null!== +(d=a())&&null!==(f=a())||l([b,d,f]),c((b&15)<<12|(d&63)<<6|f&63);else if(240===(b&248))null!==(d=a())&&null!==(f=a())&&null!==(h=a())||l([b,d,f,h]),c((b&7)<<18|(d&63)<<12|(f&63)<<6|h&63);else throw RangeError("Illegal starting byte: "+b);},UTF16toUTF8:function(a,c){for(var b,d=null;null!==(b=null!==d?d:a());)55296<=b&&57343>=b&&null!==(d=a())&&56320<=d&&57343>=d?(c(1024*(b-55296)+d-56320+65536),d=null):c(b);null!==d&&c(d)},UTF8toUTF16:function(a,c){var b=null;"number"===typeof a&&(b=a,a=function(){return null}); +for(;null!==b||null!==(b=a());)65535>=b?c(b):(b-=65536,c((b>>10)+55296),c(b%1024+56320)),b=null},encodeUTF16toUTF8:function(b,c){a.UTF16toUTF8(b,function(b){a.encodeUTF8(b,c)})},decodeUTF8toUTF16:function(b,c){a.decodeUTF8(b,function(b){a.UTF8toUTF16(b,c)})},calculateCodePoint:function(a){return 128>a?1:2048>a?2:65536>a?3:4},calculateUTF8:function(a){for(var b,d=0;null!==(b=a());)d+=128>b?1:2048>b?2:65536>b?3:4;return d},calculateUTF16asUTF8:function(b){var c=0,d=0;a.UTF16toUTF8(b,function(a){++c; +d+=128>a?1:2048>a?2:65536>a?3:4});return[c,d]}};return a}();d.toUTF8=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}var c;try{m.decodeUTF8toUTF16(function(){return a< +b?this.view.getUint8(a++):null}.bind(this),c=t())}catch(e){if(a!==b)throw RangeError("Illegal range: Truncated data, "+a+" != "+b);}return c()};f.fromUTF8=function(a,b,c){if(!c&&"string"!==typeof a)throw TypeError("Illegal str: Not a string");var d=new f(m.calculateUTF16asUTF8(l(a),!0)[1],b,c),h=0;m.encodeUTF16toUTF8(l(a),function(a){d.view.setUint8(h++,a)});d.limit=h;return d};return f}); diff --git a/dist/bytebuffer-dataview.min.js.gz b/dist/bytebuffer-dataview.min.js.gz new file mode 100644 index 0000000..885731f Binary files /dev/null and b/dist/bytebuffer-dataview.min.js.gz differ diff --git a/dist/bytebuffer-dataview.min.map b/dist/bytebuffer-dataview.min.map new file mode 100644 index 0000000..775e3ca --- /dev/null +++ b/dist/bytebuffer-dataview.min.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"", +"lineCount":88, +"mappings":"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", +"sources":["dist/bytebuffer-dataview.js"], +"names":["global","factory","define","require","module","Long","e","stringSource","s","i","length","charCodeAt","stringDestination","cs","ps","arguments","join","stringFromCharCode","apply","String","push","Array","prototype","ByteBuffer","capacity","littleEndian","noAssert","DEFAULT_CAPACITY","DEFAULT_ENDIAN","DEFAULT_NOASSERT","RangeError","buffer","EMPTY_BUFFER","ArrayBuffer","view","DataView","offset","markedOffset","limit","VERSION","LITTLE_ENDIAN","BIG_ENDIAN","ByteBufferPrototype","Object","defineProperty","value","enumerable","configurable","fromCharCode","accessor","ByteBuffer.accessor","allocate","ByteBuffer.allocate","concat","ByteBuffer.concat","buffers","encoding","undefined","k","isByteBuffer","wrap","bb","Uint8Array","bi","set","subarray","ByteBuffer.isByteBuffer","type","ByteBuffer.type","ByteBuffer.wrap","fromBase64","fromHex","fromBinary","fromUTF8","fromDebug","Error","TypeError","clone","call","byteOffset","byteLength","toString","setUint8","writeBitSet","ByteBufferPrototype.writeBitSet","relative","start","bits","bytes","bit","writeVarint32","writeByte","m","readBitSet","ByteBufferPrototype.readBitSet","ret","readVarint32","readByte","readBytes","ByteBufferPrototype.readBytes","slice","writeInt8","ByteBufferPrototype.writeInt8","capacity0","resize","setInt8","readInt8","ByteBufferPrototype.readInt8","getInt8","writeUint8","ByteBufferPrototype.writeUint8","capacity1","writeUInt8","readUint8","ByteBufferPrototype.readUint8","getUint8","readUInt8","writeInt16","ByteBufferPrototype.writeInt16","capacity2","setInt16","writeShort","readInt16","ByteBufferPrototype.readInt16","getInt16","readShort","writeUint16","ByteBufferPrototype.writeUint16","capacity3","setUint16","writeUInt16","readUint16","ByteBufferPrototype.readUint16","getUint16","readUInt16","writeInt32","ByteBufferPrototype.writeInt32","capacity4","setInt32","writeInt","readInt32","ByteBufferPrototype.readInt32","getInt32","readInt","writeUint32","ByteBufferPrototype.writeUint32","capacity5","setUint32","writeUInt32","readUint32","ByteBufferPrototype.readUint32","getUint32","readUInt32","writeInt64","ByteBufferPrototype.writeInt64","fromNumber","fromString","capacity6","low","high","writeLong","readInt64","ByteBufferPrototype.readInt64","readLong","writeUint64","ByteBufferPrototype.writeUint64","capacity7","writeUInt64","readUint64","ByteBufferPrototype.readUint64","readUInt64","writeFloat32","ByteBufferPrototype.writeFloat32","capacity8","setFloat32","writeFloat","readFloat32","ByteBufferPrototype.readFloat32","getFloat32","readFloat","writeFloat64","ByteBufferPrototype.writeFloat64","capacity9","setFloat64","writeDouble","readFloat64","ByteBufferPrototype.readFloat64","getFloat64","readDouble","MAX_VARINT32_BYTES","calculateVarint32","ByteBuffer.calculateVarint32","zigZagEncode32","ByteBuffer.zigZagEncode32","n","zigZagDecode32","ByteBuffer.zigZagDecode32","ByteBufferPrototype.writeVarint32","size","capacity10","b","writeVarint32ZigZag","ByteBufferPrototype.writeVarint32ZigZag","ByteBufferPrototype.readVarint32","c","err","readVarint32ZigZag","ByteBufferPrototype.readVarint32ZigZag","val","MAX_VARINT64_BYTES","calculateVarint64","ByteBuffer.calculateVarint64","part0","toInt","part1","shiftRightUnsigned","part2","zigZagEncode64","ByteBuffer.zigZagEncode64","unsigned","toSigned","shiftLeft","xor","shiftRight","toUnsigned","zigZagDecode64","ByteBuffer.zigZagDecode64","and","ONE","negate","writeVarint64","ByteBufferPrototype.writeVarint64","capacity11","writeVarint64ZigZag","ByteBufferPrototype.writeVarint64ZigZag","readVarint64","ByteBufferPrototype.readVarint64","fromBits","readVarint64ZigZag","ByteBufferPrototype.readVarint64ZigZag","writeCString","ByteBufferPrototype.writeCString","str","utfx","calculateUTF16asUTF8","capacity12","encodeUTF16toUTF8","bind","readCString","ByteBufferPrototype.readCString","sd","decodeUTF8toUTF16","writeIString","ByteBufferPrototype.writeIString","capacity13","readIString","ByteBufferPrototype.readIString","len","readUTF8String","METRICS_BYTES","METRICS_CHARS","writeUTF8String","ByteBufferPrototype.writeUTF8String","capacity14","writeString","calculateUTF8Chars","ByteBuffer.calculateUTF8Chars","calculateUTF8Bytes","ByteBuffer.calculateUTF8Bytes","calculateString","ByteBufferPrototype.readUTF8String","metrics","decodeUTF8","cp","UTF8toUTF16","readString","writeVString","ByteBufferPrototype.writeVString","l","capacity15","readVString","ByteBufferPrototype.readVString","append","ByteBufferPrototype.append","source","capacity16","appendTo","ByteBufferPrototype.appendTo","target","writeBytes","assert","ByteBufferPrototype.assert","ByteBufferPrototype.capacity","clear","ByteBufferPrototype.clear","ByteBufferPrototype.clone","copy","compact","ByteBufferPrototype.compact","begin","end","ByteBufferPrototype.copy","copyTo","ByteBufferPrototype.copyTo","targetOffset","sourceOffset","sourceLimit","targetRelative","ensureCapacity","ByteBufferPrototype.ensureCapacity","current","fill","ByteBufferPrototype.fill","flip","ByteBufferPrototype.flip","mark","ByteBufferPrototype.mark","order","ByteBufferPrototype.order","LE","ByteBufferPrototype.LE","BE","ByteBufferPrototype.BE","bigEndian","prepend","ByteBufferPrototype.prepend","diff","arrayView","prependTo","ByteBufferPrototype.prependTo","printDebug","ByteBufferPrototype.printDebug","out","console","log","toDebug","remaining","ByteBufferPrototype.remaining","reset","ByteBufferPrototype.reset","ByteBufferPrototype.resize","reverse","ByteBufferPrototype.reverse","skip","ByteBufferPrototype.skip","ByteBufferPrototype.slice","toBuffer","ByteBufferPrototype.toBuffer","forceCopy","toArrayBuffer","ByteBufferPrototype.toString","toUTF8","toBase64","toHex","toBinary","toColumns","lxiv","aout","ain","encode","lxiv.encode","src","dst","t","decode","lxiv.decode","fail","t1","t2","test","lxiv.test","ByteBufferPrototype.toBase64","ByteBuffer.fromBase64","btoa","ByteBuffer.btoa","atob","ByteBuffer.atob","b64","ByteBufferPrototype.toBinary","chars","parts","ByteBuffer.fromBinary","charCode","ByteBufferPrototype.toDebug","columns","hex","asc","toUpperCase","ByteBuffer.fromDebug","j","ch","rs","ho","hm","hl","charAt","parseInt","isNaN","ByteBufferPrototype.toHex","ByteBuffer.fromHex","substring","isFinite","utfx.encodeUTF8","utfx.decodeUTF8","a","d","indexOf","name","utfx.UTF16toUTF8","c1","c2","utfx.UTF8toUTF16","utfx.encodeUTF16toUTF8","UTF16toUTF8","encodeUTF8","utfx.decodeUTF8toUTF16","utfx.calculateCodePoint","utfx.calculateUTF8","utfx.calculateUTF16asUTF8","ByteBufferPrototype.toUTF8","ByteBuffer.fromUTF8"] +} diff --git a/dist/bytebuffer-node.js b/dist/bytebuffer-node.js new file mode 100644 index 0000000..70ba4f3 --- /dev/null +++ b/dist/bytebuffer-node.js @@ -0,0 +1,3454 @@ +/* + Copyright 2013-2014 Daniel Wirtz + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +/** + * @license bytebuffer.js (c) 2015 Daniel Wirtz + * Backing buffer / Accessor: node Buffer + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/bytebuffer.js for details + */ +module.exports = (function() { + "use strict"; + + var buffer = require("buffer"), + Buffer = buffer["Buffer"], + Long = require("long"), + memcpy = null; try { memcpy = require("memcpy"); } catch (e) {} + + /** + * Constructs a new ByteBuffer. + * @class The swiss army knife for binary data in JavaScript. + * @exports ByteBuffer + * @constructor + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @expose + */ + var ByteBuffer = function(capacity, littleEndian, noAssert) { + if (typeof capacity === 'undefined') + capacity = ByteBuffer.DEFAULT_CAPACITY; + if (typeof littleEndian === 'undefined') + littleEndian = ByteBuffer.DEFAULT_ENDIAN; + if (typeof noAssert === 'undefined') + noAssert = ByteBuffer.DEFAULT_NOASSERT; + if (!noAssert) { + capacity = capacity | 0; + if (capacity < 0) + throw RangeError("Illegal capacity"); + littleEndian = !!littleEndian; + noAssert = !!noAssert; + } + + /** + * Backing node Buffer. + * @type {!Buffer} + * @expose + */ + this.buffer = capacity === 0 ? EMPTY_BUFFER : new Buffer(capacity); + + /** + * Absolute read/write offset. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.offset = 0; + + /** + * Marked offset. + * @type {number} + * @expose + * @see ByteBuffer#mark + * @see ByteBuffer#reset + */ + this.markedOffset = -1; + + /** + * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.limit = capacity; + + /** + * Whether to use little endian byte order, defaults to `false` for big endian. + * @type {boolean} + * @expose + */ + this.littleEndian = littleEndian; + + /** + * Whether to skip assertions of offsets and values, defaults to `false`. + * @type {boolean} + * @expose + */ + this.noAssert = noAssert; + }; + + /** + * ByteBuffer version. + * @type {string} + * @const + * @expose + */ + ByteBuffer.VERSION = "5.0.1"; + + /** + * Little endian constant that can be used instead of its boolean value. Evaluates to `true`. + * @type {boolean} + * @const + * @expose + */ + ByteBuffer.LITTLE_ENDIAN = true; + + /** + * Big endian constant that can be used instead of its boolean value. Evaluates to `false`. + * @type {boolean} + * @const + * @expose + */ + ByteBuffer.BIG_ENDIAN = false; + + /** + * Default initial capacity of `16`. + * @type {number} + * @expose + */ + ByteBuffer.DEFAULT_CAPACITY = 16; + + /** + * Default endianess of `false` for big endian. + * @type {boolean} + * @expose + */ + ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN; + + /** + * Default no assertions flag of `false`. + * @type {boolean} + * @expose + */ + ByteBuffer.DEFAULT_NOASSERT = false; + + /** + * A `Long` class for representing a 64-bit two's-complement integer value. + * @type {!Long} + * @const + * @see https://npmjs.org/package/long + * @expose + */ + ByteBuffer.Long = Long; + + /** + * @alias ByteBuffer.prototype + * @inner + */ + var ByteBufferPrototype = ByteBuffer.prototype; + + /** + * An indicator used to reliably determine if an object is a ByteBuffer or not. + * @type {boolean} + * @const + * @expose + * @private + */ + ByteBufferPrototype.__isByteBuffer__; + + Object.defineProperty(ByteBufferPrototype, "__isByteBuffer__", { + value: true, + enumerable: false, + configurable: false + }); + + // helpers + + /** + * @type {!Buffer} + * @inner + */ + var EMPTY_BUFFER = new Buffer(0); + + /** + * String.fromCharCode reference for compile-time renaming. + * @type {function(...number):string} + * @inner + */ + var stringFromCharCode = String.fromCharCode; + + /** + * Creates a source function for a string. + * @param {string} s String to read from + * @returns {function():number|null} Source function returning the next char code respectively `null` if there are + * no more characters left. + * @throws {TypeError} If the argument is invalid + * @inner + */ + function stringSource(s) { + var i=0; return function() { + return i < s.length ? s.charCodeAt(i++) : null; + }; + } + + /** + * Creates a destination function for a string. + * @returns {function(number=):undefined|string} Destination function successively called with the next char code. + * Returns the final string when called without arguments. + * @inner + */ + function stringDestination() { + var cs = [], ps = []; return function() { + if (arguments.length === 0) + return ps.join('')+stringFromCharCode.apply(String, cs); + if (cs.length + arguments.length > 1024) + ps.push(stringFromCharCode.apply(String, cs)), + cs.length = 0; + Array.prototype.push.apply(cs, arguments); + }; + } + + /** + * Gets the accessor type. + * @returns {Function} `Buffer` under node.js, `Uint8Array` respectively `DataView` in the browser (classes) + * @expose + */ + ByteBuffer.accessor = function() { + return Buffer; + }; + /** + * Allocates a new ByteBuffer backed by a buffer of the specified capacity. + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} + * @expose + */ + ByteBuffer.allocate = function(capacity, littleEndian, noAssert) { + return new ByteBuffer(capacity, littleEndian, noAssert); + }; + + /** + * Concatenates multiple ByteBuffers into one. + * @param {!Array.} buffers Buffers to concatenate + * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary", + * defaults to "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults + * to {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} Concatenated ByteBuffer + * @expose + */ + ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) { + if (typeof encoding === 'boolean' || typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + var capacity = 0; + for (var i=0, k=buffers.length, length; i 0) capacity += length; + } + if (capacity === 0) + return new ByteBuffer(0, littleEndian, noAssert); + var bb = new ByteBuffer(capacity, littleEndian, noAssert), + bi; + i=0; while (i} buffer Anything that can be wrapped + * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to + * "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer` + * @expose + */ + ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) { + if (typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + if (typeof buffer === 'string') { + if (typeof encoding === 'undefined') + encoding = "utf8"; + switch (encoding) { + case "base64": + return ByteBuffer.fromBase64(buffer, littleEndian); + case "hex": + return ByteBuffer.fromHex(buffer, littleEndian); + case "binary": + return ByteBuffer.fromBinary(buffer, littleEndian); + case "utf8": + return ByteBuffer.fromUTF8(buffer, littleEndian); + case "debug": + return ByteBuffer.fromDebug(buffer, littleEndian); + default: + throw Error("Unsupported encoding: "+encoding); + } + } + if (buffer === null || typeof buffer !== 'object') + throw TypeError("Illegal buffer"); + var bb; + if (ByteBuffer.isByteBuffer(buffer)) { + bb = ByteBufferPrototype.clone.call(buffer); + bb.markedOffset = -1; + return bb; + } + var i = 0, + k = 0, + b; + if (buffer instanceof Uint8Array) { // Extract bytes from Uint8Array + b = new Buffer(buffer.length); + if (memcpy) { // Fast + memcpy(b, 0, buffer.buffer, buffer.byteOffset, buffer.byteOffset + buffer.length); + } else { // Slow + for (i=0, k=buffer.length; i 0) { // Avoid references to more than one EMPTY_BUFFER + bb.buffer = buffer; + bb.limit = buffer.length; + } + return bb; + }; + + /** + * Writes the array as a bitset. + * @param {Array} value Array of booleans to write + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ + ByteBufferPrototype.writeBitSet = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (!(value instanceof Array)) + throw TypeError("Illegal BitSet: Not an array"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + + var start = offset, + bits = value.length, + bytes = (bits >> 3), + bit = 0, + k; + + offset += this.writeVarint32(bits,offset); + + while(bytes--) { + k = (!!value[bit++] & 1) | + ((!!value[bit++] & 1) << 1) | + ((!!value[bit++] & 1) << 2) | + ((!!value[bit++] & 1) << 3) | + ((!!value[bit++] & 1) << 4) | + ((!!value[bit++] & 1) << 5) | + ((!!value[bit++] & 1) << 6) | + ((!!value[bit++] & 1) << 7); + this.writeByte(k,offset++); + } + + if(bit < bits) { + var m = 0; k = 0; + while(bit < bits) k = k | ((!!value[bit++] & 1) << (m++)); + this.writeByte(k,offset++); + } + + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + } + + /** + * Reads a BitSet as an array of booleans. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {Array + * @expose + */ + ByteBufferPrototype.readBitSet = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + + var ret = this.readVarint32(offset), + bits = ret.value, + bytes = (bits >> 3), + bit = 0, + value = [], + k; + + offset += ret.length; + + while(bytes--) { + k = this.readByte(offset++); + value[bit++] = !!(k & 0x01); + value[bit++] = !!(k & 0x02); + value[bit++] = !!(k & 0x04); + value[bit++] = !!(k & 0x08); + value[bit++] = !!(k & 0x10); + value[bit++] = !!(k & 0x20); + value[bit++] = !!(k & 0x40); + value[bit++] = !!(k & 0x80); + } + + if(bit < bits) { + var m = 0; + k = this.readByte(offset++); + while(bit < bits) value[bit++] = !!((k >> (m++)) & 1); + } + + if (relative) { + this.offset = offset; + } + return value; + } + /** + * Reads the specified number of bytes. + * @param {number} length Number of bytes to read + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ + ByteBufferPrototype.readBytes = function(length, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + length > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.length); + } + var slice = this.slice(offset, offset + length); + if (relative) this.offset += length; + return slice; + }; + + + // types/ints/int8 + + /** + * Writes an 8bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt8 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + offset += 1; + var capacity0 = this.buffer.length; + if (offset > capacity0) + this.resize((capacity0 *= 2) > offset ? capacity0 : offset); + offset -= 1; + this.buffer[offset] = value; + if (relative) this.offset += 1; + return this; + }; + + /** + * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8; + + /** + * Reads an 8bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt8 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.length); + } + var value = this.buffer[offset]; + if ((value & 0x80) === 0x80) value = -(0xFF - value + 1); // Cast to signed + if (relative) this.offset += 1; + return value; + }; + + /** + * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8; + + /** + * Writes an 8bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint8 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + offset += 1; + var capacity1 = this.buffer.length; + if (offset > capacity1) + this.resize((capacity1 *= 2) > offset ? capacity1 : offset); + offset -= 1; + this.buffer[offset] = value; + if (relative) this.offset += 1; + return this; + }; + + /** + * Writes an 8bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt8 = ByteBufferPrototype.writeUint8; + + /** + * Reads an 8bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUint8 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.length); + } + var value = this.buffer[offset]; + if (relative) this.offset += 1; + return value; + }; + + /** + * Reads an 8bit unsigned integer. This is an alias of {@link ByteBuffer#readUint8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUInt8 = ByteBufferPrototype.readUint8; + + // types/ints/int16 + + /** + * Writes a 16bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeInt16 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + offset += 2; + var capacity2 = this.buffer.length; + if (offset > capacity2) + this.resize((capacity2 *= 2) > offset ? capacity2 : offset); + offset -= 2; + if (this.littleEndian) { + this.buffer[offset+1] = (value & 0xFF00) >>> 8; + this.buffer[offset ] = value & 0x00FF; + } else { + this.buffer[offset] = (value & 0xFF00) >>> 8; + this.buffer[offset+1] = value & 0x00FF; + } + if (relative) this.offset += 2; + return this; + }; + + /** + * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16; + + /** + * Reads a 16bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readInt16 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 2 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.length); + } + var value = 0; + if (this.littleEndian) { + value = this.buffer[offset ]; + value |= this.buffer[offset+1] << 8; + } else { + value = this.buffer[offset ] << 8; + value |= this.buffer[offset+1]; + } + if ((value & 0x8000) === 0x8000) value = -(0xFFFF - value + 1); // Cast to signed + if (relative) this.offset += 2; + return value; + }; + + /** + * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16; + + /** + * Writes a 16bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeUint16 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + offset += 2; + var capacity3 = this.buffer.length; + if (offset > capacity3) + this.resize((capacity3 *= 2) > offset ? capacity3 : offset); + offset -= 2; + if (this.littleEndian) { + this.buffer[offset+1] = (value & 0xFF00) >>> 8; + this.buffer[offset ] = value & 0x00FF; + } else { + this.buffer[offset] = (value & 0xFF00) >>> 8; + this.buffer[offset+1] = value & 0x00FF; + } + if (relative) this.offset += 2; + return this; + }; + + /** + * Writes a 16bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeUInt16 = ByteBufferPrototype.writeUint16; + + /** + * Reads a 16bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readUint16 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 2 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.length); + } + var value = 0; + if (this.littleEndian) { + value = this.buffer[offset ]; + value |= this.buffer[offset+1] << 8; + } else { + value = this.buffer[offset ] << 8; + value |= this.buffer[offset+1]; + } + if (relative) this.offset += 2; + return value; + }; + + /** + * Reads a 16bit unsigned integer. This is an alias of {@link ByteBuffer#readUint16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readUInt16 = ByteBufferPrototype.readUint16; + + // types/ints/int32 + + /** + * Writes a 32bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeInt32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + offset += 4; + var capacity4 = this.buffer.length; + if (offset > capacity4) + this.resize((capacity4 *= 2) > offset ? capacity4 : offset); + offset -= 4; + if (this.littleEndian) { + this.buffer[offset+3] = (value >>> 24) & 0xFF; + this.buffer[offset+2] = (value >>> 16) & 0xFF; + this.buffer[offset+1] = (value >>> 8) & 0xFF; + this.buffer[offset ] = value & 0xFF; + } else { + this.buffer[offset ] = (value >>> 24) & 0xFF; + this.buffer[offset+1] = (value >>> 16) & 0xFF; + this.buffer[offset+2] = (value >>> 8) & 0xFF; + this.buffer[offset+3] = value & 0xFF; + } + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32; + + /** + * Reads a 32bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.length); + } + var value = 0; + if (this.littleEndian) { + value = this.buffer[offset+2] << 16; + value |= this.buffer[offset+1] << 8; + value |= this.buffer[offset ]; + value += this.buffer[offset+3] << 24 >>> 0; + } else { + value = this.buffer[offset+1] << 16; + value |= this.buffer[offset+2] << 8; + value |= this.buffer[offset+3]; + value += this.buffer[offset ] << 24 >>> 0; + } + value |= 0; // Cast to signed + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32; + + /** + * Writes a 32bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeUint32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + offset += 4; + var capacity5 = this.buffer.length; + if (offset > capacity5) + this.resize((capacity5 *= 2) > offset ? capacity5 : offset); + offset -= 4; + if (this.littleEndian) { + this.buffer[offset+3] = (value >>> 24) & 0xFF; + this.buffer[offset+2] = (value >>> 16) & 0xFF; + this.buffer[offset+1] = (value >>> 8) & 0xFF; + this.buffer[offset ] = value & 0xFF; + } else { + this.buffer[offset ] = (value >>> 24) & 0xFF; + this.buffer[offset+1] = (value >>> 16) & 0xFF; + this.buffer[offset+2] = (value >>> 8) & 0xFF; + this.buffer[offset+3] = value & 0xFF; + } + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeUInt32 = ByteBufferPrototype.writeUint32; + + /** + * Reads a 32bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUint32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.length); + } + var value = 0; + if (this.littleEndian) { + value = this.buffer[offset+2] << 16; + value |= this.buffer[offset+1] << 8; + value |= this.buffer[offset ]; + value += this.buffer[offset+3] << 24 >>> 0; + } else { + value = this.buffer[offset+1] << 16; + value |= this.buffer[offset+2] << 8; + value |= this.buffer[offset+3]; + value += this.buffer[offset ] << 24 >>> 0; + } + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit unsigned integer. This is an alias of {@link ByteBuffer#readUint32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUInt32 = ByteBufferPrototype.readUint32; + + // types/ints/int64 + + if (Long) { + + /** + * Writes a 64bit signed integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + offset += 8; + var capacity6 = this.buffer.length; + if (offset > capacity6) + this.resize((capacity6 *= 2) > offset ? capacity6 : offset); + offset -= 8; + var lo = value.low, + hi = value.high; + if (this.littleEndian) { + this.buffer[offset+3] = (lo >>> 24) & 0xFF; + this.buffer[offset+2] = (lo >>> 16) & 0xFF; + this.buffer[offset+1] = (lo >>> 8) & 0xFF; + this.buffer[offset ] = lo & 0xFF; + offset += 4; + this.buffer[offset+3] = (hi >>> 24) & 0xFF; + this.buffer[offset+2] = (hi >>> 16) & 0xFF; + this.buffer[offset+1] = (hi >>> 8) & 0xFF; + this.buffer[offset ] = hi & 0xFF; + } else { + this.buffer[offset ] = (hi >>> 24) & 0xFF; + this.buffer[offset+1] = (hi >>> 16) & 0xFF; + this.buffer[offset+2] = (hi >>> 8) & 0xFF; + this.buffer[offset+3] = hi & 0xFF; + offset += 4; + this.buffer[offset ] = (lo >>> 24) & 0xFF; + this.buffer[offset+1] = (lo >>> 16) & 0xFF; + this.buffer[offset+2] = (lo >>> 8) & 0xFF; + this.buffer[offset+3] = lo & 0xFF; + } + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64; + + /** + * Reads a 64bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readInt64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.length); + } + var lo = 0, + hi = 0; + if (this.littleEndian) { + lo = this.buffer[offset+2] << 16; + lo |= this.buffer[offset+1] << 8; + lo |= this.buffer[offset ]; + lo += this.buffer[offset+3] << 24 >>> 0; + offset += 4; + hi = this.buffer[offset+2] << 16; + hi |= this.buffer[offset+1] << 8; + hi |= this.buffer[offset ]; + hi += this.buffer[offset+3] << 24 >>> 0; + } else { + hi = this.buffer[offset+1] << 16; + hi |= this.buffer[offset+2] << 8; + hi |= this.buffer[offset+3]; + hi += this.buffer[offset ] << 24 >>> 0; + offset += 4; + lo = this.buffer[offset+1] << 16; + lo |= this.buffer[offset+2] << 8; + lo |= this.buffer[offset+3]; + lo += this.buffer[offset ] << 24 >>> 0; + } + var value = new Long(lo, hi, false); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64; + + /** + * Writes a 64bit unsigned integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + offset += 8; + var capacity7 = this.buffer.length; + if (offset > capacity7) + this.resize((capacity7 *= 2) > offset ? capacity7 : offset); + offset -= 8; + var lo = value.low, + hi = value.high; + if (this.littleEndian) { + this.buffer[offset+3] = (lo >>> 24) & 0xFF; + this.buffer[offset+2] = (lo >>> 16) & 0xFF; + this.buffer[offset+1] = (lo >>> 8) & 0xFF; + this.buffer[offset ] = lo & 0xFF; + offset += 4; + this.buffer[offset+3] = (hi >>> 24) & 0xFF; + this.buffer[offset+2] = (hi >>> 16) & 0xFF; + this.buffer[offset+1] = (hi >>> 8) & 0xFF; + this.buffer[offset ] = hi & 0xFF; + } else { + this.buffer[offset ] = (hi >>> 24) & 0xFF; + this.buffer[offset+1] = (hi >>> 16) & 0xFF; + this.buffer[offset+2] = (hi >>> 8) & 0xFF; + this.buffer[offset+3] = hi & 0xFF; + offset += 4; + this.buffer[offset ] = (lo >>> 24) & 0xFF; + this.buffer[offset+1] = (lo >>> 16) & 0xFF; + this.buffer[offset+2] = (lo >>> 8) & 0xFF; + this.buffer[offset+3] = lo & 0xFF; + } + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint64}. + * @function + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt64 = ByteBufferPrototype.writeUint64; + + /** + * Reads a 64bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUint64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.length); + } + var lo = 0, + hi = 0; + if (this.littleEndian) { + lo = this.buffer[offset+2] << 16; + lo |= this.buffer[offset+1] << 8; + lo |= this.buffer[offset ]; + lo += this.buffer[offset+3] << 24 >>> 0; + offset += 4; + hi = this.buffer[offset+2] << 16; + hi |= this.buffer[offset+1] << 8; + hi |= this.buffer[offset ]; + hi += this.buffer[offset+3] << 24 >>> 0; + } else { + hi = this.buffer[offset+1] << 16; + hi |= this.buffer[offset+2] << 8; + hi |= this.buffer[offset+3]; + hi += this.buffer[offset ] << 24 >>> 0; + offset += 4; + lo = this.buffer[offset+1] << 16; + lo |= this.buffer[offset+2] << 8; + lo |= this.buffer[offset+3]; + lo += this.buffer[offset ] << 24 >>> 0; + } + var value = new Long(lo, hi, true); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit unsigned integer. This is an alias of {@link ByteBuffer#readUint64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUInt64 = ByteBufferPrototype.readUint64; + + } // Long + + + // types/floats/float32 + + /** + * Writes a 32bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + offset += 4; + var capacity8 = this.buffer.length; + if (offset > capacity8) + this.resize((capacity8 *= 2) > offset ? capacity8 : offset); + offset -= 4; + this.littleEndian + ? this.buffer.writeFloatLE(value, offset, true) + : this.buffer.writeFloatBE(value, offset, true); + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32; + + /** + * Reads a 32bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.length); + } + var value = this.littleEndian + ? this.buffer.readFloatLE(offset, true) + : this.buffer.readFloatBE(offset, true); + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32; + + // types/floats/float64 + + /** + * Writes a 64bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + offset += 8; + var capacity9 = this.buffer.length; + if (offset > capacity9) + this.resize((capacity9 *= 2) > offset ? capacity9 : offset); + offset -= 8; + this.littleEndian + ? this.buffer.writeDoubleLE(value, offset, true) + : this.buffer.writeDoubleBE(value, offset, true); + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64; + + /** + * Reads a 64bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.length); + } + var value = this.littleEndian + ? this.buffer.readDoubleLE(offset, true) + : this.buffer.readDoubleBE(offset, true); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64; + + + // types/varints/varint32 + + /** + * Maximum number of bytes required to store a 32bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT32_BYTES = 5; + + /** + * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer. + * @param {number} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES} + * @expose + */ + ByteBuffer.calculateVarint32 = function(value) { + // ref: src/google/protobuf/io/coded_stream.cc + value = value >>> 0; + if (value < 1 << 7 ) return 1; + else if (value < 1 << 14) return 2; + else if (value < 1 << 21) return 3; + else if (value < 1 << 28) return 4; + else return 5; + }; + + /** + * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding. + * @param {number} n Signed 32bit integer + * @returns {number} Unsigned zigzag encoded 32bit integer + * @expose + */ + ByteBuffer.zigZagEncode32 = function(n) { + return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h + }; + + /** + * Decodes a zigzag encoded signed 32bit integer. + * @param {number} n Unsigned zigzag encoded 32bit integer + * @returns {number} Signed 32bit integer + * @expose + */ + ByteBuffer.zigZagDecode32 = function(n) { + return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h + }; + + /** + * Writes a 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeVarint32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + var size = ByteBuffer.calculateVarint32(value), + b; + offset += size; + var capacity10 = this.buffer.length; + if (offset > capacity10) + this.resize((capacity10 *= 2) > offset ? capacity10 : offset); + offset -= size; + value >>>= 0; + while (value >= 0x80) { + b = (value & 0x7f) | 0x80; + this.buffer[offset++] = b; + value >>>= 7; + } + this.buffer[offset++] = value; + if (relative) { + this.offset = offset; + return this; + } + return size; + }; + + /** + * Writes a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) { + return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset); + }; + + /** + * Reads a 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available + * to fully decode the varint. + * @expose + */ + ByteBufferPrototype.readVarint32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.length); + } + var c = 0, + value = 0 >>> 0, + b; + do { + if (!this.noAssert && offset > this.limit) { + var err = Error("Truncated"); + err['truncated'] = true; + throw err; + } + b = this.buffer[offset++]; + if (c < 5) + value |= (b & 0x7f) << (7*c); + ++c; + } while ((b & 0x80) !== 0); + value |= 0; + if (relative) { + this.offset = offset; + return value; + } + return { + "value": value, + "length": c + }; + }; + + /** + * Reads a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint32ZigZag = function(offset) { + var val = this.readVarint32(offset); + if (typeof val === 'object') + val["value"] = ByteBuffer.zigZagDecode32(val["value"]); + else + val = ByteBuffer.zigZagDecode32(val); + return val; + }; + + // types/varints/varint64 + + if (Long) { + + /** + * Maximum number of bytes required to store a 64bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT64_BYTES = 10; + + /** + * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer. + * @param {number|!Long} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES} + * @expose + */ + ByteBuffer.calculateVarint64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + // ref: src/google/protobuf/io/coded_stream.cc + var part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + if (part2 == 0) { + if (part1 == 0) { + if (part0 < 1 << 14) + return part0 < 1 << 7 ? 1 : 2; + else + return part0 < 1 << 21 ? 3 : 4; + } else { + if (part1 < 1 << 14) + return part1 < 1 << 7 ? 5 : 6; + else + return part1 < 1 << 21 ? 7 : 8; + } + } else + return part2 < 1 << 7 ? 9 : 10; + }; + + /** + * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding. + * @param {number|!Long} value Signed long + * @returns {!Long} Unsigned zigzag encoded long + * @expose + */ + ByteBuffer.zigZagEncode64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned(); + }; + + /** + * Decodes a zigzag encoded signed 64bit integer. + * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number + * @returns {!Long} Signed long + * @expose + */ + ByteBuffer.zigZagDecode64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned(); + }; + + /** + * Writes a 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + var size = ByteBuffer.calculateVarint64(value), + part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + offset += size; + var capacity11 = this.buffer.length; + if (offset > capacity11) + this.resize((capacity11 *= 2) > offset ? capacity11 : offset); + offset -= size; + switch (size) { + case 10: this.buffer[offset+9] = (part2 >>> 7) & 0x01; + case 9 : this.buffer[offset+8] = size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F; + case 8 : this.buffer[offset+7] = size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F; + case 7 : this.buffer[offset+6] = size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F; + case 6 : this.buffer[offset+5] = size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F; + case 5 : this.buffer[offset+4] = size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F; + case 4 : this.buffer[offset+3] = size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F; + case 3 : this.buffer[offset+2] = size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F; + case 2 : this.buffer[offset+1] = size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F; + case 1 : this.buffer[offset ] = size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F; + } + if (relative) { + this.offset += size; + return this; + } else { + return size; + } + }; + + /** + * Writes a zig-zag encoded 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) { + return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); + }; + + /** + * Reads a 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.length); + } + // ref: src/google/protobuf/io/coded_stream.cc + var start = offset, + part0 = 0, + part1 = 0, + part2 = 0, + b = 0; + b = this.buffer[offset++]; part0 = (b & 0x7F) ; if ( b & 0x80 ) { + b = this.buffer[offset++]; part0 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.buffer[offset++]; part0 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.buffer[offset++]; part0 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.buffer[offset++]; part1 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.buffer[offset++]; part1 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.buffer[offset++]; part1 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.buffer[offset++]; part1 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.buffer[offset++]; part2 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.buffer[offset++]; part2 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + throw Error("Buffer overrun"); }}}}}}}}}} + var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false); + if (relative) { + this.offset = offset; + return value; + } else { + return { + 'value': value, + 'length': offset-start + }; + } + }; + + /** + * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64ZigZag = function(offset) { + var val = this.readVarint64(offset); + if (val && val['value'] instanceof Long) + val["value"] = ByteBuffer.zigZagDecode64(val["value"]); + else + val = ByteBuffer.zigZagDecode64(val); + return val; + }; + + } // Long + + + // types/strings/cstring + + /** + * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL + * characters itself. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * contained in `str` + 1 if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeCString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + var i, + k = str.length; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + for (i=0; i>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + // UTF8 strings do not contain zero bytes in between except for the zero character, so: + k = Buffer.byteLength(str, "utf8"); + offset += k+1; + var capacity12 = this.buffer.length; + if (offset > capacity12) + this.resize((capacity12 *= 2) > offset ? capacity12 : offset); + offset -= k+1; + offset += this.buffer.write(str, offset, k, "utf8"); + this.buffer[offset++] = 0; + if (relative) { + this.offset = offset; + return this; + } + return k; + }; + + /** + * Reads a NULL-terminated UTF8 encoded string. For this to work the string read must not contain any NULL characters + * itself. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readCString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.length); + } + var start = offset, + temp; + // UTF8 strings do not contain zero bytes in between except for the zero character itself, so: + do { + if (offset >= this.buffer.length) + throw RangeError("Index out of range: "+offset+" <= "+this.buffer.length); + temp = this.buffer[offset++]; + } while (temp !== 0); + var str = this.buffer.toString("utf8", start, offset-1); + if (relative) { + this.offset = offset; + return str; + } else { + return { + "string": str, + "length": offset - start + }; + } + }; + + // types/strings/istring + + /** + * Writes a length as uint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ + ByteBufferPrototype.writeIString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + var start = offset, + k; + k = Buffer.byteLength(str, "utf8"); + offset += 4+k; + var capacity13 = this.buffer.length; + if (offset > capacity13) + this.resize((capacity13 *= 2) > offset ? capacity13 : offset); + offset -= 4+k; + if (this.littleEndian) { + this.buffer[offset+3] = (k >>> 24) & 0xFF; + this.buffer[offset+2] = (k >>> 16) & 0xFF; + this.buffer[offset+1] = (k >>> 8) & 0xFF; + this.buffer[offset ] = k & 0xFF; + } else { + this.buffer[offset ] = (k >>> 24) & 0xFF; + this.buffer[offset+1] = (k >>> 16) & 0xFF; + this.buffer[offset+2] = (k >>> 8) & 0xFF; + this.buffer[offset+3] = k & 0xFF; + } + offset += 4; + offset += this.buffer.write(str, offset, k, "utf8"); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Reads a length as uint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ + ByteBufferPrototype.readIString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.length); + } + var start = offset; + var len = this.readUint32(offset); + var str = this.readUTF8String(len, ByteBuffer.METRICS_BYTES, offset += 4); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } + }; + + // types/strings/utf8string + + /** + * Metrics representing number of UTF8 characters. Evaluates to `c`. + * @type {string} + * @const + * @expose + */ + ByteBuffer.METRICS_CHARS = 'c'; + + /** + * Metrics representing number of bytes. Evaluates to `b`. + * @type {string} + * @const + * @expose + */ + ByteBuffer.METRICS_BYTES = 'b'; + + /** + * Writes an UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeUTF8String = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + var k; + k = Buffer.byteLength(str, "utf8"); + offset += k; + var capacity14 = this.buffer.length; + if (offset > capacity14) + this.resize((capacity14 *= 2) > offset ? capacity14 : offset); + offset -= k; + offset += this.buffer.write(str, offset, k, "utf8"); + if (relative) { + this.offset = offset; + return this; + } + return k; + }; + + /** + * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}. + * @function + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String; + + /** + * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's + * `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 characters + * @expose + */ + ByteBuffer.calculateUTF8Chars = function(str) { + return utfx.calculateUTF16asUTF8(stringSource(str))[0]; + }; + + /** + * Calculates the number of UTF8 bytes of a string. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ + ByteBuffer.calculateUTF8Bytes = function(str) { + if (typeof str !== 'string') + throw TypeError("Illegal argument: "+(typeof str)); + return Buffer.byteLength(str, "utf8"); + }; + + /** + * Calculates the number of UTF8 bytes of a string. This is an alias of {@link ByteBuffer.calculateUTF8Bytes}. + * @function + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ + ByteBuffer.calculateString = ByteBuffer.calculateUTF8Bytes; + + /** + * Reads an UTF8 encoded string. + * @param {number} length Number of characters or bytes to read. + * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readUTF8String = function(length, metrics, offset) { + if (typeof metrics === 'number') { + offset = metrics; + metrics = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS; + if (!this.noAssert) { + if (typeof length !== 'number' || length % 1 !== 0) + throw TypeError("Illegal length: "+length+" (not an integer)"); + length |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + var i = 0, + start = offset, + temp, + sd; + if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser + sd = stringDestination(); + utfx.decodeUTF8(function() { + return i < length && offset < this.limit ? this.buffer[offset++] : null; + }.bind(this), function(cp) { + ++i; utfx.UTF8toUTF16(cp, sd); + }); + if (i !== length) + throw RangeError("Illegal range: Truncated data, "+i+" == "+length); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + } else if (metrics === ByteBuffer.METRICS_BYTES) { + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + length > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.length); + } + temp = this.buffer.toString("utf8", offset, offset+length); + if (relative) { + this.offset += length; + return temp; + } else { + return { + 'string': temp, + 'length': length + }; + } + } else + throw TypeError("Unsupported metrics: "+metrics); + }; + + /** + * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}. + * @function + * @param {number} length Number of characters or bytes to read + * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String; + + // types/strings/vstring + + /** + * Writes a length as varint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ + ByteBufferPrototype.writeVString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + var start = offset, + k, l; + k = Buffer.byteLength(str, "utf8"); + l = ByteBuffer.calculateVarint32(k); + offset += l+k; + var capacity15 = this.buffer.length; + if (offset > capacity15) + this.resize((capacity15 *= 2) > offset ? capacity15 : offset); + offset -= l+k; + offset += this.writeVarint32(k, offset); + offset += this.buffer.write(str, offset, k, "utf8"); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Reads a length as varint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ + ByteBufferPrototype.readVString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.length); + } + var start = offset; + var len = this.readVarint32(offset); + var str = this.readUTF8String(len['value'], ByteBuffer.METRICS_BYTES, offset += len['length']); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } + }; + + + /** + * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended + * data's length. + * @param {!ByteBuffer|!Buffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its + * offsets will be modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|` + * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|` + */ + ByteBufferPrototype.append = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var length = source.limit - source.offset; + if (length <= 0) return this; // Nothing to append + offset += length; + var capacity16 = this.buffer.length; + if (offset > capacity16) + this.resize((capacity16 *= 2) > offset ? capacity16 : offset); + offset -= length; + source.buffer.copy(this.buffer, offset, source.offset, source.limit); + source.offset += length; + if (relative) this.offset += length; + return this; + }; + + /** + * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents at and after the + specified offset up to the length of this ByteBuffer's data. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#append + */ + ByteBufferPrototype.appendTo = function(target, offset) { + target.append(this, offset); + return this; + }; + + /** + * Writes a payload of bytes. This is an alias of {@link ByteBuffer#append}. + * @function + * @param {!ByteBuffer|!Buffer|!ArrayBuffer|!Uint8Array|string} source Data to write. If `source` is a ByteBuffer, its + * offsets will be modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeBytes = ByteBufferPrototype.append; + /** + * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to + * disable them if your code already makes sure that everything is valid. + * @param {boolean} assert `true` to enable assertions, otherwise `false` + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.assert = function(assert) { + this.noAssert = !assert; + return this; + }; + + /** + * Gets the capacity of this ByteBuffer's backing buffer. + * @returns {number} Capacity of the backing buffer + * @expose + */ + ByteBufferPrototype.capacity = function() { + return this.buffer.length; + }; + /** + * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the + * backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.clear = function() { + this.offset = 0; + this.limit = this.buffer.length; + this.markedOffset = -1; + return this; + }; + + /** + * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset}, + * {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}. + * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false` + * @returns {!ByteBuffer} Cloned instance + * @expose + */ + ByteBufferPrototype.clone = function(copy) { + var bb = new ByteBuffer(0, this.littleEndian, this.noAssert); + if (copy) { + var buffer = new Buffer(this.buffer.length); + this.buffer.copy(buffer); + bb.buffer = buffer; + } else { + bb.buffer = this.buffer; + } + bb.offset = this.offset; + bb.markedOffset = this.markedOffset; + bb.limit = this.limit; + return bb; + }; + + /** + * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes + * between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and + * adapt {@link ByteBuffer#markedOffset} to the same relative position if set. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.compact = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.length); + } + if (begin === 0 && end === this.buffer.length) + return this; // Already compacted + var len = end - begin; + if (len === 0) { + this.buffer = EMPTY_BUFFER; + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = 0; + return this; + } + var buffer = new Buffer(len); + this.buffer.copy(buffer, 0, begin, end); + this.buffer = buffer; + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = len; + return this; + }; + + /** + * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Copy + * @expose + */ + ByteBufferPrototype.copy = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.length); + } + if (begin === end) + return new ByteBuffer(0, this.littleEndian, this.noAssert); + var capacity = end - begin, + bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert); + bb.offset = 0; + bb.limit = capacity; + if (bb.markedOffset >= 0) bb.markedOffset -= begin; + this.copyTo(bb, 0, begin, end); + return bb; + }; + + /** + * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset} + * by the number of bytes copied if omitted. + * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the + * number of bytes copied if omitted. + * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) { + var relative, + targetRelative; + if (!this.noAssert) { + if (!ByteBuffer.isByteBuffer(target)) + throw TypeError("Illegal target: Not a ByteBuffer"); + } + targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0; + sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0; + sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0; + + if (targetOffset < 0 || targetOffset > target.buffer.length) + throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+target.buffer.length); + if (sourceOffset < 0 || sourceLimit > this.buffer.length) + throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+this.buffer.length); + + var len = sourceLimit - sourceOffset; + if (len === 0) + return target; // Nothing to copy + + target.ensureCapacity(targetOffset + len); + + this.buffer.copy(target.buffer, targetOffset, sourceOffset, sourceLimit); + + if (relative) this.offset += len; + if (targetRelative) target.offset += len; + + return this; + }; + + /** + * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the + * current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity, + * the required capacity will be used instead. + * @param {number} capacity Required capacity + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.ensureCapacity = function(capacity) { + var current = this.buffer.length; + if (current < capacity) + return this.resize((current *= 2) > capacity ? current : capacity); + return this; + }; + + /** + * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {number|string} value Byte value to fill with. If given as a string, the first character is used. + * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} this + * @expose + * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes + */ + ByteBufferPrototype.fill = function(value, begin, end) { + var relative = typeof begin === 'undefined'; + if (relative) begin = this.offset; + if (typeof value === 'string' && value.length > 0) + value = value.charCodeAt(0); + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.length); + } + if (begin >= end) + return this; // Nothing to fill + this.buffer.fill(value, begin, end); + begin = end; + if (relative) this.offset = begin; + return this; + }; + + /** + * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and + * `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.flip = function() { + this.limit = this.offset; + this.offset = 0; + return this; + }; + /** + * Marks an offset on this ByteBuffer to be used later. + * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}. + * @returns {!ByteBuffer} this + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @see ByteBuffer#reset + * @expose + */ + ByteBufferPrototype.mark = function(offset) { + offset = typeof offset === 'undefined' ? this.offset : offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + this.markedOffset = offset; + return this; + }; + /** + * Sets the byte order. + * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.order = function(littleEndian) { + if (!this.noAssert) { + if (typeof littleEndian !== 'boolean') + throw TypeError("Illegal littleEndian: Not a boolean"); + } + this.littleEndian = !!littleEndian; + return this; + }; + + /** + * Switches (to) little endian byte order. + * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.LE = function(littleEndian) { + this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true; + return this; + }; + + /** + * Switches (to) big endian byte order. + * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.BE = function(bigEndian) { + this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false; + return this; + }; + /** + * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer|string||!Buffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be modified + * according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|` + * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|` + */ + ByteBufferPrototype.prepend = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.length) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.length); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var len = source.limit - source.offset; + if (len <= 0) return this; // Nothing to prepend + var diff = len - offset; + if (diff > 0) { // Not enough space before offset, so resize + move + var buffer = new Buffer(this.buffer.length + diff); + this.buffer.copy(buffer, len, offset, this.buffer.length); + this.buffer = buffer; + this.offset += diff; + if (this.markedOffset >= 0) this.markedOffset += diff; + this.limit += diff; + offset += diff; + } source.buffer.copy(this.buffer, offset - len, source.offset, source.limit); + + source.offset = source.limit; + if (relative) + this.offset -= len; + return this; + }; + + /** + * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#prepend + */ + ByteBufferPrototype.prependTo = function(target, offset) { + target.prepend(this, offset); + return this; + }; + /** + * Prints debug information about this ByteBuffer's contents. + * @param {function(string)=} out Output function to call, defaults to console.log + * @expose + */ + ByteBufferPrototype.printDebug = function(out) { + if (typeof out !== 'function') out = console.log.bind(console); + out( + this.toString()+"\n"+ + "-------------------------------------------------------------------\n"+ + this.toDebug(/* columns */ true) + ); + }; + + /** + * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}, so this returns `limit - offset`. + * @returns {number} Remaining readable bytes. May be negative if `offset > limit`. + * @expose + */ + ByteBufferPrototype.remaining = function() { + return this.limit - this.offset; + }; + /** + * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark} + * before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been + * marked, sets `offset = 0`. + * @returns {!ByteBuffer} this + * @see ByteBuffer#mark + * @expose + */ + ByteBufferPrototype.reset = function() { + if (this.markedOffset >= 0) { + this.offset = this.markedOffset; + this.markedOffset = -1; + } else { + this.offset = 0; + } + return this; + }; + /** + * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that + * large or larger. + * @param {number} capacity Capacity required + * @returns {!ByteBuffer} this + * @throws {TypeError} If `capacity` is not a number + * @throws {RangeError} If `capacity < 0` + * @expose + */ + ByteBufferPrototype.resize = function(capacity) { + if (!this.noAssert) { + if (typeof capacity !== 'number' || capacity % 1 !== 0) + throw TypeError("Illegal capacity: "+capacity+" (not an integer)"); + capacity |= 0; + if (capacity < 0) + throw RangeError("Illegal capacity: 0 <= "+capacity); + } + if (this.buffer.length < capacity) { + var buffer = new Buffer(capacity); + this.buffer.copy(buffer); + this.buffer = buffer; + } + return this; + }; + /** + * Reverses this ByteBuffer's contents. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.reverse = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.length); + } + if (begin === end) + return this; // Nothing to reverse + Array.prototype.reverse.call(this.buffer.slice(begin, end)); + return this; + }; + /** + * Skips the next `length` bytes. This will just advance + * @param {number} length Number of bytes to skip. May also be negative to move the offset back. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.skip = function(length) { + if (!this.noAssert) { + if (typeof length !== 'number' || length % 1 !== 0) + throw TypeError("Illegal length: "+length+" (not an integer)"); + length |= 0; + } + var offset = this.offset + length; + if (!this.noAssert) { + if (offset < 0 || offset > this.buffer.length) + throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+this.buffer.length); + } + this.offset = offset; + return this; + }; + + /** + * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer} + * @expose + */ + ByteBufferPrototype.slice = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.length); + } + var bb = this.clone(); + bb.offset = begin; + bb.limit = end; + return bb; + }; + /** + * Returns a copy of the backing buffer that contains this ByteBuffer's contents. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory if + * possible. Defaults to `false` + * @returns {!Buffer} Contents as a Buffer + * @expose + */ + ByteBufferPrototype.toBuffer = function(forceCopy) { + var offset = this.offset, + limit = this.limit; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: Not an integer"); + offset >>>= 0; + if (typeof limit !== 'number' || limit % 1 !== 0) + throw TypeError("Illegal limit: Not an integer"); + limit >>>= 0; + if (offset < 0 || offset > limit || limit > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.length); + } + if (forceCopy) { + var buffer = new Buffer(limit - offset); + this.buffer.copy(buffer, 0, offset, limit); + return buffer; + } else { + if (offset === 0 && limit === this.buffer.length) + return this.buffer; + else + return this.buffer.slice(offset, limit); + } + }; + + /** + * Returns a copy of the backing buffer compacted to contain this ByteBuffer's contents. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @returns {!ArrayBuffer} Contents as an ArrayBuffer + */ + ByteBufferPrototype.toArrayBuffer = function() { + var offset = this.offset, + limit = this.limit; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: Not an integer"); + offset >>>= 0; + if (typeof limit !== 'number' || limit % 1 !== 0) + throw TypeError("Illegal limit: Not an integer"); + limit >>>= 0; + if (offset < 0 || offset > limit || limit > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.length); + } + var ab = new ArrayBuffer(limit - offset); + if (memcpy) { // Fast + memcpy(ab, 0, this.buffer, offset, limit); + } else { // Slow + var dst = new Uint8Array(ab); + for (var i=offset; i this.capacity || begin > end) + throw RangeError("begin, end"); + return this.buffer.toString("base64", begin, end); + }; + + /** + * Decodes a base64 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromBase64 = function(str, littleEndian) { + return ByteBuffer.wrap(new Buffer(str, "base64"), littleEndian); + return bb; + }; + + /** + * Encodes a binary string to base64 like `window.btoa` does. + * @param {string} str Binary string + * @returns {string} Base64 encoded string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa + * @expose + */ + ByteBuffer.btoa = function(str) { + return ByteBuffer.fromBinary(str).toBase64(); + }; + + /** + * Decodes a base64 encoded string to binary like `window.atob` does. + * @param {string} b64 Base64 encoded string + * @returns {string} Binary string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob + * @expose + */ + ByteBuffer.atob = function(b64) { + return ByteBuffer.fromBase64(b64).toBinary(); + }; + + // encodings/binary + + /** + * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes. + * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}. + * @returns {string} Binary encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ + ByteBufferPrototype.toBinary = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin |= 0; end |= 0; + if (begin < 0 || end > this.capacity() || begin > end) + throw RangeError("begin, end"); + return this.buffer.toString("binary", begin, end); + }; + + /** + * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromBinary = function(str, littleEndian) { + return ByteBuffer.wrap(new Buffer(str, "binary"), littleEndian); + return bb; + }; + + // encodings/debug + + /** + * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are: + * * `<` : offset, + * * `'` : markedOffset, + * * `>` : limit, + * * `|` : offset and limit, + * * `[` : offset and markedOffset, + * * `]` : markedOffset and limit, + * * `!` : offset, markedOffset and limit + * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false` + * @returns {string|!Array.} Debug string or array of lines if `asArray = true` + * @expose + * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3` + * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4` + * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1` + * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1` + */ + ByteBufferPrototype.toDebug = function(columns) { + var i = -1, + k = this.buffer.length, + b, + hex = "", + asc = "", + out = ""; + while (i 32 && b < 127 ? String.fromCharCode(b) : '.'; + } + ++i; + if (columns) { + if (i > 0 && i % 16 === 0 && i !== k) { + while (hex.length < 3*16+3) hex += " "; + out += hex+asc+"\n"; + hex = asc = ""; + } + } + if (i === this.offset && i === this.limit) + hex += i === this.markedOffset ? "!" : "|"; + else if (i === this.offset) + hex += i === this.markedOffset ? "[" : "<"; + else if (i === this.limit) + hex += i === this.markedOffset ? "]" : ">"; + else + hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : ""); + } + if (columns && hex !== " ") { + while (hex.length < 3*16+3) + hex += " "; + out += hex + asc + "\n"; + } + return columns ? out : hex; + }; + + /** + * Decodes a hex encoded string with marked offsets to a ByteBuffer. + * @param {string} str Debug string to decode (not be generated with `columns = true`) + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + * @see ByteBuffer#toDebug + */ + ByteBuffer.fromDebug = function(str, littleEndian, noAssert) { + var k = str.length, + bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert); + var i = 0, j = 0, ch, b, + rs = false, // Require symbol next + ho = false, hm = false, hl = false, // Already has offset (ho), markedOffset (hm), limit (hl)? + fail = false; + while (i': + if (!noAssert) { + if (hl) { + fail = true; + break; + } + hl = true; + } + bb.limit = j; + rs = false; + break; + case "'": + if (!noAssert) { + if (hm) { + fail = true; + break; + } + hm = true; + } + bb.markedOffset = j; + rs = false; + break; + case ' ': + rs = false; + break; + default: + if (!noAssert) { + if (rs) { + fail = true; + break; + } + } + b = parseInt(ch+str.charAt(i++), 16); + if (!noAssert) { + if (isNaN(b) || b < 0 || b > 255) + throw TypeError("Illegal str: Not a debug encoded string"); + } + bb.buffer[j++] = b; + rs = true; + } + if (fail) + throw TypeError("Illegal str: Invalid symbol at "+i); + } + if (!noAssert) { + if (!ho || !hl) + throw TypeError("Illegal str: Missing offset or limit"); + if (j>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.length); + } + return this.buffer.toString("hex", begin, end); + }; + + /** + * Decodes a hex encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromHex = function(str, littleEndian, noAssert) { + if (!noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (str.length % 2 !== 0) + throw TypeError("Illegal str: Length not a multiple of 2"); + } + var bb = new ByteBuffer(0, littleEndian, true); + bb.buffer = new Buffer(str, "hex"); + bb.limit = bb.buffer.length; + return bb; + }; + + // utfx-embeddable + + /** + * utfx-embeddable (c) 2014 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/utfx for details + */ + var utfx = function() { + "use strict"; + + /** + * utfx namespace. + * @inner + * @type {!Object.} + */ + var utfx = {}; + + /** + * Maximum valid code point. + * @type {number} + * @const + */ + utfx.MAX_CODEPOINT = 0x10FFFF; + + /** + * Encodes UTF8 code points to UTF8 bytes. + * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point + * respectively `null` if there are no more code points left or a single numeric code point. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte + */ + utfx.encodeUTF8 = function(src, dst) { + var cp = null; + if (typeof src === 'number') + cp = src, + src = function() { return null; }; + while (cp !== null || (cp = src()) !== null) { + if (cp < 0x80) + dst(cp&0x7F); + else if (cp < 0x800) + dst(((cp>>6)&0x1F)|0xC0), + dst((cp&0x3F)|0x80); + else if (cp < 0x10000) + dst(((cp>>12)&0x0F)|0xE0), + dst(((cp>>6)&0x3F)|0x80), + dst((cp&0x3F)|0x80); + else + dst(((cp>>18)&0x07)|0xF0), + dst(((cp>>12)&0x3F)|0x80), + dst(((cp>>6)&0x3F)|0x80), + dst((cp&0x3F)|0x80); + cp = null; + } + }; + + /** + * Decodes UTF8 bytes to UTF8 code points. + * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there + * are no more bytes left. + * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point. + * @throws {RangeError} If a starting byte is invalid in UTF8 + * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the + * remaining bytes. + */ + utfx.decodeUTF8 = function(src, dst) { + var a, b, c, d, fail = function(b) { + b = b.slice(0, b.indexOf(null)); + var err = Error(b.toString()); + err.name = "TruncatedError"; + err['bytes'] = b; + throw err; + }; + while ((a = src()) !== null) { + if ((a&0x80) === 0) + dst(a); + else if ((a&0xE0) === 0xC0) + ((b = src()) === null) && fail([a, b]), + dst(((a&0x1F)<<6) | (b&0x3F)); + else if ((a&0xF0) === 0xE0) + ((b=src()) === null || (c=src()) === null) && fail([a, b, c]), + dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F)); + else if ((a&0xF8) === 0xF0) + ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]), + dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F)); + else throw RangeError("Illegal starting byte: "+a); + } + }; + + /** + * Converts UTF16 characters to UTF8 code points. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @param {!function(number)} dst Code points destination as a function successively called with each converted code + * point. + */ + utfx.UTF16toUTF8 = function(src, dst) { + var c1, c2 = null; + while (true) { + if ((c1 = c2 !== null ? c2 : src()) === null) + break; + if (c1 >= 0xD800 && c1 <= 0xDFFF) { + if ((c2 = src()) !== null) { + if (c2 >= 0xDC00 && c2 <= 0xDFFF) { + dst((c1-0xD800)*0x400+c2-0xDC00+0x10000); + c2 = null; continue; + } + } + } + dst(c1); + } + if (c2 !== null) dst(c2); + }; + + /** + * Converts UTF8 code points to UTF16 characters. + * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point + * respectively `null` if there are no more code points left or a single numeric code point. + * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. + * @throws {RangeError} If a code point is out of range + */ + utfx.UTF8toUTF16 = function(src, dst) { + var cp = null; + if (typeof src === 'number') + cp = src, src = function() { return null; }; + while (cp !== null || (cp = src()) !== null) { + if (cp <= 0xFFFF) + dst(cp); + else + cp -= 0x10000, + dst((cp>>10)+0xD800), + dst((cp%0x400)+0xDC00); + cp = null; + } + }; + + /** + * Converts and encodes UTF16 characters to UTF8 bytes. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null` + * if there are no more characters left. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. + */ + utfx.encodeUTF16toUTF8 = function(src, dst) { + utfx.UTF16toUTF8(src, function(cp) { + utfx.encodeUTF8(cp, dst); + }); + }; + + /** + * Decodes and converts UTF8 bytes to UTF16 characters. + * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there + * are no more bytes left. + * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. + * @throws {RangeError} If a starting byte is invalid in UTF8 + * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes. + */ + utfx.decodeUTF8toUTF16 = function(src, dst) { + utfx.decodeUTF8(src, function(cp) { + utfx.UTF8toUTF16(cp, dst); + }); + }; + + /** + * Calculates the byte length of an UTF8 code point. + * @param {number} cp UTF8 code point + * @returns {number} Byte length + */ + utfx.calculateCodePoint = function(cp) { + return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + }; + + /** + * Calculates the number of UTF8 bytes required to store UTF8 code points. + * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively + * `null` if there are no more code points left. + * @returns {number} The number of UTF8 bytes required + */ + utfx.calculateUTF8 = function(src) { + var cp, l=0; + while ((cp = src()) !== null) + l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + return l; + }; + + /** + * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes. + * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @returns {!Array.} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1. + */ + utfx.calculateUTF16asUTF8 = function(src) { + var n=0, l=0; + utfx.UTF16toUTF8(src, function(cp) { + ++n; l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + }); + return [n,l]; + }; + + return utfx; + }(); + + // encodings/utf8 + + /** + * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded + * string. + * @returns {string} Hex encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ + ByteBufferPrototype.toUTF8 = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.length) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.length); + } + return this.buffer.toString("utf8", begin, end); + }; + + /** + * Decodes an UTF8 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) { + if (!noAssert) + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + var bb = new ByteBuffer(0, littleEndian, noAssert); + bb.buffer = new Buffer(str, "utf8"); + bb.limit = bb.buffer.length; + return bb; + }; + + + /** + * node-memcpy. This is an optional binding dependency and may not be present. + * @function + * @param {!(Buffer|ArrayBuffer|Uint8Array)} target Destination + * @param {number|!(Buffer|ArrayBuffer)} targetStart Destination start, defaults to 0. + * @param {(!(Buffer|ArrayBuffer|Uint8Array)|number)=} source Source + * @param {number=} sourceStart Source start, defaults to 0. + * @param {number=} sourceEnd Source end, defaults to capacity. + * @returns {number} Number of bytes copied + * @throws {Error} If any index is out of bounds + * @expose + */ + ByteBuffer.memcpy = memcpy; + + return ByteBuffer; + +})(); diff --git a/dist/bytebuffer.js b/dist/bytebuffer.js new file mode 100644 index 0000000..8362fa3 --- /dev/null +++ b/dist/bytebuffer.js @@ -0,0 +1,3746 @@ +/* + Copyright 2013-2014 Daniel Wirtz + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +/** + * @license bytebuffer.js (c) 2015 Daniel Wirtz + * Backing buffer: ArrayBuffer, Accessor: Uint8Array + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/bytebuffer.js for details + */ +(function(global, factory) { + + /* AMD */ if (typeof define === 'function' && define["amd"]) + define(["long"], factory); + /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) + module['exports'] = (function() { + var Long; try { Long = require("long"); } catch (e) {} + return factory(Long); + })(); + /* Global */ else + (global["dcodeIO"] = global["dcodeIO"] || {})["ByteBuffer"] = factory(global["dcodeIO"]["Long"]); + +})(this, function(Long) { + "use strict"; + + /** + * Constructs a new ByteBuffer. + * @class The swiss army knife for binary data in JavaScript. + * @exports ByteBuffer + * @constructor + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @expose + */ + var ByteBuffer = function(capacity, littleEndian, noAssert) { + if (typeof capacity === 'undefined') + capacity = ByteBuffer.DEFAULT_CAPACITY; + if (typeof littleEndian === 'undefined') + littleEndian = ByteBuffer.DEFAULT_ENDIAN; + if (typeof noAssert === 'undefined') + noAssert = ByteBuffer.DEFAULT_NOASSERT; + if (!noAssert) { + capacity = capacity | 0; + if (capacity < 0) + throw RangeError("Illegal capacity"); + littleEndian = !!littleEndian; + noAssert = !!noAssert; + } + + /** + * Backing ArrayBuffer. + * @type {!ArrayBuffer} + * @expose + */ + this.buffer = capacity === 0 ? EMPTY_BUFFER : new ArrayBuffer(capacity); + + /** + * Uint8Array utilized to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`. + * @type {?Uint8Array} + * @expose + */ + this.view = capacity === 0 ? null : new Uint8Array(this.buffer); + + /** + * Absolute read/write offset. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.offset = 0; + + /** + * Marked offset. + * @type {number} + * @expose + * @see ByteBuffer#mark + * @see ByteBuffer#reset + */ + this.markedOffset = -1; + + /** + * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.limit = capacity; + + /** + * Whether to use little endian byte order, defaults to `false` for big endian. + * @type {boolean} + * @expose + */ + this.littleEndian = littleEndian; + + /** + * Whether to skip assertions of offsets and values, defaults to `false`. + * @type {boolean} + * @expose + */ + this.noAssert = noAssert; + }; + + /** + * ByteBuffer version. + * @type {string} + * @const + * @expose + */ + ByteBuffer.VERSION = "5.0.1"; + + /** + * Little endian constant that can be used instead of its boolean value. Evaluates to `true`. + * @type {boolean} + * @const + * @expose + */ + ByteBuffer.LITTLE_ENDIAN = true; + + /** + * Big endian constant that can be used instead of its boolean value. Evaluates to `false`. + * @type {boolean} + * @const + * @expose + */ + ByteBuffer.BIG_ENDIAN = false; + + /** + * Default initial capacity of `16`. + * @type {number} + * @expose + */ + ByteBuffer.DEFAULT_CAPACITY = 16; + + /** + * Default endianess of `false` for big endian. + * @type {boolean} + * @expose + */ + ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN; + + /** + * Default no assertions flag of `false`. + * @type {boolean} + * @expose + */ + ByteBuffer.DEFAULT_NOASSERT = false; + + /** + * A `Long` class for representing a 64-bit two's-complement integer value. May be `null` if Long.js has not been loaded + * and int64 support is not available. + * @type {?Long} + * @const + * @see https://github.com/dcodeIO/long.js + * @expose + */ + ByteBuffer.Long = Long || null; + + /** + * @alias ByteBuffer.prototype + * @inner + */ + var ByteBufferPrototype = ByteBuffer.prototype; + + /** + * An indicator used to reliably determine if an object is a ByteBuffer or not. + * @type {boolean} + * @const + * @expose + * @private + */ + ByteBufferPrototype.__isByteBuffer__; + + Object.defineProperty(ByteBufferPrototype, "__isByteBuffer__", { + value: true, + enumerable: false, + configurable: false + }); + + // helpers + + /** + * @type {!ArrayBuffer} + * @inner + */ + var EMPTY_BUFFER = new ArrayBuffer(0); + + /** + * String.fromCharCode reference for compile-time renaming. + * @type {function(...number):string} + * @inner + */ + var stringFromCharCode = String.fromCharCode; + + /** + * Creates a source function for a string. + * @param {string} s String to read from + * @returns {function():number|null} Source function returning the next char code respectively `null` if there are + * no more characters left. + * @throws {TypeError} If the argument is invalid + * @inner + */ + function stringSource(s) { + var i=0; return function() { + return i < s.length ? s.charCodeAt(i++) : null; + }; + } + + /** + * Creates a destination function for a string. + * @returns {function(number=):undefined|string} Destination function successively called with the next char code. + * Returns the final string when called without arguments. + * @inner + */ + function stringDestination() { + var cs = [], ps = []; return function() { + if (arguments.length === 0) + return ps.join('')+stringFromCharCode.apply(String, cs); + if (cs.length + arguments.length > 1024) + ps.push(stringFromCharCode.apply(String, cs)), + cs.length = 0; + Array.prototype.push.apply(cs, arguments); + }; + } + + /** + * Gets the accessor type. + * @returns {Function} `Buffer` under node.js, `Uint8Array` respectively `DataView` in the browser (classes) + * @expose + */ + ByteBuffer.accessor = function() { + return Uint8Array; + }; + /** + * Allocates a new ByteBuffer backed by a buffer of the specified capacity. + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} + * @expose + */ + ByteBuffer.allocate = function(capacity, littleEndian, noAssert) { + return new ByteBuffer(capacity, littleEndian, noAssert); + }; + + /** + * Concatenates multiple ByteBuffers into one. + * @param {!Array.} buffers Buffers to concatenate + * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary", + * defaults to "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults + * to {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} Concatenated ByteBuffer + * @expose + */ + ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) { + if (typeof encoding === 'boolean' || typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + var capacity = 0; + for (var i=0, k=buffers.length, length; i 0) capacity += length; + } + if (capacity === 0) + return new ByteBuffer(0, littleEndian, noAssert); + var bb = new ByteBuffer(capacity, littleEndian, noAssert), + bi; + i=0; while (i} buffer Anything that can be wrapped + * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to + * "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer` + * @expose + */ + ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) { + if (typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + if (typeof buffer === 'string') { + if (typeof encoding === 'undefined') + encoding = "utf8"; + switch (encoding) { + case "base64": + return ByteBuffer.fromBase64(buffer, littleEndian); + case "hex": + return ByteBuffer.fromHex(buffer, littleEndian); + case "binary": + return ByteBuffer.fromBinary(buffer, littleEndian); + case "utf8": + return ByteBuffer.fromUTF8(buffer, littleEndian); + case "debug": + return ByteBuffer.fromDebug(buffer, littleEndian); + default: + throw Error("Unsupported encoding: "+encoding); + } + } + if (buffer === null || typeof buffer !== 'object') + throw TypeError("Illegal buffer"); + var bb; + if (ByteBuffer.isByteBuffer(buffer)) { + bb = ByteBufferPrototype.clone.call(buffer); + bb.markedOffset = -1; + return bb; + } + if (buffer instanceof Uint8Array) { // Extract ArrayBuffer from Uint8Array + bb = new ByteBuffer(0, littleEndian, noAssert); + if (buffer.length > 0) { // Avoid references to more than one EMPTY_BUFFER + bb.buffer = buffer.buffer; + bb.offset = buffer.byteOffset; + bb.limit = buffer.byteOffset + buffer.byteLength; + bb.view = new Uint8Array(buffer.buffer); + } + } else if (buffer instanceof ArrayBuffer) { // Reuse ArrayBuffer + bb = new ByteBuffer(0, littleEndian, noAssert); + if (buffer.byteLength > 0) { + bb.buffer = buffer; + bb.offset = 0; + bb.limit = buffer.byteLength; + bb.view = buffer.byteLength > 0 ? new Uint8Array(buffer) : null; + } + } else if (Object.prototype.toString.call(buffer) === "[object Array]") { // Create from octets + bb = new ByteBuffer(buffer.length, littleEndian, noAssert); + bb.limit = buffer.length; + for (var i=0; i} value Array of booleans to write + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ + ByteBufferPrototype.writeBitSet = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (!(value instanceof Array)) + throw TypeError("Illegal BitSet: Not an array"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + + var start = offset, + bits = value.length, + bytes = (bits >> 3), + bit = 0, + k; + + offset += this.writeVarint32(bits,offset); + + while(bytes--) { + k = (!!value[bit++] & 1) | + ((!!value[bit++] & 1) << 1) | + ((!!value[bit++] & 1) << 2) | + ((!!value[bit++] & 1) << 3) | + ((!!value[bit++] & 1) << 4) | + ((!!value[bit++] & 1) << 5) | + ((!!value[bit++] & 1) << 6) | + ((!!value[bit++] & 1) << 7); + this.writeByte(k,offset++); + } + + if(bit < bits) { + var m = 0; k = 0; + while(bit < bits) k = k | ((!!value[bit++] & 1) << (m++)); + this.writeByte(k,offset++); + } + + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + } + + /** + * Reads a BitSet as an array of booleans. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {Array + * @expose + */ + ByteBufferPrototype.readBitSet = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + + var ret = this.readVarint32(offset), + bits = ret.value, + bytes = (bits >> 3), + bit = 0, + value = [], + k; + + offset += ret.length; + + while(bytes--) { + k = this.readByte(offset++); + value[bit++] = !!(k & 0x01); + value[bit++] = !!(k & 0x02); + value[bit++] = !!(k & 0x04); + value[bit++] = !!(k & 0x08); + value[bit++] = !!(k & 0x10); + value[bit++] = !!(k & 0x20); + value[bit++] = !!(k & 0x40); + value[bit++] = !!(k & 0x80); + } + + if(bit < bits) { + var m = 0; + k = this.readByte(offset++); + while(bit < bits) value[bit++] = !!((k >> (m++)) & 1); + } + + if (relative) { + this.offset = offset; + } + return value; + } + /** + * Reads the specified number of bytes. + * @param {number} length Number of bytes to read + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ + ByteBufferPrototype.readBytes = function(length, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + length > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength); + } + var slice = this.slice(offset, offset + length); + if (relative) this.offset += length; + return slice; + }; + + + // types/ints/int8 + + /** + * Writes an 8bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt8 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 1; + var capacity0 = this.buffer.byteLength; + if (offset > capacity0) + this.resize((capacity0 *= 2) > offset ? capacity0 : offset); + offset -= 1; + this.view[offset] = value; + if (relative) this.offset += 1; + return this; + }; + + /** + * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8; + + /** + * Reads an 8bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt8 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var value = this.view[offset]; + if ((value & 0x80) === 0x80) value = -(0xFF - value + 1); // Cast to signed + if (relative) this.offset += 1; + return value; + }; + + /** + * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8; + + /** + * Writes an 8bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint8 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 1; + var capacity1 = this.buffer.byteLength; + if (offset > capacity1) + this.resize((capacity1 *= 2) > offset ? capacity1 : offset); + offset -= 1; + this.view[offset] = value; + if (relative) this.offset += 1; + return this; + }; + + /** + * Writes an 8bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt8 = ByteBufferPrototype.writeUint8; + + /** + * Reads an 8bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUint8 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var value = this.view[offset]; + if (relative) this.offset += 1; + return value; + }; + + /** + * Reads an 8bit unsigned integer. This is an alias of {@link ByteBuffer#readUint8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUInt8 = ByteBufferPrototype.readUint8; + + // types/ints/int16 + + /** + * Writes a 16bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeInt16 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 2; + var capacity2 = this.buffer.byteLength; + if (offset > capacity2) + this.resize((capacity2 *= 2) > offset ? capacity2 : offset); + offset -= 2; + if (this.littleEndian) { + this.view[offset+1] = (value & 0xFF00) >>> 8; + this.view[offset ] = value & 0x00FF; + } else { + this.view[offset] = (value & 0xFF00) >>> 8; + this.view[offset+1] = value & 0x00FF; + } + if (relative) this.offset += 2; + return this; + }; + + /** + * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16; + + /** + * Reads a 16bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readInt16 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 2 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength); + } + var value = 0; + if (this.littleEndian) { + value = this.view[offset ]; + value |= this.view[offset+1] << 8; + } else { + value = this.view[offset ] << 8; + value |= this.view[offset+1]; + } + if ((value & 0x8000) === 0x8000) value = -(0xFFFF - value + 1); // Cast to signed + if (relative) this.offset += 2; + return value; + }; + + /** + * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16; + + /** + * Writes a 16bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeUint16 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 2; + var capacity3 = this.buffer.byteLength; + if (offset > capacity3) + this.resize((capacity3 *= 2) > offset ? capacity3 : offset); + offset -= 2; + if (this.littleEndian) { + this.view[offset+1] = (value & 0xFF00) >>> 8; + this.view[offset ] = value & 0x00FF; + } else { + this.view[offset] = (value & 0xFF00) >>> 8; + this.view[offset+1] = value & 0x00FF; + } + if (relative) this.offset += 2; + return this; + }; + + /** + * Writes a 16bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeUInt16 = ByteBufferPrototype.writeUint16; + + /** + * Reads a 16bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readUint16 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 2 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength); + } + var value = 0; + if (this.littleEndian) { + value = this.view[offset ]; + value |= this.view[offset+1] << 8; + } else { + value = this.view[offset ] << 8; + value |= this.view[offset+1]; + } + if (relative) this.offset += 2; + return value; + }; + + /** + * Reads a 16bit unsigned integer. This is an alias of {@link ByteBuffer#readUint16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readUInt16 = ByteBufferPrototype.readUint16; + + // types/ints/int32 + + /** + * Writes a 32bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeInt32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity4 = this.buffer.byteLength; + if (offset > capacity4) + this.resize((capacity4 *= 2) > offset ? capacity4 : offset); + offset -= 4; + if (this.littleEndian) { + this.view[offset+3] = (value >>> 24) & 0xFF; + this.view[offset+2] = (value >>> 16) & 0xFF; + this.view[offset+1] = (value >>> 8) & 0xFF; + this.view[offset ] = value & 0xFF; + } else { + this.view[offset ] = (value >>> 24) & 0xFF; + this.view[offset+1] = (value >>> 16) & 0xFF; + this.view[offset+2] = (value >>> 8) & 0xFF; + this.view[offset+3] = value & 0xFF; + } + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32; + + /** + * Reads a 32bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = 0; + if (this.littleEndian) { + value = this.view[offset+2] << 16; + value |= this.view[offset+1] << 8; + value |= this.view[offset ]; + value += this.view[offset+3] << 24 >>> 0; + } else { + value = this.view[offset+1] << 16; + value |= this.view[offset+2] << 8; + value |= this.view[offset+3]; + value += this.view[offset ] << 24 >>> 0; + } + value |= 0; // Cast to signed + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32; + + /** + * Writes a 32bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeUint32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity5 = this.buffer.byteLength; + if (offset > capacity5) + this.resize((capacity5 *= 2) > offset ? capacity5 : offset); + offset -= 4; + if (this.littleEndian) { + this.view[offset+3] = (value >>> 24) & 0xFF; + this.view[offset+2] = (value >>> 16) & 0xFF; + this.view[offset+1] = (value >>> 8) & 0xFF; + this.view[offset ] = value & 0xFF; + } else { + this.view[offset ] = (value >>> 24) & 0xFF; + this.view[offset+1] = (value >>> 16) & 0xFF; + this.view[offset+2] = (value >>> 8) & 0xFF; + this.view[offset+3] = value & 0xFF; + } + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeUInt32 = ByteBufferPrototype.writeUint32; + + /** + * Reads a 32bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUint32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = 0; + if (this.littleEndian) { + value = this.view[offset+2] << 16; + value |= this.view[offset+1] << 8; + value |= this.view[offset ]; + value += this.view[offset+3] << 24 >>> 0; + } else { + value = this.view[offset+1] << 16; + value |= this.view[offset+2] << 8; + value |= this.view[offset+3]; + value += this.view[offset ] << 24 >>> 0; + } + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit unsigned integer. This is an alias of {@link ByteBuffer#readUint32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUInt32 = ByteBufferPrototype.readUint32; + + // types/ints/int64 + + if (Long) { + + /** + * Writes a 64bit signed integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + offset += 8; + var capacity6 = this.buffer.byteLength; + if (offset > capacity6) + this.resize((capacity6 *= 2) > offset ? capacity6 : offset); + offset -= 8; + var lo = value.low, + hi = value.high; + if (this.littleEndian) { + this.view[offset+3] = (lo >>> 24) & 0xFF; + this.view[offset+2] = (lo >>> 16) & 0xFF; + this.view[offset+1] = (lo >>> 8) & 0xFF; + this.view[offset ] = lo & 0xFF; + offset += 4; + this.view[offset+3] = (hi >>> 24) & 0xFF; + this.view[offset+2] = (hi >>> 16) & 0xFF; + this.view[offset+1] = (hi >>> 8) & 0xFF; + this.view[offset ] = hi & 0xFF; + } else { + this.view[offset ] = (hi >>> 24) & 0xFF; + this.view[offset+1] = (hi >>> 16) & 0xFF; + this.view[offset+2] = (hi >>> 8) & 0xFF; + this.view[offset+3] = hi & 0xFF; + offset += 4; + this.view[offset ] = (lo >>> 24) & 0xFF; + this.view[offset+1] = (lo >>> 16) & 0xFF; + this.view[offset+2] = (lo >>> 8) & 0xFF; + this.view[offset+3] = lo & 0xFF; + } + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64; + + /** + * Reads a 64bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readInt64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var lo = 0, + hi = 0; + if (this.littleEndian) { + lo = this.view[offset+2] << 16; + lo |= this.view[offset+1] << 8; + lo |= this.view[offset ]; + lo += this.view[offset+3] << 24 >>> 0; + offset += 4; + hi = this.view[offset+2] << 16; + hi |= this.view[offset+1] << 8; + hi |= this.view[offset ]; + hi += this.view[offset+3] << 24 >>> 0; + } else { + hi = this.view[offset+1] << 16; + hi |= this.view[offset+2] << 8; + hi |= this.view[offset+3]; + hi += this.view[offset ] << 24 >>> 0; + offset += 4; + lo = this.view[offset+1] << 16; + lo |= this.view[offset+2] << 8; + lo |= this.view[offset+3]; + lo += this.view[offset ] << 24 >>> 0; + } + var value = new Long(lo, hi, false); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64; + + /** + * Writes a 64bit unsigned integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + offset += 8; + var capacity7 = this.buffer.byteLength; + if (offset > capacity7) + this.resize((capacity7 *= 2) > offset ? capacity7 : offset); + offset -= 8; + var lo = value.low, + hi = value.high; + if (this.littleEndian) { + this.view[offset+3] = (lo >>> 24) & 0xFF; + this.view[offset+2] = (lo >>> 16) & 0xFF; + this.view[offset+1] = (lo >>> 8) & 0xFF; + this.view[offset ] = lo & 0xFF; + offset += 4; + this.view[offset+3] = (hi >>> 24) & 0xFF; + this.view[offset+2] = (hi >>> 16) & 0xFF; + this.view[offset+1] = (hi >>> 8) & 0xFF; + this.view[offset ] = hi & 0xFF; + } else { + this.view[offset ] = (hi >>> 24) & 0xFF; + this.view[offset+1] = (hi >>> 16) & 0xFF; + this.view[offset+2] = (hi >>> 8) & 0xFF; + this.view[offset+3] = hi & 0xFF; + offset += 4; + this.view[offset ] = (lo >>> 24) & 0xFF; + this.view[offset+1] = (lo >>> 16) & 0xFF; + this.view[offset+2] = (lo >>> 8) & 0xFF; + this.view[offset+3] = lo & 0xFF; + } + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint64}. + * @function + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt64 = ByteBufferPrototype.writeUint64; + + /** + * Reads a 64bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUint64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var lo = 0, + hi = 0; + if (this.littleEndian) { + lo = this.view[offset+2] << 16; + lo |= this.view[offset+1] << 8; + lo |= this.view[offset ]; + lo += this.view[offset+3] << 24 >>> 0; + offset += 4; + hi = this.view[offset+2] << 16; + hi |= this.view[offset+1] << 8; + hi |= this.view[offset ]; + hi += this.view[offset+3] << 24 >>> 0; + } else { + hi = this.view[offset+1] << 16; + hi |= this.view[offset+2] << 8; + hi |= this.view[offset+3]; + hi += this.view[offset ] << 24 >>> 0; + offset += 4; + lo = this.view[offset+1] << 16; + lo |= this.view[offset+2] << 8; + lo |= this.view[offset+3]; + lo += this.view[offset ] << 24 >>> 0; + } + var value = new Long(lo, hi, true); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit unsigned integer. This is an alias of {@link ByteBuffer#readUint64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUInt64 = ByteBufferPrototype.readUint64; + + } // Long + + + // types/floats/float32 + + /* + ieee754 - https://github.com/feross/ieee754 + + The MIT License (MIT) + + Copyright (c) Feross Aboukhadijeh + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + /** + * Reads an IEEE754 float from a byte array. + * @param {!Array} buffer + * @param {number} offset + * @param {boolean} isLE + * @param {number} mLen + * @param {number} nBytes + * @returns {number} + * @inner + */ + function ieee754_read(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); + } + + /** + * Writes an IEEE754 float to a byte array. + * @param {!Array} buffer + * @param {number} value + * @param {number} offset + * @param {boolean} isLE + * @param {number} mLen + * @param {number} nBytes + * @inner + */ + function ieee754_write(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; + } + + /** + * Writes a 32bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity8 = this.buffer.byteLength; + if (offset > capacity8) + this.resize((capacity8 *= 2) > offset ? capacity8 : offset); + offset -= 4; + ieee754_write(this.view, value, offset, this.littleEndian, 23, 4); + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32; + + /** + * Reads a 32bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = ieee754_read(this.view, offset, this.littleEndian, 23, 4); + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32; + + // types/floats/float64 + + /** + * Writes a 64bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 8; + var capacity9 = this.buffer.byteLength; + if (offset > capacity9) + this.resize((capacity9 *= 2) > offset ? capacity9 : offset); + offset -= 8; + ieee754_write(this.view, value, offset, this.littleEndian, 52, 8); + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64; + + /** + * Reads a 64bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var value = ieee754_read(this.view, offset, this.littleEndian, 52, 8); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64; + + + // types/varints/varint32 + + /** + * Maximum number of bytes required to store a 32bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT32_BYTES = 5; + + /** + * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer. + * @param {number} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES} + * @expose + */ + ByteBuffer.calculateVarint32 = function(value) { + // ref: src/google/protobuf/io/coded_stream.cc + value = value >>> 0; + if (value < 1 << 7 ) return 1; + else if (value < 1 << 14) return 2; + else if (value < 1 << 21) return 3; + else if (value < 1 << 28) return 4; + else return 5; + }; + + /** + * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding. + * @param {number} n Signed 32bit integer + * @returns {number} Unsigned zigzag encoded 32bit integer + * @expose + */ + ByteBuffer.zigZagEncode32 = function(n) { + return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h + }; + + /** + * Decodes a zigzag encoded signed 32bit integer. + * @param {number} n Unsigned zigzag encoded 32bit integer + * @returns {number} Signed 32bit integer + * @expose + */ + ByteBuffer.zigZagDecode32 = function(n) { + return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h + }; + + /** + * Writes a 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeVarint32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var size = ByteBuffer.calculateVarint32(value), + b; + offset += size; + var capacity10 = this.buffer.byteLength; + if (offset > capacity10) + this.resize((capacity10 *= 2) > offset ? capacity10 : offset); + offset -= size; + value >>>= 0; + while (value >= 0x80) { + b = (value & 0x7f) | 0x80; + this.view[offset++] = b; + value >>>= 7; + } + this.view[offset++] = value; + if (relative) { + this.offset = offset; + return this; + } + return size; + }; + + /** + * Writes a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) { + return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset); + }; + + /** + * Reads a 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available + * to fully decode the varint. + * @expose + */ + ByteBufferPrototype.readVarint32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var c = 0, + value = 0 >>> 0, + b; + do { + if (!this.noAssert && offset > this.limit) { + var err = Error("Truncated"); + err['truncated'] = true; + throw err; + } + b = this.view[offset++]; + if (c < 5) + value |= (b & 0x7f) << (7*c); + ++c; + } while ((b & 0x80) !== 0); + value |= 0; + if (relative) { + this.offset = offset; + return value; + } + return { + "value": value, + "length": c + }; + }; + + /** + * Reads a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint32ZigZag = function(offset) { + var val = this.readVarint32(offset); + if (typeof val === 'object') + val["value"] = ByteBuffer.zigZagDecode32(val["value"]); + else + val = ByteBuffer.zigZagDecode32(val); + return val; + }; + + // types/varints/varint64 + + if (Long) { + + /** + * Maximum number of bytes required to store a 64bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT64_BYTES = 10; + + /** + * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer. + * @param {number|!Long} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES} + * @expose + */ + ByteBuffer.calculateVarint64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + // ref: src/google/protobuf/io/coded_stream.cc + var part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + if (part2 == 0) { + if (part1 == 0) { + if (part0 < 1 << 14) + return part0 < 1 << 7 ? 1 : 2; + else + return part0 < 1 << 21 ? 3 : 4; + } else { + if (part1 < 1 << 14) + return part1 < 1 << 7 ? 5 : 6; + else + return part1 < 1 << 21 ? 7 : 8; + } + } else + return part2 < 1 << 7 ? 9 : 10; + }; + + /** + * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding. + * @param {number|!Long} value Signed long + * @returns {!Long} Unsigned zigzag encoded long + * @expose + */ + ByteBuffer.zigZagEncode64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned(); + }; + + /** + * Decodes a zigzag encoded signed 64bit integer. + * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number + * @returns {!Long} Signed long + * @expose + */ + ByteBuffer.zigZagDecode64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned(); + }; + + /** + * Writes a 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + var size = ByteBuffer.calculateVarint64(value), + part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + offset += size; + var capacity11 = this.buffer.byteLength; + if (offset > capacity11) + this.resize((capacity11 *= 2) > offset ? capacity11 : offset); + offset -= size; + switch (size) { + case 10: this.view[offset+9] = (part2 >>> 7) & 0x01; + case 9 : this.view[offset+8] = size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F; + case 8 : this.view[offset+7] = size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F; + case 7 : this.view[offset+6] = size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F; + case 6 : this.view[offset+5] = size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F; + case 5 : this.view[offset+4] = size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F; + case 4 : this.view[offset+3] = size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F; + case 3 : this.view[offset+2] = size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F; + case 2 : this.view[offset+1] = size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F; + case 1 : this.view[offset ] = size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F; + } + if (relative) { + this.offset += size; + return this; + } else { + return size; + } + }; + + /** + * Writes a zig-zag encoded 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) { + return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); + }; + + /** + * Reads a 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + // ref: src/google/protobuf/io/coded_stream.cc + var start = offset, + part0 = 0, + part1 = 0, + part2 = 0, + b = 0; + b = this.view[offset++]; part0 = (b & 0x7F) ; if ( b & 0x80 ) { + b = this.view[offset++]; part0 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part0 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part0 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part1 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part1 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part1 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part1 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part2 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part2 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + throw Error("Buffer overrun"); }}}}}}}}}} + var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false); + if (relative) { + this.offset = offset; + return value; + } else { + return { + 'value': value, + 'length': offset-start + }; + } + }; + + /** + * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64ZigZag = function(offset) { + var val = this.readVarint64(offset); + if (val && val['value'] instanceof Long) + val["value"] = ByteBuffer.zigZagDecode64(val["value"]); + else + val = ByteBuffer.zigZagDecode64(val); + return val; + }; + + } // Long + + + // types/strings/cstring + + /** + * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL + * characters itself. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * contained in `str` + 1 if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeCString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + var i, + k = str.length; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + for (i=0; i>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + // UTF8 strings do not contain zero bytes in between except for the zero character, so: + k = utfx.calculateUTF16asUTF8(stringSource(str))[1]; + offset += k+1; + var capacity12 = this.buffer.byteLength; + if (offset > capacity12) + this.resize((capacity12 *= 2) > offset ? capacity12 : offset); + offset -= k+1; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view[offset++] = b; + }.bind(this)); + this.view[offset++] = 0; + if (relative) { + this.offset = offset; + return this; + } + return k; + }; + + /** + * Reads a NULL-terminated UTF8 encoded string. For this to work the string read must not contain any NULL characters + * itself. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readCString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var start = offset, + temp; + // UTF8 strings do not contain zero bytes in between except for the zero character itself, so: + var sd, b = -1; + utfx.decodeUTF8toUTF16(function() { + if (b === 0) return null; + if (offset >= this.limit) + throw RangeError("Illegal range: Truncated data, "+offset+" < "+this.limit); + b = this.view[offset++]; + return b === 0 ? null : b; + }.bind(this), sd = stringDestination(), true); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + }; + + // types/strings/istring + + /** + * Writes a length as uint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ + ByteBufferPrototype.writeIString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var start = offset, + k; + k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1]; + offset += 4+k; + var capacity13 = this.buffer.byteLength; + if (offset > capacity13) + this.resize((capacity13 *= 2) > offset ? capacity13 : offset); + offset -= 4+k; + if (this.littleEndian) { + this.view[offset+3] = (k >>> 24) & 0xFF; + this.view[offset+2] = (k >>> 16) & 0xFF; + this.view[offset+1] = (k >>> 8) & 0xFF; + this.view[offset ] = k & 0xFF; + } else { + this.view[offset ] = (k >>> 24) & 0xFF; + this.view[offset+1] = (k >>> 16) & 0xFF; + this.view[offset+2] = (k >>> 8) & 0xFF; + this.view[offset+3] = k & 0xFF; + } + offset += 4; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view[offset++] = b; + }.bind(this)); + if (offset !== start + 4 + k) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+4+k)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Reads a length as uint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ + ByteBufferPrototype.readIString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var start = offset; + var len = this.readUint32(offset); + var str = this.readUTF8String(len, ByteBuffer.METRICS_BYTES, offset += 4); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } + }; + + // types/strings/utf8string + + /** + * Metrics representing number of UTF8 characters. Evaluates to `c`. + * @type {string} + * @const + * @expose + */ + ByteBuffer.METRICS_CHARS = 'c'; + + /** + * Metrics representing number of bytes. Evaluates to `b`. + * @type {string} + * @const + * @expose + */ + ByteBuffer.METRICS_BYTES = 'b'; + + /** + * Writes an UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeUTF8String = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var k; + var start = offset; + k = utfx.calculateUTF16asUTF8(stringSource(str))[1]; + offset += k; + var capacity14 = this.buffer.byteLength; + if (offset > capacity14) + this.resize((capacity14 *= 2) > offset ? capacity14 : offset); + offset -= k; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view[offset++] = b; + }.bind(this)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}. + * @function + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String; + + /** + * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's + * `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 characters + * @expose + */ + ByteBuffer.calculateUTF8Chars = function(str) { + return utfx.calculateUTF16asUTF8(stringSource(str))[0]; + }; + + /** + * Calculates the number of UTF8 bytes of a string. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ + ByteBuffer.calculateUTF8Bytes = function(str) { + return utfx.calculateUTF16asUTF8(stringSource(str))[1]; + }; + + /** + * Calculates the number of UTF8 bytes of a string. This is an alias of {@link ByteBuffer.calculateUTF8Bytes}. + * @function + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ + ByteBuffer.calculateString = ByteBuffer.calculateUTF8Bytes; + + /** + * Reads an UTF8 encoded string. + * @param {number} length Number of characters or bytes to read. + * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readUTF8String = function(length, metrics, offset) { + if (typeof metrics === 'number') { + offset = metrics; + metrics = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS; + if (!this.noAssert) { + if (typeof length !== 'number' || length % 1 !== 0) + throw TypeError("Illegal length: "+length+" (not an integer)"); + length |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var i = 0, + start = offset, + sd; + if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser + sd = stringDestination(); + utfx.decodeUTF8(function() { + return i < length && offset < this.limit ? this.view[offset++] : null; + }.bind(this), function(cp) { + ++i; utfx.UTF8toUTF16(cp, sd); + }); + if (i !== length) + throw RangeError("Illegal range: Truncated data, "+i+" == "+length); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + } else if (metrics === ByteBuffer.METRICS_BYTES) { + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + length > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength); + } + var k = offset + length; + utfx.decodeUTF8toUTF16(function() { + return offset < k ? this.view[offset++] : null; + }.bind(this), sd = stringDestination(), this.noAssert); + if (offset !== k) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+k); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + 'string': sd(), + 'length': offset - start + }; + } + } else + throw TypeError("Unsupported metrics: "+metrics); + }; + + /** + * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}. + * @function + * @param {number} length Number of characters or bytes to read + * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String; + + // types/strings/vstring + + /** + * Writes a length as varint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ + ByteBufferPrototype.writeVString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var start = offset, + k, l; + k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1]; + l = ByteBuffer.calculateVarint32(k); + offset += l+k; + var capacity15 = this.buffer.byteLength; + if (offset > capacity15) + this.resize((capacity15 *= 2) > offset ? capacity15 : offset); + offset -= l+k; + offset += this.writeVarint32(k, offset); + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view[offset++] = b; + }.bind(this)); + if (offset !== start+k+l) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+k+l)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Reads a length as varint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ + ByteBufferPrototype.readVString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var start = offset; + var len = this.readVarint32(offset); + var str = this.readUTF8String(len['value'], ByteBuffer.METRICS_BYTES, offset += len['length']); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } + }; + + + /** + * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended + * data's length. + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its offsets + * will be modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|` + * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|` + */ + ByteBufferPrototype.append = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var length = source.limit - source.offset; + if (length <= 0) return this; // Nothing to append + offset += length; + var capacity16 = this.buffer.byteLength; + if (offset > capacity16) + this.resize((capacity16 *= 2) > offset ? capacity16 : offset); + offset -= length; + this.view.set(source.view.subarray(source.offset, source.limit), offset); + source.offset += length; + if (relative) this.offset += length; + return this; + }; + + /** + * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents at and after the + specified offset up to the length of this ByteBuffer's data. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#append + */ + ByteBufferPrototype.appendTo = function(target, offset) { + target.append(this, offset); + return this; + }; + + /** + * Writes a payload of bytes. This is an alias of {@link ByteBuffer#append}. + * @function + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to write. If `source` is a ByteBuffer, its offsets + * will be modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeBytes = ByteBufferPrototype.append; + /** + * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to + * disable them if your code already makes sure that everything is valid. + * @param {boolean} assert `true` to enable assertions, otherwise `false` + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.assert = function(assert) { + this.noAssert = !assert; + return this; + }; + + /** + * Gets the capacity of this ByteBuffer's backing buffer. + * @returns {number} Capacity of the backing buffer + * @expose + */ + ByteBufferPrototype.capacity = function() { + return this.buffer.byteLength; + }; + /** + * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the + * backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.clear = function() { + this.offset = 0; + this.limit = this.buffer.byteLength; + this.markedOffset = -1; + return this; + }; + + /** + * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset}, + * {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}. + * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false` + * @returns {!ByteBuffer} Cloned instance + * @expose + */ + ByteBufferPrototype.clone = function(copy) { + var bb = new ByteBuffer(0, this.littleEndian, this.noAssert); + if (copy) { + bb.buffer = new ArrayBuffer(this.buffer.byteLength); + bb.view = new Uint8Array(bb.buffer); + } else { + bb.buffer = this.buffer; + bb.view = this.view; + } + bb.offset = this.offset; + bb.markedOffset = this.markedOffset; + bb.limit = this.limit; + return bb; + }; + + /** + * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes + * between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and + * adapt {@link ByteBuffer#markedOffset} to the same relative position if set. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.compact = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === 0 && end === this.buffer.byteLength) + return this; // Already compacted + var len = end - begin; + if (len === 0) { + this.buffer = EMPTY_BUFFER; + this.view = null; + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = 0; + return this; + } + var buffer = new ArrayBuffer(len); + var view = new Uint8Array(buffer); + view.set(this.view.subarray(begin, end)); + this.buffer = buffer; + this.view = view; + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = len; + return this; + }; + + /** + * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Copy + * @expose + */ + ByteBufferPrototype.copy = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === end) + return new ByteBuffer(0, this.littleEndian, this.noAssert); + var capacity = end - begin, + bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert); + bb.offset = 0; + bb.limit = capacity; + if (bb.markedOffset >= 0) bb.markedOffset -= begin; + this.copyTo(bb, 0, begin, end); + return bb; + }; + + /** + * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset} + * by the number of bytes copied if omitted. + * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the + * number of bytes copied if omitted. + * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) { + var relative, + targetRelative; + if (!this.noAssert) { + if (!ByteBuffer.isByteBuffer(target)) + throw TypeError("Illegal target: Not a ByteBuffer"); + } + targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0; + sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0; + sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0; + + if (targetOffset < 0 || targetOffset > target.buffer.byteLength) + throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+target.buffer.byteLength); + if (sourceOffset < 0 || sourceLimit > this.buffer.byteLength) + throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+this.buffer.byteLength); + + var len = sourceLimit - sourceOffset; + if (len === 0) + return target; // Nothing to copy + + target.ensureCapacity(targetOffset + len); + + target.view.set(this.view.subarray(sourceOffset, sourceLimit), targetOffset); + + if (relative) this.offset += len; + if (targetRelative) target.offset += len; + + return this; + }; + + /** + * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the + * current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity, + * the required capacity will be used instead. + * @param {number} capacity Required capacity + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.ensureCapacity = function(capacity) { + var current = this.buffer.byteLength; + if (current < capacity) + return this.resize((current *= 2) > capacity ? current : capacity); + return this; + }; + + /** + * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {number|string} value Byte value to fill with. If given as a string, the first character is used. + * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} this + * @expose + * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes + */ + ByteBufferPrototype.fill = function(value, begin, end) { + var relative = typeof begin === 'undefined'; + if (relative) begin = this.offset; + if (typeof value === 'string' && value.length > 0) + value = value.charCodeAt(0); + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin >= end) + return this; // Nothing to fill + while (begin < end) this.view[begin++] = value; + if (relative) this.offset = begin; + return this; + }; + + /** + * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and + * `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.flip = function() { + this.limit = this.offset; + this.offset = 0; + return this; + }; + /** + * Marks an offset on this ByteBuffer to be used later. + * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}. + * @returns {!ByteBuffer} this + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @see ByteBuffer#reset + * @expose + */ + ByteBufferPrototype.mark = function(offset) { + offset = typeof offset === 'undefined' ? this.offset : offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + this.markedOffset = offset; + return this; + }; + /** + * Sets the byte order. + * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.order = function(littleEndian) { + if (!this.noAssert) { + if (typeof littleEndian !== 'boolean') + throw TypeError("Illegal littleEndian: Not a boolean"); + } + this.littleEndian = !!littleEndian; + return this; + }; + + /** + * Switches (to) little endian byte order. + * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.LE = function(littleEndian) { + this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true; + return this; + }; + + /** + * Switches (to) big endian byte order. + * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.BE = function(bigEndian) { + this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false; + return this; + }; + /** + * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer|string|!ArrayBuffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be + * modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|` + * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|` + */ + ByteBufferPrototype.prepend = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var len = source.limit - source.offset; + if (len <= 0) return this; // Nothing to prepend + var diff = len - offset; + if (diff > 0) { // Not enough space before offset, so resize + move + var buffer = new ArrayBuffer(this.buffer.byteLength + diff); + var view = new Uint8Array(buffer); + view.set(this.view.subarray(offset, this.buffer.byteLength), len); + this.buffer = buffer; + this.view = view; + this.offset += diff; + if (this.markedOffset >= 0) this.markedOffset += diff; + this.limit += diff; + offset += diff; + } else { + var arrayView = new Uint8Array(this.buffer); + } + this.view.set(source.view.subarray(source.offset, source.limit), offset - len); + + source.offset = source.limit; + if (relative) + this.offset -= len; + return this; + }; + + /** + * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#prepend + */ + ByteBufferPrototype.prependTo = function(target, offset) { + target.prepend(this, offset); + return this; + }; + /** + * Prints debug information about this ByteBuffer's contents. + * @param {function(string)=} out Output function to call, defaults to console.log + * @expose + */ + ByteBufferPrototype.printDebug = function(out) { + if (typeof out !== 'function') out = console.log.bind(console); + out( + this.toString()+"\n"+ + "-------------------------------------------------------------------\n"+ + this.toDebug(/* columns */ true) + ); + }; + + /** + * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}, so this returns `limit - offset`. + * @returns {number} Remaining readable bytes. May be negative if `offset > limit`. + * @expose + */ + ByteBufferPrototype.remaining = function() { + return this.limit - this.offset; + }; + /** + * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark} + * before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been + * marked, sets `offset = 0`. + * @returns {!ByteBuffer} this + * @see ByteBuffer#mark + * @expose + */ + ByteBufferPrototype.reset = function() { + if (this.markedOffset >= 0) { + this.offset = this.markedOffset; + this.markedOffset = -1; + } else { + this.offset = 0; + } + return this; + }; + /** + * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that + * large or larger. + * @param {number} capacity Capacity required + * @returns {!ByteBuffer} this + * @throws {TypeError} If `capacity` is not a number + * @throws {RangeError} If `capacity < 0` + * @expose + */ + ByteBufferPrototype.resize = function(capacity) { + if (!this.noAssert) { + if (typeof capacity !== 'number' || capacity % 1 !== 0) + throw TypeError("Illegal capacity: "+capacity+" (not an integer)"); + capacity |= 0; + if (capacity < 0) + throw RangeError("Illegal capacity: 0 <= "+capacity); + } + if (this.buffer.byteLength < capacity) { + var buffer = new ArrayBuffer(capacity); + var view = new Uint8Array(buffer); + view.set(this.view); + this.buffer = buffer; + this.view = view; + } + return this; + }; + /** + * Reverses this ByteBuffer's contents. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.reverse = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === end) + return this; // Nothing to reverse + Array.prototype.reverse.call(this.view.subarray(begin, end)); + return this; + }; + /** + * Skips the next `length` bytes. This will just advance + * @param {number} length Number of bytes to skip. May also be negative to move the offset back. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.skip = function(length) { + if (!this.noAssert) { + if (typeof length !== 'number' || length % 1 !== 0) + throw TypeError("Illegal length: "+length+" (not an integer)"); + length |= 0; + } + var offset = this.offset + length; + if (!this.noAssert) { + if (offset < 0 || offset > this.buffer.byteLength) + throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+this.buffer.byteLength); + } + this.offset = offset; + return this; + }; + + /** + * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer} + * @expose + */ + ByteBufferPrototype.slice = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var bb = this.clone(); + bb.offset = begin; + bb.limit = end; + return bb; + }; + /** + * Returns a copy of the backing buffer that contains this ByteBuffer's contents. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory if + * possible. Defaults to `false` + * @returns {!ArrayBuffer} Contents as an ArrayBuffer + * @expose + */ + ByteBufferPrototype.toBuffer = function(forceCopy) { + var offset = this.offset, + limit = this.limit; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: Not an integer"); + offset >>>= 0; + if (typeof limit !== 'number' || limit % 1 !== 0) + throw TypeError("Illegal limit: Not an integer"); + limit >>>= 0; + if (offset < 0 || offset > limit || limit > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.byteLength); + } + // NOTE: It's not possible to have another ArrayBuffer reference the same memory as the backing buffer. This is + // possible with Uint8Array#subarray only, but we have to return an ArrayBuffer by contract. So: + if (!forceCopy && offset === 0 && limit === this.buffer.byteLength) + return this.buffer; + if (offset === limit) + return EMPTY_BUFFER; + var buffer = new ArrayBuffer(limit - offset); + new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(offset, limit), 0); + return buffer; + }; + + /** + * Returns a raw buffer compacted to contain this ByteBuffer's contents. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. This is an alias of {@link ByteBuffer#toBuffer}. + * @function + * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory. + * Defaults to `false` + * @returns {!ArrayBuffer} Contents as an ArrayBuffer + * @expose + */ + ByteBufferPrototype.toArrayBuffer = ByteBufferPrototype.toBuffer; + + /** + * Converts the ByteBuffer's contents to a string. + * @param {string=} encoding Output encoding. Returns an informative string representation if omitted but also allows + * direct conversion to "utf8", "hex", "base64" and "binary" encoding. "debug" returns a hex representation with + * highlighted offsets. + * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {string} String representation + * @throws {Error} If `encoding` is invalid + * @expose + */ + ByteBufferPrototype.toString = function(encoding, begin, end) { + if (typeof encoding === 'undefined') + return "ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")"; + if (typeof encoding === 'number') + encoding = "utf8", + begin = encoding, + end = begin; + switch (encoding) { + case "utf8": + return this.toUTF8(begin, end); + case "base64": + return this.toBase64(begin, end); + case "hex": + return this.toHex(begin, end); + case "binary": + return this.toBinary(begin, end); + case "debug": + return this.toDebug(); + case "columns": + return this.toColumns(); + default: + throw Error("Unsupported encoding: "+encoding); + } + }; + + // lxiv-embeddable + + /** + * lxiv-embeddable (c) 2014 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/lxiv for details + */ + var lxiv = function() { + "use strict"; + + /** + * lxiv namespace. + * @type {!Object.} + * @exports lxiv + */ + var lxiv = {}; + + /** + * Character codes for output. + * @type {!Array.} + * @inner + */ + var aout = [ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47 + ]; + + /** + * Character codes for input. + * @type {!Array.} + * @inner + */ + var ain = []; + for (var i=0, k=aout.length; i>2)&0x3f]); + t = (b&0x3)<<4; + if ((b = src()) !== null) { + t |= (b>>4)&0xf; + dst(aout[(t|((b>>4)&0xf))&0x3f]); + t = (b&0xf)<<2; + if ((b = src()) !== null) + dst(aout[(t|((b>>6)&0x3))&0x3f]), + dst(aout[b&0x3f]); + else + dst(aout[t&0x3f]), + dst(61); + } else + dst(aout[t&0x3f]), + dst(61), + dst(61); + } + }; + + /** + * Decodes base64 char codes to bytes. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. + * @throws {Error} If a character code is invalid + */ + lxiv.decode = function(src, dst) { + var c, t1, t2; + function fail(c) { + throw Error("Illegal character code: "+c); + } + while ((c = src()) !== null) { + t1 = ain[c]; + if (typeof t1 === 'undefined') fail(c); + if ((c = src()) !== null) { + t2 = ain[c]; + if (typeof t2 === 'undefined') fail(c); + dst((t1<<2)>>>0|(t2&0x30)>>4); + if ((c = src()) !== null) { + t1 = ain[c]; + if (typeof t1 === 'undefined') + if (c === 61) break; else fail(c); + dst(((t2&0xf)<<4)>>>0|(t1&0x3c)>>2); + if ((c = src()) !== null) { + t2 = ain[c]; + if (typeof t2 === 'undefined') + if (c === 61) break; else fail(c); + dst(((t1&0x3)<<6)>>>0|t2); + } + } + } + } + }; + + /** + * Tests if a string is valid base64. + * @param {string} str String to test + * @returns {boolean} `true` if valid, otherwise `false` + */ + lxiv.test = function(str) { + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(str); + }; + + return lxiv; + }(); + + // encodings/base64 + + /** + * Encodes this ByteBuffer's contents to a base64 encoded string. + * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}. + * @returns {string} Base64 encoded string + * @throws {RangeError} If `begin` or `end` is out of bounds + * @expose + */ + ByteBufferPrototype.toBase64 = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin = begin | 0; end = end | 0; + if (begin < 0 || end > this.capacity || begin > end) + throw RangeError("begin, end"); + var sd; lxiv.encode(function() { + return begin < end ? this.view[begin++] : null; + }.bind(this), sd = stringDestination()); + return sd(); + }; + + /** + * Decodes a base64 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromBase64 = function(str, littleEndian) { + if (typeof str !== 'string') + throw TypeError("str"); + var bb = new ByteBuffer(str.length/4*3, littleEndian), + i = 0; + lxiv.decode(stringSource(str), function(b) { + bb.view[i++] = b; + }); + bb.limit = i; + return bb; + }; + + /** + * Encodes a binary string to base64 like `window.btoa` does. + * @param {string} str Binary string + * @returns {string} Base64 encoded string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa + * @expose + */ + ByteBuffer.btoa = function(str) { + return ByteBuffer.fromBinary(str).toBase64(); + }; + + /** + * Decodes a base64 encoded string to binary like `window.atob` does. + * @param {string} b64 Base64 encoded string + * @returns {string} Binary string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob + * @expose + */ + ByteBuffer.atob = function(b64) { + return ByteBuffer.fromBase64(b64).toBinary(); + }; + + // encodings/binary + + /** + * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes. + * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}. + * @returns {string} Binary encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ + ByteBufferPrototype.toBinary = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin |= 0; end |= 0; + if (begin < 0 || end > this.capacity() || begin > end) + throw RangeError("begin, end"); + if (begin === end) + return ""; + var chars = [], + parts = []; + while (begin < end) { + chars.push(this.view[begin++]); + if (chars.length >= 1024) + parts.push(String.fromCharCode.apply(String, chars)), + chars = []; + } + return parts.join('') + String.fromCharCode.apply(String, chars); + }; + + /** + * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromBinary = function(str, littleEndian) { + if (typeof str !== 'string') + throw TypeError("str"); + var i = 0, + k = str.length, + charCode, + bb = new ByteBuffer(k, littleEndian); + while (i 0xff) + throw RangeError("illegal char code: "+charCode); + bb.view[i++] = charCode; + } + bb.limit = k; + return bb; + }; + + // encodings/debug + + /** + * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are: + * * `<` : offset, + * * `'` : markedOffset, + * * `>` : limit, + * * `|` : offset and limit, + * * `[` : offset and markedOffset, + * * `]` : markedOffset and limit, + * * `!` : offset, markedOffset and limit + * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false` + * @returns {string|!Array.} Debug string or array of lines if `asArray = true` + * @expose + * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3` + * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4` + * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1` + * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1` + */ + ByteBufferPrototype.toDebug = function(columns) { + var i = -1, + k = this.buffer.byteLength, + b, + hex = "", + asc = "", + out = ""; + while (i 32 && b < 127 ? String.fromCharCode(b) : '.'; + } + ++i; + if (columns) { + if (i > 0 && i % 16 === 0 && i !== k) { + while (hex.length < 3*16+3) hex += " "; + out += hex+asc+"\n"; + hex = asc = ""; + } + } + if (i === this.offset && i === this.limit) + hex += i === this.markedOffset ? "!" : "|"; + else if (i === this.offset) + hex += i === this.markedOffset ? "[" : "<"; + else if (i === this.limit) + hex += i === this.markedOffset ? "]" : ">"; + else + hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : ""); + } + if (columns && hex !== " ") { + while (hex.length < 3*16+3) + hex += " "; + out += hex + asc + "\n"; + } + return columns ? out : hex; + }; + + /** + * Decodes a hex encoded string with marked offsets to a ByteBuffer. + * @param {string} str Debug string to decode (not be generated with `columns = true`) + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + * @see ByteBuffer#toDebug + */ + ByteBuffer.fromDebug = function(str, littleEndian, noAssert) { + var k = str.length, + bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert); + var i = 0, j = 0, ch, b, + rs = false, // Require symbol next + ho = false, hm = false, hl = false, // Already has offset (ho), markedOffset (hm), limit (hl)? + fail = false; + while (i': + if (!noAssert) { + if (hl) { + fail = true; + break; + } + hl = true; + } + bb.limit = j; + rs = false; + break; + case "'": + if (!noAssert) { + if (hm) { + fail = true; + break; + } + hm = true; + } + bb.markedOffset = j; + rs = false; + break; + case ' ': + rs = false; + break; + default: + if (!noAssert) { + if (rs) { + fail = true; + break; + } + } + b = parseInt(ch+str.charAt(i++), 16); + if (!noAssert) { + if (isNaN(b) || b < 0 || b > 255) + throw TypeError("Illegal str: Not a debug encoded string"); + } + bb.view[j++] = b; + rs = true; + } + if (fail) + throw TypeError("Illegal str: Invalid symbol at "+i); + } + if (!noAssert) { + if (!ho || !hl) + throw TypeError("Illegal str: Missing offset or limit"); + if (j>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var out = new Array(end - begin), + b; + while (begin < end) { + b = this.view[begin++]; + if (b < 0x10) + out.push("0", b.toString(16)); + else out.push(b.toString(16)); + } + return out.join(''); + }; + + /** + * Decodes a hex encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromHex = function(str, littleEndian, noAssert) { + if (!noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (str.length % 2 !== 0) + throw TypeError("Illegal str: Length not a multiple of 2"); + } + var k = str.length, + bb = new ByteBuffer((k / 2) | 0, littleEndian), + b; + for (var i=0, j=0; i 255) + throw TypeError("Illegal str: Contains non-hex characters"); + bb.view[j++] = b; + } + bb.limit = j; + return bb; + }; + + // utfx-embeddable + + /** + * utfx-embeddable (c) 2014 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/utfx for details + */ + var utfx = function() { + "use strict"; + + /** + * utfx namespace. + * @inner + * @type {!Object.} + */ + var utfx = {}; + + /** + * Maximum valid code point. + * @type {number} + * @const + */ + utfx.MAX_CODEPOINT = 0x10FFFF; + + /** + * Encodes UTF8 code points to UTF8 bytes. + * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point + * respectively `null` if there are no more code points left or a single numeric code point. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte + */ + utfx.encodeUTF8 = function(src, dst) { + var cp = null; + if (typeof src === 'number') + cp = src, + src = function() { return null; }; + while (cp !== null || (cp = src()) !== null) { + if (cp < 0x80) + dst(cp&0x7F); + else if (cp < 0x800) + dst(((cp>>6)&0x1F)|0xC0), + dst((cp&0x3F)|0x80); + else if (cp < 0x10000) + dst(((cp>>12)&0x0F)|0xE0), + dst(((cp>>6)&0x3F)|0x80), + dst((cp&0x3F)|0x80); + else + dst(((cp>>18)&0x07)|0xF0), + dst(((cp>>12)&0x3F)|0x80), + dst(((cp>>6)&0x3F)|0x80), + dst((cp&0x3F)|0x80); + cp = null; + } + }; + + /** + * Decodes UTF8 bytes to UTF8 code points. + * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there + * are no more bytes left. + * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point. + * @throws {RangeError} If a starting byte is invalid in UTF8 + * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the + * remaining bytes. + */ + utfx.decodeUTF8 = function(src, dst) { + var a, b, c, d, fail = function(b) { + b = b.slice(0, b.indexOf(null)); + var err = Error(b.toString()); + err.name = "TruncatedError"; + err['bytes'] = b; + throw err; + }; + while ((a = src()) !== null) { + if ((a&0x80) === 0) + dst(a); + else if ((a&0xE0) === 0xC0) + ((b = src()) === null) && fail([a, b]), + dst(((a&0x1F)<<6) | (b&0x3F)); + else if ((a&0xF0) === 0xE0) + ((b=src()) === null || (c=src()) === null) && fail([a, b, c]), + dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F)); + else if ((a&0xF8) === 0xF0) + ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]), + dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F)); + else throw RangeError("Illegal starting byte: "+a); + } + }; + + /** + * Converts UTF16 characters to UTF8 code points. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @param {!function(number)} dst Code points destination as a function successively called with each converted code + * point. + */ + utfx.UTF16toUTF8 = function(src, dst) { + var c1, c2 = null; + while (true) { + if ((c1 = c2 !== null ? c2 : src()) === null) + break; + if (c1 >= 0xD800 && c1 <= 0xDFFF) { + if ((c2 = src()) !== null) { + if (c2 >= 0xDC00 && c2 <= 0xDFFF) { + dst((c1-0xD800)*0x400+c2-0xDC00+0x10000); + c2 = null; continue; + } + } + } + dst(c1); + } + if (c2 !== null) dst(c2); + }; + + /** + * Converts UTF8 code points to UTF16 characters. + * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point + * respectively `null` if there are no more code points left or a single numeric code point. + * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. + * @throws {RangeError} If a code point is out of range + */ + utfx.UTF8toUTF16 = function(src, dst) { + var cp = null; + if (typeof src === 'number') + cp = src, src = function() { return null; }; + while (cp !== null || (cp = src()) !== null) { + if (cp <= 0xFFFF) + dst(cp); + else + cp -= 0x10000, + dst((cp>>10)+0xD800), + dst((cp%0x400)+0xDC00); + cp = null; + } + }; + + /** + * Converts and encodes UTF16 characters to UTF8 bytes. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null` + * if there are no more characters left. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. + */ + utfx.encodeUTF16toUTF8 = function(src, dst) { + utfx.UTF16toUTF8(src, function(cp) { + utfx.encodeUTF8(cp, dst); + }); + }; + + /** + * Decodes and converts UTF8 bytes to UTF16 characters. + * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there + * are no more bytes left. + * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. + * @throws {RangeError} If a starting byte is invalid in UTF8 + * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes. + */ + utfx.decodeUTF8toUTF16 = function(src, dst) { + utfx.decodeUTF8(src, function(cp) { + utfx.UTF8toUTF16(cp, dst); + }); + }; + + /** + * Calculates the byte length of an UTF8 code point. + * @param {number} cp UTF8 code point + * @returns {number} Byte length + */ + utfx.calculateCodePoint = function(cp) { + return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + }; + + /** + * Calculates the number of UTF8 bytes required to store UTF8 code points. + * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively + * `null` if there are no more code points left. + * @returns {number} The number of UTF8 bytes required + */ + utfx.calculateUTF8 = function(src) { + var cp, l=0; + while ((cp = src()) !== null) + l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + return l; + }; + + /** + * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes. + * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @returns {!Array.} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1. + */ + utfx.calculateUTF16asUTF8 = function(src) { + var n=0, l=0; + utfx.UTF16toUTF8(src, function(cp) { + ++n; l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + }); + return [n,l]; + }; + + return utfx; + }(); + + // encodings/utf8 + + /** + * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded + * string. + * @returns {string} Hex encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ + ByteBufferPrototype.toUTF8 = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var sd; try { + utfx.decodeUTF8toUTF16(function() { + return begin < end ? this.view[begin++] : null; + }.bind(this), sd = stringDestination()); + } catch (e) { + if (begin !== end) + throw RangeError("Illegal range: Truncated data, "+begin+" != "+end); + } + return sd(); + }; + + /** + * Decodes an UTF8 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) { + if (!noAssert) + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + var bb = new ByteBuffer(utfx.calculateUTF16asUTF8(stringSource(str), true)[1], littleEndian, noAssert), + i = 0; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + bb.view[i++] = b; + }); + bb.limit = i; + return bb; + }; + + return ByteBuffer; +}); diff --git a/dist/bytebuffer.min.js b/dist/bytebuffer.min.js new file mode 100644 index 0000000..11c798e --- /dev/null +++ b/dist/bytebuffer.min.js @@ -0,0 +1,94 @@ +/* + bytebuffer.js (c) 2015 Daniel Wirtz + Backing buffer: ArrayBuffer, Accessor: Uint8Array + Released under the Apache License, Version 2.0 + see: https://github.com/dcodeIO/bytebuffer.js for details +*/ +(function(h,l){if("function"===typeof define&&define.amd)define(["long"],l);else if("function"===typeof require&&"object"===typeof module&&module&&module.exports){h=module;try{var t=require("long")}catch(v){}l=l(t);h.exports=l}else(h.dcodeIO=h.dcodeIO||{}).ByteBuffer=l(h.dcodeIO.Long)})(this,function(h){function l(a){var b=0;return function(){return b>1,n=-7;k=c?k-1:0;var h=c?-1:1,q=a[b+k];k+=h;c=q&(1<<-n)-1;q>>=-n;for(n+=f;0>=-n;for(n+=e;0>1,q=23===k?Math.pow(2, +-24)-Math.pow(2,-77):0;f=e?0:f-1;var l=e?1:-1,m=0>b||0===b&&0>1/b?1:0;b=Math.abs(b);isNaN(b)||Infinity===b?(b=isNaN(b)?1:0,e=n):(e=Math.floor(Math.log(b)/Math.LN2),1>b*(d=Math.pow(2,-e))&&(e--,d*=2),b=1<=e+h?b+q/d:b+q*Math.pow(2,1-h),2<=b*d&&(e++,d/=2),e+h>=n?(b=0,e=n):1<=e+h?(b=(b*d-1)*Math.pow(2,k),e+=h):(b=b*Math.pow(2,h-1)*Math.pow(2,k),e=0));for(;8<=k;a[c+f]=b&255,f+=l,b/=256,k-=8);e=e<a)throw RangeError("Illegal capacity");b=!!b;c=!!c}this.buffer=0===a?w:new ArrayBuffer(a);this.view=0===a?null:new Uint8Array(this.buffer);this.offset=0;this.markedOffset=-1;this.limit=a;this.littleEndian=b;this.noAssert=c};g.VERSION="5.0.1";g.LITTLE_ENDIAN=!0;g.BIG_ENDIAN=!1;g.DEFAULT_CAPACITY=16;g.DEFAULT_ENDIAN=g.BIG_ENDIAN;g.DEFAULT_NOASSERT=!1;g.Long=h||null;var d= +g.prototype;Object.defineProperty(d,"__isByteBuffer__",{value:!0,enumerable:!1,configurable:!1});var w=new ArrayBuffer(0),x=String.fromCharCode;g.accessor=function(){return Uint8Array};g.allocate=function(a,b,c){return new g(a,b,c)};g.concat=function(a,b,c,e){if("boolean"===typeof b||"string"!==typeof b)e=c,c=b,b=void 0;for(var k=0,f=0,d=a.length,u;f=u||(b.view.set(c.view.subarray(c.offset,c.limit),b.offset),b.offset+=u);b.limit=b.offset;b.offset=0;return b};g.isByteBuffer=function(a){return!0===(a&&a.__isByteBuffer__)};g.type=function(){return ArrayBuffer};g.wrap=function(a,b,c,e){"string"!==typeof b&&(e=c,c=b,b=void 0);if("string"===typeof a)switch("undefined"===typeof b&&(b="utf8"),b){case "base64":return g.fromBase64(a,c);case "hex":return g.fromHex(a,c);case "binary":return g.fromBinary(a,c);case "utf8":return g.fromUTF8(a, +c);case "debug":return g.fromDebug(a,c);default:throw Error("Unsupported encoding: "+b);}if(null===a||"object"!==typeof a)throw TypeError("Illegal buffer");if(g.isByteBuffer(a))return b=d.clone.call(a),b.markedOffset=-1,b;if(a instanceof Uint8Array)b=new g(0,c,e),0>>=0;if(0>b||b+0> +this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var e=b,k=a.length,f=k>>3,d=0;for(b+=this.writeVarint32(k,b);f--;){var g=!!a[d++]&1|(!!a[d++]&1)<<1|(!!a[d++]&1)<<2|(!!a[d++]&1)<<3|(!!a[d++]&1)<<4|(!!a[d++]&1)<<5|(!!a[d++]&1)<<6|(!!a[d++]&1)<<7;this.writeByte(g,b++)}if(d>3,f=0,d=[];for(a+=c.length;k--;)c=this.readByte(a++),d[f++]=!!(c&1),d[f++]=!!(c&2),d[f++]=!!(c&4),d[f++]=!!(c&8),d[f++]=!!(c&16),d[f++]=!!(c&32),d[f++]=!!(c&64),d[f++]=!!(c&128);if(f>k++&1);b&&(this.offset=a);return d};d.readBytes=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b|| +b+a>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+"+a+") <= "+this.buffer.byteLength);}b=this.slice(b,b+a);c&&(this.offset+=a);return b};d.writeInt8=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +b+" (+0) <= "+this.buffer.byteLength);}b+=1;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);this.view[b-1]=a;c&&(this.offset+=1);return this};d.writeByte=d.writeInt8;d.readInt8=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}a=this.view[a];128=== +(a&128)&&(a=-(255-a+1));b&&(this.offset+=1);return a};d.readByte=d.readInt8;d.writeUint8=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=1;var e=this.buffer.byteLength; +b>e&&this.resize((e*=2)>b?e:b);this.view[b-1]=a;c&&(this.offset+=1);return this};d.writeUInt8=d.writeUint8;d.readUint8=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}a=this.view[a];b&&(this.offset+=1);return a};d.readUInt8=d.readUint8;d.writeInt16=function(a, +b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=2;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=2;this.littleEndian?(this.view[b+1]=(a&65280)>>>8,this.view[b]= +a&255):(this.view[b]=(a&65280)>>>8,this.view[b+1]=a&255);c&&(this.offset+=2);return this};d.writeShort=d.writeInt16;d.readInt16=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+2>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+2) <= "+this.buffer.byteLength);}if(this.littleEndian){var c=this.view[a];c|=this.view[a+1]<<8}else c=this.view[a]<< +8,c|=this.view[a+1];32768===(c&32768)&&(c=-(65535-c+1));b&&(this.offset+=2);return c};d.readShort=d.readInt16;d.writeUint16=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength); +}b+=2;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=2;this.littleEndian?(this.view[b+1]=(a&65280)>>>8,this.view[b]=a&255):(this.view[b]=(a&65280)>>>8,this.view[b+1]=a&255);c&&(this.offset+=2);return this};d.writeUInt16=d.writeUint16;d.readUint16=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+2>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +a+" (+2) <= "+this.buffer.byteLength);}if(this.littleEndian){var c=this.view[a];c|=this.view[a+1]<<8}else c=this.view[a]<<8,c|=this.view[a+1];b&&(this.offset+=2);return c};d.readUInt16=d.readUint16;d.writeInt32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +b+" (+0) <= "+this.buffer.byteLength);}b+=4;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=4;this.littleEndian?(this.view[b+3]=a>>>24&255,this.view[b+2]=a>>>16&255,this.view[b+1]=a>>>8&255,this.view[b]=a&255):(this.view[b]=a>>>24&255,this.view[b+1]=a>>>16&255,this.view[b+2]=a>>>8&255,this.view[b+3]=a&255);c&&(this.offset+=4);return this};d.writeInt=d.writeInt32;d.readInt32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a% +1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}if(this.littleEndian){var c=this.view[a+2]<<16;c|=this.view[a+1]<<8;c|=this.view[a];c+=this.view[a+3]<<24>>>0}else c=this.view[a+1]<<16,c|=this.view[a+2]<<8,c|=this.view[a+3],c+=this.view[a]<<24>>>0;b&&(this.offset+=4);return c|0};d.readInt=d.readInt32;d.writeUint32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset); +if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=4;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=4;this.littleEndian?(this.view[b+3]=a>>>24&255,this.view[b+2]=a>>>16&255,this.view[b+1]=a>>>8&255,this.view[b]= +a&255):(this.view[b]=a>>>24&255,this.view[b+1]=a>>>16&255,this.view[b+2]=a>>>8&255,this.view[b+3]=a&255);c&&(this.offset+=4);return this};d.writeUInt32=d.writeUint32;d.readUint32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}if(this.littleEndian){var c=this.view[a+ +2]<<16;c|=this.view[a+1]<<8;c|=this.view[a];c+=this.view[a+3]<<24>>>0}else c=this.view[a+1]<<16,c|=this.view[a+2]<<8,c|=this.view[a+3],c+=this.view[a]<<24>>>0;b&&(this.offset+=4);return c};d.readUInt32=d.readUint32;h&&(d.writeInt64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"===typeof a)a=h.fromNumber(a);else if("string"===typeof a)a=h.fromString(a);else if(!(a&&a instanceof h))throw TypeError("Illegal value: "+a+" (not an integer or Long)");if("number"!== +typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=h.fromNumber(a):"string"===typeof a&&(a=h.fromString(a));b+=8;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=8;e=a.low;a=a.high;this.littleEndian?(this.view[b+3]=e>>>24&255,this.view[b+2]=e>>>16&255,this.view[b+1]=e>>>8&255,this.view[b]=e&255,b+=4,this.view[b+3]=a>>> +24&255,this.view[b+2]=a>>>16&255,this.view[b+1]=a>>>8&255,this.view[b]=a&255):(this.view[b]=a>>>24&255,this.view[b+1]=a>>>16&255,this.view[b+2]=a>>>8&255,this.view[b+3]=a&255,b+=4,this.view[b]=e>>>24&255,this.view[b+1]=e>>>16&255,this.view[b+2]=e>>>8&255,this.view[b+3]=e&255);c&&(this.offset+=8);return this},d.writeLong=d.writeInt64,d.readInt64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)"); +a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+8) <= "+this.buffer.byteLength);}if(this.littleEndian){var c=this.view[a+2]<<16;c|=this.view[a+1]<<8;c|=this.view[a];c+=this.view[a+3]<<24>>>0;a+=4;var e=this.view[a+2]<<16;e|=this.view[a+1]<<8;e|=this.view[a];e+=this.view[a+3]<<24>>>0}else e=this.view[a+1]<<16,e|=this.view[a+2]<<8,e|=this.view[a+3],e+=this.view[a]<<24>>>0,a+=4,c=this.view[a+1]<<16,c|=this.view[a+2]<<8,c|=this.view[a+3],c+=this.view[a]<<24>>> +0;a=new h(c,e,!1);b&&(this.offset+=8);return a},d.readLong=d.readInt64,d.writeUint64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"===typeof a)a=h.fromNumber(a);else if("string"===typeof a)a=h.fromString(a);else if(!(a&&a instanceof h))throw TypeError("Illegal value: "+a+" (not an integer or Long)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=h.fromNumber(a):"string"===typeof a&&(a=h.fromString(a));b+=8;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=8;e=a.low;a=a.high;this.littleEndian?(this.view[b+3]=e>>>24&255,this.view[b+2]=e>>>16&255,this.view[b+1]=e>>>8&255,this.view[b]=e&255,b+=4,this.view[b+3]=a>>>24&255,this.view[b+2]=a>>>16&255,this.view[b+1]=a>>>8&255,this.view[b]=a&255):(this.view[b]=a>>>24&255,this.view[b+1]=a>>>16&255,this.view[b+2]=a>>>8&255,this.view[b+ +3]=a&255,b+=4,this.view[b]=e>>>24&255,this.view[b+1]=e>>>16&255,this.view[b+2]=e>>>8&255,this.view[b+3]=e&255);c&&(this.offset+=8);return this},d.writeUInt64=d.writeUint64,d.readUint64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+8) <= "+this.buffer.byteLength);}if(this.littleEndian){var c= +this.view[a+2]<<16;c|=this.view[a+1]<<8;c|=this.view[a];c+=this.view[a+3]<<24>>>0;a+=4;var e=this.view[a+2]<<16;e|=this.view[a+1]<<8;e|=this.view[a];e+=this.view[a+3]<<24>>>0}else e=this.view[a+1]<<16,e|=this.view[a+2]<<8,e|=this.view[a+3],e+=this.view[a]<<24>>>0,a+=4,c=this.view[a+1]<<16,c|=this.view[a+2]<<8,c|=this.view[a+3],c+=this.view[a]<<24>>>0;a=new h(c,e,!0);b&&(this.offset+=8);return a},d.readUInt64=d.readUint64);d.writeFloat32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset); +if(!this.noAssert){if("number"!==typeof a)throw TypeError("Illegal value: "+a+" (not a number)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=4;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);y(this.view,a,b-4,this.littleEndian,23,4);c&&(this.offset+=4);return this};d.writeFloat=d.writeFloat32;d.readFloat32=function(a){var b= +"undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}a=v(this.view,a,this.littleEndian,23,4);b&&(this.offset+=4);return a};d.readFloat=d.readFloat32;d.writeFloat64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a)throw TypeError("Illegal value: "+ +a+" (not a number)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=8;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);y(this.view,a,b-8,this.littleEndian,52,8);c&&(this.offset+=8);return this};d.writeDouble=d.writeFloat64;d.readFloat64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!== +typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+8) <= "+this.buffer.byteLength);}a=v(this.view,a,this.littleEndian,52,8);b&&(this.offset+=8);return a};d.readDouble=d.readFloat64;g.MAX_VARINT32_BYTES=5;g.calculateVarint32=function(a){a>>>=0;return 128>a?1:16384>a?2:2097152>a?3:268435456>a?4:5};g.zigZagEncode32=function(a){return((a|=0)<<1^a>>31)>>>0};g.zigZagDecode32=function(a){return a>>> +1^-(a&1)|0};d.writeVarint32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var e=g.calculateVarint32(a);b+=e;var k=this.buffer.byteLength;b>k&&this.resize((k*=2)> +b?k:b);b-=e;for(a>>>=0;128<=a;)k=a&127|128,this.view[b++]=k,a>>>=7;this.view[b++]=a;return c?(this.offset=b,this):e};d.writeVarint32ZigZag=function(a,b){return this.writeVarint32(g.zigZagEncode32(a),b)};d.readVarint32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength); +}var c=0,e=0;do{if(!this.noAssert&&a>this.limit)throw a=Error("Truncated"),a.truncated=!0,a;var k=this.view[a++];5>c&&(e|=(k&127)<<7*c);++c}while(0!==(k&128));e|=0;return b?(this.offset=a,e):{value:e,length:c}};d.readVarint32ZigZag=function(a){a=this.readVarint32(a);"object"===typeof a?a.value=g.zigZagDecode32(a.value):a=g.zigZagDecode32(a);return a};h&&(g.MAX_VARINT64_BYTES=10,g.calculateVarint64=function(a){"number"===typeof a?a=h.fromNumber(a):"string"===typeof a&&(a=h.fromString(a));var b=a.toInt()>>> +0,c=a.shiftRightUnsigned(28).toInt()>>>0;a=a.shiftRightUnsigned(56).toInt()>>>0;return 0==a?0==c?16384>b?128>b?1:2:2097152>b?3:4:16384>c?128>c?5:6:2097152>c?7:8:128>a?9:10},g.zigZagEncode64=function(a){"number"===typeof a?a=h.fromNumber(a,!1):"string"===typeof a?a=h.fromString(a,!1):!1!==a.unsigned&&(a=a.toSigned());return a.shiftLeft(1).xor(a.shiftRight(63)).toUnsigned()},g.zigZagDecode64=function(a){"number"===typeof a?a=h.fromNumber(a,!1):"string"===typeof a?a=h.fromString(a,!1):!1!==a.unsigned&& +(a=a.toSigned());return a.shiftRightUnsigned(1).xor(a.and(h.ONE).toSigned().negate()).toSigned()},d.writeVarint64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"===typeof a)a=h.fromNumber(a);else if("string"===typeof a)a=h.fromString(a);else if(!(a&&a instanceof h))throw TypeError("Illegal value: "+a+" (not an integer or Long)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=h.fromNumber(a,!1):"string"===typeof a?a=h.fromString(a,!1):!1!==a.unsigned&&(a=a.toSigned());var e=g.calculateVarint64(a),k=a.toInt()>>>0,f=a.shiftRightUnsigned(28).toInt()>>>0;a=a.shiftRightUnsigned(56).toInt()>>>0;b+=e;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);b-=e;switch(e){case 10:this.view[b+9]=a>>>7&1;case 9:this.view[b+8]=9!==e?a|128:a&127;case 8:this.view[b+7]=8!==e?f>>>21|128:f>>>21&127;case 7:this.view[b+6]= +7!==e?f>>>14|128:f>>>14&127;case 6:this.view[b+5]=6!==e?f>>>7|128:f>>>7&127;case 5:this.view[b+4]=5!==e?f|128:f&127;case 4:this.view[b+3]=4!==e?k>>>21|128:k>>>21&127;case 3:this.view[b+2]=3!==e?k>>>14|128:k>>>14&127;case 2:this.view[b+1]=2!==e?k>>>7|128:k>>>7&127;case 1:this.view[b]=1!==e?k|128:k&127}return c?(this.offset+=e,this):e},d.writeVarint64ZigZag=function(a,b){return this.writeVarint64(g.zigZagEncode64(a),b)},d.readVarint64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!== +typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,e=0,k=0;var d=this.view[a++];var g=d&127;if(d&128&&(d=this.view[a++],g|=(d&127)<<7,d&128||this.noAssert&&"undefined"===typeof d)&&(d=this.view[a++],g|=(d&127)<<14,d&128||this.noAssert&&"undefined"===typeof d)&&(d=this.view[a++],g|=(d&127)<<21,d&128||this.noAssert&&"undefined"===typeof d)&&(d=this.view[a++], +e=d&127,d&128||this.noAssert&&"undefined"===typeof d)&&(d=this.view[a++],e|=(d&127)<<7,d&128||this.noAssert&&"undefined"===typeof d)&&(d=this.view[a++],e|=(d&127)<<14,d&128||this.noAssert&&"undefined"===typeof d)&&(d=this.view[a++],e|=(d&127)<<21,d&128||this.noAssert&&"undefined"===typeof d)&&(d=this.view[a++],k=d&127,d&128||this.noAssert&&"undefined"===typeof d)&&(d=this.view[a++],k|=(d&127)<<7,d&128||this.noAssert&&"undefined"===typeof d))throw Error("Buffer overrun");g=h.fromBits(g|e<<28,e>>>4| +k<<24,!1);return b?(this.offset=a,g):{value:g,length:a-c}},d.readVarint64ZigZag=function(a){(a=this.readVarint64(a))&&a.value instanceof h?a.value=g.zigZagDecode64(a.value):a=g.zigZagDecode64(a);return a});d.writeCString=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);var e,d=a.length;if(!this.noAssert){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");for(e=0;e>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}d=m.calculateUTF16asUTF8(l(a))[1];b+=d+1;e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=d+1;m.encodeUTF16toUTF8(l(a),function(a){this.view[b++]=a}.bind(this));this.view[b++]=0;return c?(this.offset=b,this):d};d.readCString=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!== +typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,e,d=-1;m.decodeUTF8toUTF16(function(){if(0===d)return null;if(a>=this.limit)throw RangeError("Illegal range: Truncated data, "+a+" < "+this.limit);d=this.view[a++];return 0===d?null:d}.bind(this),e=t(),!0);return b?(this.offset=a,e()):{string:e(),length:a-c}};d.writeIString=function(a,b){var c= +"undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var e=b;var d=m.calculateUTF16asUTF8(l(a),this.noAssert)[1];b+=4+d;var f=this.buffer.byteLength;b>f&&this.resize((f*=2)>b?f:b);b-=4+d;this.littleEndian?(this.view[b+ +3]=d>>>24&255,this.view[b+2]=d>>>16&255,this.view[b+1]=d>>>8&255,this.view[b]=d&255):(this.view[b]=d>>>24&255,this.view[b+1]=d>>>16&255,this.view[b+2]=d>>>8&255,this.view[b+3]=d&255);b+=4;m.encodeUTF16toUTF8(l(a),function(a){this.view[b++]=a}.bind(this));if(b!==e+4+d)throw RangeError("Illegal range: Truncated data, "+b+" == "+(b+4+d));return c?(this.offset=b,this):b-e};d.readIString=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+ +a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}var c=a,e=this.readUint32(a);e=this.readUTF8String(e,g.METRICS_BYTES,a+=4);a+=e.length;return b?(this.offset=a,e.string):{string:e.string,length:a-c}};g.METRICS_CHARS="c";g.METRICS_BYTES="b";d.writeUTF8String=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+ +b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var e=b;var d=m.calculateUTF16asUTF8(l(a))[1];b+=d;var f=this.buffer.byteLength;b>f&&this.resize((f*=2)>b?f:b);b-=d;m.encodeUTF16toUTF8(l(a),function(a){this.view[b++]=a}.bind(this));return c?(this.offset=b,this):b-e};d.writeString=d.writeUTF8String;g.calculateUTF8Chars=function(a){return m.calculateUTF16asUTF8(l(a))[0]};g.calculateUTF8Bytes=function(a){return m.calculateUTF16asUTF8(l(a))[1]}; +g.calculateString=g.calculateUTF8Bytes;d.readUTF8String=function(a,b,c){"number"===typeof b&&(c=b,b=void 0);var e="undefined"===typeof c;e&&(c=this.offset);"undefined"===typeof b&&(b=g.METRICS_CHARS);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal length: "+a+" (not an integer)");a|=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+0) <= "+ +this.buffer.byteLength);}var d=0,f=c;if(b===g.METRICS_CHARS){var p=t();m.decodeUTF8(function(){return d>>=0;if(0>c||c+a>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+ +c+" (+"+a+") <= "+this.buffer.byteLength);}var h=c+a;m.decodeUTF8toUTF16(function(){return c>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var e=b;var d=m.calculateUTF16asUTF8(l(a),this.noAssert)[1];var f=g.calculateVarint32(d);b+=f+d;var p=this.buffer.byteLength;b>p&&this.resize((p*=2)>b?p:b);b-=f+d;b+=this.writeVarint32(d,b);m.encodeUTF16toUTF8(l(a),function(a){this.view[b++]=a}.bind(this));if(b!==e+d+f)throw RangeError("Illegal range: Truncated data, "+ +b+" == "+(b+d+f));return c?(this.offset=b,this):b-e};d.readVString=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,e=this.readVarint32(a);e=this.readUTF8String(e.value,g.METRICS_BYTES,a+=e.length);a+=e.length;return b?(this.offset=a,e.string):{string:e.string, +length:a-c}};d.append=function(a,b,c){if("number"===typeof b||"string"!==typeof b)c=b,b=void 0;var e="undefined"===typeof c;e&&(c=this.offset);if(!this.noAssert){if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+0) <= "+this.buffer.byteLength);}a instanceof g||(a=g.wrap(a,b));b=a.limit-a.offset;if(0>=b)return this;c+=b;var d=this.buffer.byteLength;c>d&&this.resize((d*=2)> +c?d:c);c-=b;this.view.set(a.view.subarray(a.offset,a.limit),c);a.offset+=b;e&&(this.offset+=b);return this};d.appendTo=function(a,b){a.append(this,b);return this};d.writeBytes=d.append;d.assert=function(a){this.noAssert=!a;return this};d.capacity=function(){return this.buffer.byteLength};d.clear=function(){this.offset=0;this.limit=this.buffer.byteLength;this.markedOffset=-1;return this};d.clone=function(a){var b=new g(0,this.littleEndian,this.noAssert);a?(b.buffer=new ArrayBuffer(this.buffer.byteLength), +b.view=new Uint8Array(b.buffer)):(b.buffer=this.buffer,b.view=this.view);b.offset=this.offset;b.markedOffset=this.markedOffset;b.limit=this.limit;return b};d.compact=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+ +a+" <= "+b+" <= "+this.buffer.byteLength);}if(0===a&&b===this.buffer.byteLength)return this;var c=b-a;if(0===c)return this.buffer=w,this.view=null,0<=this.markedOffset&&(this.markedOffset-=a),this.limit=this.offset=0,this;var e=new ArrayBuffer(c),d=new Uint8Array(e);d.set(this.view.subarray(a,b));this.buffer=e;this.view=d;0<=this.markedOffset&&(this.markedOffset-=a);this.offset=0;this.limit=c;return this};d.copy=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit); +if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}if(a===b)return new g(0,this.littleEndian,this.noAssert);var c=b-a,e=new g(c,this.littleEndian,this.noAssert);e.offset=0;e.limit=c;0<=e.markedOffset&&(e.markedOffset-=a);this.copyTo(e,0,a, +b);return e};d.copyTo=function(a,b,c,e){var d,f;if(!this.noAssert&&!g.isByteBuffer(a))throw TypeError("Illegal target: Not a ByteBuffer");b=(f="undefined"===typeof b)?a.offset:b|0;c=(d="undefined"===typeof c)?this.offset:c|0;e="undefined"===typeof e?this.limit:e|0;if(0>b||b>a.buffer.byteLength)throw RangeError("Illegal target range: 0 <= "+b+" <= "+a.buffer.byteLength);if(0>c||e>this.buffer.byteLength)throw RangeError("Illegal source range: 0 <= "+c+" <= "+this.buffer.byteLength);var p=e-c;if(0=== +p)return a;a.ensureCapacity(b+p);a.view.set(this.view.subarray(c,e),b);d&&(this.offset+=p);f&&(a.offset+=p);return this};d.ensureCapacity=function(a){var b=this.buffer.byteLength;return ba?b:a):this};d.fill=function(a,b,c){var e="undefined"===typeof b;e&&(b=this.offset);"string"===typeof a&&0>>=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal end: Not an integer");c>>>=0;if(0>b||b>c||c>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+b+" <= "+c+" <= "+this.buffer.byteLength);}if(b>=c)return this;for(;b>>=0;if(0>a||a+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+0) <= "+this.buffer.byteLength);}this.markedOffset=a;return this};d.order=function(a){if(!this.noAssert&&"boolean"!==typeof a)throw TypeError("Illegal littleEndian: Not a boolean");this.littleEndian=!!a;return this};d.LE=function(a){this.littleEndian="undefined"!==typeof a?!!a:!0; +return this};d.BE=function(a){this.littleEndian="undefined"!==typeof a?!a:!1;return this};d.prepend=function(a,b,c){if("number"===typeof b||"string"!==typeof b)c=b,b=void 0;var e="undefined"===typeof c;e&&(c=this.offset);if(!this.noAssert){if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+0) <= "+this.buffer.byteLength);}a instanceof g||(a=g.wrap(a,b));b=a.limit-a.offset; +if(0>=b)return this;var d=b-c;if(0a)throw RangeError("Illegal capacity: 0 <= "+ +a);}if(this.buffer.byteLength>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+ +a+" <= "+b+" <= "+this.buffer.byteLength);}if(a===b)return this;Array.prototype.reverse.call(this.view.subarray(a,b));return this};d.skip=function(a){if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal length: "+a+" (not an integer)");a|=0}var b=this.offset+a;if(!this.noAssert&&(0>b||b>this.buffer.byteLength))throw RangeError("Illegal length: 0 <= "+this.offset+" + "+a+" <= "+this.buffer.byteLength);this.offset=b;return this};d.slice=function(a,b){"undefined"===typeof a&&(a= +this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}var c=this.clone();c.offset=a;c.limit=b;return c};d.toBuffer=function(a){var b=this.offset,c=this.limit;if(!this.noAssert){if("number"!== +typeof b||0!==b%1)throw TypeError("Illegal offset: Not an integer");b>>>=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal limit: Not an integer");c>>>=0;if(0>b||b>c||c>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+b+" <= "+c+" <= "+this.buffer.byteLength);}if(!a&&0===b&&c===this.buffer.byteLength)return this.buffer;if(b===c)return w;a=new ArrayBuffer(c-b);(new Uint8Array(a)).set((new Uint8Array(this.buffer)).subarray(b,c),0);return a};d.toArrayBuffer=d.toBuffer;d.toString= +function(a,b,c){if("undefined"===typeof a)return"ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")";"number"===typeof a&&(c=b=a="utf8");switch(a){case "utf8":return this.toUTF8(b,c);case "base64":return this.toBase64(b,c);case "hex":return this.toHex(b,c);case "binary":return this.toBinary(b,c);case "debug":return this.toDebug();case "columns":return this.toColumns();default:throw Error("Unsupported encoding: "+a);}};var z=function(){for(var a= +{},b=[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,54,55,56,57,43,47],c=[],e=0,d=b.length;e>2&63]),d=(e&3)<<4,null!==(e=a())?(d|=e>>4&15,c(b[(d|e>>4&15)&63]),d=(e&15)<<2,null!==(e=a())?(c(b[(d|e>>6&3)&63]),c(b[e&63])):(c(b[d&63]),c(61))):(c(b[d&63]),c(61),c(61))};a.decode=function(a, +b){function e(a){throw Error("Illegal character code: "+a);}for(var d,k,f;null!==(d=a());)if(k=c[d],"undefined"===typeof k&&e(d),null!==(d=a())&&(f=c[d],"undefined"===typeof f&&e(d),b(k<<2>>>0|(f&48)>>4),null!==(d=a()))){k=c[d];if("undefined"===typeof k)if(61===d)break;else e(d);b((f&15)<<4>>>0|(k&60)>>2);if(null!==(d=a())){f=c[d];if("undefined"===typeof f)if(61===d)break;else e(d);b((k&3)<<6>>>0|f)}}};a.test=function(a){return/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(a)}; +return a}();d.toBase64=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);a|=0;b|=0;if(0>a||b>this.capacity||a>b)throw RangeError("begin, end");var c;z.encode(function(){return aa||b>this.capacity()||a>b)throw RangeError("begin, end");if(a===b)return"";for(var c=[],e=[];ae?d+("0"+e.toString(16).toUpperCase()):d+e.toString(16).toUpperCase(),a&&(f+=32e?String.fromCharCode(e):"."));++b;if(a&&0d.length;)d+=" ";g+=d+f+"\n";d=f=""}d=b===this.offset&&b===this.limit?d+(b===this.markedOffset?"!":"|"):b===this.offset? +d+(b===this.markedOffset?"[":"<"):b===this.limit?d+(b===this.markedOffset?"]":">"):d+(b===this.markedOffset?"'":a||0!==b&&b!==c?" ":"")}if(a&&" "!==d){for(;51>d.length;)d+=" ";g+=d+f+"\n"}return a?g:d};g.fromDebug=function(a,b,c){var e=a.length;b=new g((e+1)/3|0,b,c);for(var d=0,f=0,h,l=!1,n=!1,m=!1,q=!1,r=!1;d":if(!c){if(q){r=!0;break}q=!0}b.limit=f;l=!1;break;case "'":if(!c){if(m){r=!0;break}m=!0}b.markedOffset=f;l=!1;break;case " ":l=!1;break;default:if(!c&&l)r=!0;else{h=parseInt(h+a.charAt(d++),16);if(!c&&(isNaN(h)||0>h||255>>=0;if("number"!==typeof b|| +0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}for(var c=Array(b-a),e;ae?c.push("0",e.toString(16)):c.push(e.toString(16));return c.join("")};g.fromHex=function(a,b,c){if(!c){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");if(0!==a.length%2)throw TypeError("Illegal str: Length not a multiple of 2");}var e=a.length;b=new g(e/ +2|0,b);for(var d,f=0,h=0;fd||255b?c(b&127):(2048>b?c(b>>6&31|192):65536>b?(c(b>>12&15|224),c(b>>6&63|128)):(c(b>>18&7|240),c(b>>12&63|128),c(b>>6&63|128)),c(b&63|128)), +b=null},decodeUTF8:function(a,c){for(var b,d,f,g,h=function(a){a=a.slice(0,a.indexOf(null));var b=Error(a.toString());b.name="TruncatedError";b.bytes=a;throw b;};null!==(b=a());)if(0===(b&128))c(b);else if(192===(b&224))null===(d=a())&&h([b,d]),c((b&31)<<6|d&63);else if(224===(b&240))null!==(d=a())&&null!==(f=a())||h([b,d,f]),c((b&15)<<12|(d&63)<<6|f&63);else if(240===(b&248))null!==(d=a())&&null!==(f=a())&&null!==(g=a())||h([b,d,f,g]),c((b&7)<<18|(d&63)<<12|(f&63)<<6|g&63);else throw RangeError("Illegal starting byte: "+ +b);},UTF16toUTF8:function(a,c){for(var b,d=null;null!==(b=null!==d?d:a());)55296<=b&&57343>=b&&null!==(d=a())&&56320<=d&&57343>=d?(c(1024*(b-55296)+d-56320+65536),d=null):c(b);null!==d&&c(d)},UTF8toUTF16:function(a,c){var b=null;"number"===typeof a&&(b=a,a=function(){return null});for(;null!==b||null!==(b=a());)65535>=b?c(b):(b-=65536,c((b>>10)+55296),c(b%1024+56320)),b=null},encodeUTF16toUTF8:function(b,c){a.UTF16toUTF8(b,function(b){a.encodeUTF8(b,c)})},decodeUTF8toUTF16:function(b,c){a.decodeUTF8(b, +function(b){a.UTF8toUTF16(b,c)})},calculateCodePoint:function(a){return 128>a?1:2048>a?2:65536>a?3:4},calculateUTF8:function(a){for(var b,d=0;null!==(b=a());)d+=128>b?1:2048>b?2:65536>b?3:4;return d},calculateUTF16asUTF8:function(b){var c=0,d=0;a.UTF16toUTF8(b,function(a){++c;d+=128>a?1:2048>a?2:65536>a?3:4});return[c,d]}};return a}();d.toUTF8=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer"); +a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}var c;try{m.decodeUTF8toUTF16(function(){return a - - - - Class: Long - - - - - - - - - - -
- -

Class: Long

- - - - - -
- -
-

- ByteBuffer. - - Long -

- -
- -
-
- - - - -
-

new Long(low, high)

- - -
-
- - -
-

Constructs a 64-bit two's-complement integer, given its low and high 32-bit -values as signed integers. See the from* functions below for more -convenient ways of constructing Longs.

- -

The internal representation of a long is the two given signed, 32-bit values. -We use 32-bit pieces because these are the size of integers on which -Javascript performs bit-operations. For operations like addition and -multiplication, we split each number into 16-bit pieces, which can easily be -multiplied within Javascript's floating-point representation without overflow -or change in sign.

- -

In the algorithms below, we frequently reduce the negative case to the -positive case by negating the input(s) and then post-processing the result. -Note that we must ALWAYS check specially whether those values are MINVALUE -(-2^63) because -MINVALUE == MIN_VALUE (since 2^63 cannot be represented as -a positive number, it overflows back into a negative). Not handling this -case would often result in infinite recursion.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
low - - -number - - - -

The low (signed) 32 bits of the long.

high - - -number - - - -

The high (signed) 32 bits of the long.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
- - -
- - - - - - - - - - - - -

Members

- -
- -
-

<static> MAX_VALUE :Long

- - -
-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static> MIN_VALUE :Long

- - -
-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static> NEG_ONE :Long

- - -
-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static> ONE :Long

- - -
-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static> ZERO :Long

- - -
-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-

<static> fromBits(lowBits, highBits) → {Long}

- - -
-
- - -
-

Returns a Long representing the 64-bit integer that comes by concatenating -the given high and low bits. Each is assumed to use 32 bits.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
lowBits - - -number - - - -

The low 32-bits.

highBits - - -number - - - -

The high 32-bits.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The corresponding Long value.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

<static> fromInt(value) → {Long}

- - -
-
- - -
-

Returns a Long representing the given (32-bit) integer value.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -number - - - -

The 32-bit integer in question.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The corresponding Long value.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

<static> fromNumber(value) → {Long}

- - -
-
- - -
-

Returns a Long representing the given value, provided that it is a finite -number. Otherwise, zero is returned.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -number - - - -

The number in question.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The corresponding Long value.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

<static> fromString(str, opt_radix) → {Long}

- - -
-
- - -
-

Returns a Long representation of the given string, written using the given -radix.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
str - - -string - - - - - - - -

The textual representation of the Long.

opt_radix - - -number - - - - - - <optional>
- - - -

The radix in which the text is written.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The corresponding Long value.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

add(other) → {Long}

- - -
-
- - -
-

Returns the sum of this and the given Long.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to add to this one.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The sum of this and the given Long.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

and(other) → {Long}

- - -
-
- - -
-

Returns the bitwise-AND of this Long and the given one.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

The Long with which to AND.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The bitwise-AND of this and the other.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

compare(other) → {number}

- - -
-
- - -
-

Compares this Long with the given one.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to compare against.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

0 if they are the same, 1 if the this is greater, and -1 - if the given one is greater.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

div(other) → {Long}

- - -
-
- - -
-

Returns this Long divided by the given one.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long by which to divide.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

This Long divided by the given one.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

equals(other) → {boolean}

- - -
-
- - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to compare against.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this Long equals the other.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

getHighBits() → {number}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The high 32-bits as a signed value.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

getLowBits() → {number}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The low 32-bits as a signed value.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

getLowBitsUnsigned() → {number}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The low 32-bits as an unsigned value.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

getNumBitsAbs() → {number}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Returns the number of bits needed to represent the absolute - value of this Long.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

greaterThan(other) → {boolean}

- - -
-
- - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to compare against.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this Long is greater than the other.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

greaterThanOrEqual(other) → {boolean}

- - -
-
- - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to compare against.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this Long is greater than or equal to the other.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

isNegative() → {boolean}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this value is negative.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

isOdd() → {boolean}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this value is odd.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

isZero() → {boolean}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this value is zero.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

lessThan(other) → {boolean}

- - -
-
- - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to compare against.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this Long is less than the other.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

lessThanOrEqual(other) → {boolean}

- - -
-
- - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to compare against.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this Long is less than or equal to the other.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

modulo(other) → {Long}

- - -
-
- - -
-

Returns this Long modulo the given one.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long by which to mod.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

This Long modulo the given one.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

multiply(other) → {Long}

- - -
-
- - -
-

Returns the product of this and the given long.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to multiply with this.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The product of this and the other.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

negate() → {Long}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The negation of this value.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

not() → {Long}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The bitwise-NOT of this value.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

notEquals(other) → {boolean}

- - -
-
- - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to compare against.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Whether this Long does not equal the other.

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

or(other) → {Long}

- - -
-
- - -
-

Returns the bitwise-OR of this Long and the given one.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

The Long with which to OR.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The bitwise-OR of this and the other.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

shiftLeft(numBits) → {Long}

- - -
-
- - -
-

Returns this Long with bits shifted to the left by the given amount.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
numBits - - -number - - - -

The number of bits by which to shift.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

This shifted to the left by the given amount.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

shiftRight(numBits) → {Long}

- - -
-
- - -
-

Returns this Long with bits shifted to the right by the given amount.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
numBits - - -number - - - -

The number of bits by which to shift.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

This shifted to the right by the given amount.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

shiftRightUnsigned(numBits) → {Long}

- - -
-
- - -
-

Returns this Long with bits shifted to the right by the given amount, with -the new top bits matching the current sign bit.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
numBits - - -number - - - -

The number of bits by which to shift.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

This shifted to the right by the given amount, with - zeros placed into the new leading bits.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

subtract(other) → {Long}

- - -
-
- - -
-

Returns the difference of this and the given Long.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

Long to subtract from this.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The difference of this and the given Long.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

toInt() → {number}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The value, assuming it is a 32-bit integer.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

toNumber() → {number}

- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The closest floating-point representation to this value.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

toString(opt_radix) → {string}

- - -
-
- - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
opt_radix - - -number - - - - - - <optional>
- - - -

The radix in which the text should be written.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The textual representation of this value.

-
- - - -
-
- Type -
-
- -string - - -
-
- - - - -
- - - -
-

xor(other) → {Long}

- - -
-
- - -
-

Returns the bitwise-XOR of this Long and the given one.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
other - - -Long - - - -

The Long with which to XOR.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The bitwise-XOR of this and the other.

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- -
- - - - - -
- -
- - - - -
- - - -
- - - - diff --git a/docs/ByteBuffer.html b/docs/ByteBuffer.html deleted file mode 100644 index 4f94100..0000000 --- a/docs/ByteBuffer.html +++ /dev/null @@ -1,15379 +0,0 @@ - - - - - Class: ByteBuffer - - - - - - - - - - -
- -

Class: ByteBuffer

- - - - - -
- -
-

- ByteBuffer -

- -

Provides a Java-like, Netty-inspired ByteBuffer implementation using typed arrays. It also tries to -abstract a bit of the complexity away by providing convenience methods for those who just want to write stuff -without caring about signed, unsigned and the actual bit sizes.

- -
- -
-
- - - - -
-

new ByteBuffer(capacity, littleEndian)

- - -
-
- - -
-

Constructs a new ByteBuffer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
capacity - - -number - - - - - - <optional>
- - - -

Initial capacity. Defaults to ByteBuffer.DEFAULT_CAPACITY.

littleEndian - - -boolean - - - - - - <optional>
- - - -

true to use little endian multi byte values, false for big endian. Defaults to false.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
- - -
- - - - - - - - - - - - -

Members

- -
- -
-

<static, constant> BIG_ENDIAN :boolean

- - -
-
- -
-

Big endian constant for usage in constructors instead of a boolean value. Evaluates to false.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static, constant> DEFAULT_CAPACITY :number

- - -
-
- -
-

Default buffer capacity of 16 if nothing else is stated. The ByteBuffer will be automatically resized by a factor -of 2 if required.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static, constant> LITTLE_ENDIAN :boolean

- - -
-
- -
-

Little endian constant for usage in constructors instead of a boolean value. Evaluates to true.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static, constant> Long :Long

- - -
-
- -
-

Long class for int64 support. May be undefined if the Long class has not been loaded and int64 support is - not available.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static, constant> MAX_VARINT32_BYTES :number

- - -
-
- -
-

Maximum number of bytes required to store a 32bit base 128 variable-length integer.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

<static, constant> MAX_VARINT64_BYTES :number

- - -
-
- -
-

Maximum number of bytes required to store a 64bit base 128 variable-length integer.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

array :ArrayBuffer

- - -
-
- -
-

Underlying ArrayBuffer.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

length :number

- - -
-
- -
-

Length of the contained data. Offset- and capacity-independent index. Contents are the bytes between offset and -length, which are both absolute indexes. There is no capacity property, use ByteBuffer#capacity -instead.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

littleEndian :boolean

- - -
-
- -
-

Whether to use little endian multi byte values.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

markedOffset :number

- - -
-
- -
-

Marked offset set through ByteBuffer#mark. Evaluates to -1 if there is no marked offset.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

offset :number

- - -
-
- -
-

Current read/write offset. Length- and capacity-independent index. Contents are the bytes between offset and -length, which are both absolute indexes. There is no capacity property, use ByteBuffer#capacity -instead.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-

view :DataView

- - -
-
- -
-

DataView to mess with the ArrayBuffer.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-

<static> allocate(capacity, littleEndian) → {ByteBuffer}

- - -
-
- - -
-

Allocates a new ByteBuffer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
capacity - - -number - - - - - - <optional>
- - - -

Initial capacity. Defaults to ByteBuffer.DEFAULT_CAPACITY.

littleEndian - - -boolean - - - - - - <optional>
- - - -

true to use little endian multi byte values, false for big endian. Defaults to true.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

<static> calculateUTF8Char(charCode) → {number}

- - -
-
- - -
-

Calculates the actual number of bytes required to encode the specified char code.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
charCode - - -number - - - -

Character to encode as char code

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the character cannot be calculated (too large) -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Number of bytes required to encode the specified char code

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

<static> calculateUTF8String(str) → {number}

- - -
-
- - -
-

Calculates the number of bytes required to store an UTF8 encoded string.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
str - - -string - - - -

String to calculate

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Number of bytes required

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

<static> calculateVarint32(value) → {number}

- - -
-
- - -
-

Calculates the actual number of bytes required to encode a 32bit base 128 variable-length integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -number - - - -

Value to encode

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Number of bytes required. Capped to ByteBuffer.MAX_VARINT32_BYTES (35bit). No overflow error.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

<static> calculateVarint64(value) → {number}

- - -
-
- - -
-

Calculates the actual number of bytes required to encode a 64bit base 128 variable-length integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -number -| - -Long - - - -

Value to encode

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Number of bytes required. Capped to ByteBuffer.MAX_VARINT64_BYTES. No overflow error.

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

<static> decode64(str) → {ByteBuffer}

- - -
-
- - -
-

Decodes a base6 encoded string to a ByteBuffer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
str - - -string - - - -

Base64 encoded string

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the argument is not a valid base64 encoded string -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

ByteBuffer

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

<static> decodeUTF8Char(src, offset) → {{char: number, length: number}}

- - -
-
- - -
-

Decodes a single UTF8 character from the specified ByteBuffer. The ByteBuffer's offsets are not modified.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
src - - -ByteBuffer - - - -
offset - - -number - - - -

Offset to read from

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the character cannot be decoded or there is a capacity overflow -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Decoded char code and the actual number of bytes read

-
- - - -
-
- Type -
-
- -{char: number, length: number} - - -
-
- - - - -
- - - -
-

<static> encode64(bb) → {string}

- - -
-
- - -
-

Encodes a ByteBuffer's contents to a base64 string.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bb - - -ByteBuffer - - - -

ByteBuffer

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the argument is invalid -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Base64 encoded string

-
- - - -
-
- Type -
-
- -string - - -
-
- - - - -
- - - -
-

<static> encodeUTF8Char(charCode, dst, offset) → {number}

- - -
-
- - -
-

Encodes a single UTF8 character to the specified ByteBuffer. The ByteBuffer's offsets are not modified.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
charCode - - -number - - - -

Character to encode as char code

dst - - -ByteBuffer - - - -

ByteBuffer to encode to

offset - - -number - - - -

Offset to write to

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the character cannot be encoded -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Actual number of bytes written

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

<static> extend(name, func)

- - -
-
- - -
-

Extends the ByteBuffer prototype with additional methods.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - -

Method name

func - - -Function - - - -

Prototype function

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the arguments are invalid -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - - - -
- - - -
-

<static> wrap(buffer, littleEndian) → {ByteBuffer}

- - -
-
- - -
-

Wraps an ArrayBuffer, any object containing an ArrayBuffer or a string. Sets the created ByteBuffer's offset to 0 -and its length to the wrapped objects byte length.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
buffer - - -ArrayBuffer -| - -Buffer -| - -string -| - -{array: ArrayBuffer} -| - -{buffer: ArrayBuffer} -| - -string - - - - - - - -

ArrayBuffer, any object with an .array or .buffer property or a string to wrap

littleEndian - - -boolean - - - - - - <optional>
- - - -

true to use little endian multi byte values, false for big endian. Defaults to true.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the specified object cannot be wrapped -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

<static> zigZagDecode32(n) → {number}

- - -
-
- - -
-

Decodes a zigzag encoded signed 32bit integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
n - - -number - - - -

Unsigned zigzag encoded 32bit integer

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Signed 32bit integer

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

<static> zigZagDecode64(n) → {Long}

- - -
-
- - -
-

Decodes a zigzag encoded signed 64bit integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
n - - -Long - - - -

Unsigned zigzag encoded long

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Signed long

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

<static> zigZagEncode32(n) → {number}

- - -
-
- - -
-

Encodes a signed 32bit integer so that it can be effectively used with varint encoding.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
n - - -number - - - -

Signed 32bit integer

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Unsigned zigzag encoded 32bit integer

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

<static> zigZagEncode64(n) → {Long}

- - -
-
- - -
-

Encodes a signed 64bit integer so that it can be effectively used with varint encoding.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
n - - -number -| - -Long - - - -

Signed long

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Unsigned zigzag encoded long

-
- - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

append(src, offset) → {ByteBuffer}

- - -
-
- - -
-

Appends another ByteBuffer to this one. Appends only the portion between offset and length of the specified -ByteBuffer and overwrites any contents behind the specified offset up to the number of bytes appended from -the specified ByteBuffer in this ByteBuffer. Will clone and flip the specified ByteBuffer if its offset is -larger than its length (its offsets remain untouched through cloning).

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
src - - -* - - - - - - - -

ByteBuffer or any object that can be wrapped by one to prepend

offset - - -number - - - - - - <optional>
- - - -

Offset to append behind. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the specified buffer is already destroyed -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

BE() → {ByteBuffer}

- - -
-
- - -
-

Switches to bid endian byte order.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

capacity() → {number}

- - -
-
- - -
-

Gets the capacity of the backing buffer. May be larger but not less than the contents actual length. Contents are the -bytes between offset and length, which is independent of the actual capacity.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Capacity of the backing buffer or 0 if destroyed

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

clone() → {ByteBuffer}

- - -
-
- - -
-

Clones this ByteBuffer. The returned cloned ByteBuffer shares the same ArrayBuffer but will have its own offsets.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

compact() → {ByteBuffer}

- - -
-
- - -
-

Compacts the ByteBuffer to be backed by an ArrayBuffer of its actual length. Will ByteBuffer#flip the -ByteBuffer if its offset is larger than its length. If the ByteBuffer's offset is less than its length, only the -portion between its offset and length will be contained in the compacted backing buffer. Will set offset=0 and -length=capacity. Will do nothing but flipping, if required, if already compacted.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the buffer cannot be compacted -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

copy() → {ByteBuffer}

- - -
-
- - -
-

Copies this ByteBuffer. The returned copied ByteBuffer has its own ArrayBuffer and uses the same offsets as this one.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

destroy() → {ByteBuffer}

- - -
-
- - -
-

Destroys the ByteBuffer, releasing all references to the backing array.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

ensureCapacity(capacity) → {boolean}

- - -
-
- - -
-

Makes sure that the specified capacity is available. If the current capacity is exceeded, it will be doubled. If -double the previous capacity is less than the required capacity, the required capacity will be used.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
capacity - - -number - - - -

Required capacity

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

true if actually resized, false if already that large or larger

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

flip() → {ByteBuffer}

- - -
-
- - -
-

Makes the buffer ready for a new sequence of write or relative read operations. Sets length=offset and offset=0.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

LE() → {ByteBuffer}

- - -
-
- - -
-

Switches to little endian byte order.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

mark(offset) → {ByteBuffer}

- - -
-
- - -
-

Marks the current offset in ByteBuffer#markedOffset.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to mark. Defaults to ByteBuffer#offset.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
See:
-
- -
- - - -
- - - - - -
Throws:
- - -
- If the mark cannot be set -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

prepend(src, offset) → {ByteBuffer}

- - -
-
- - -
-

Prepends another ByteBuffer to this one. Prepends only the portion between offset and length of the specified -ByteBuffer and overwrites any contents before the specified offsets up to the number of bytes prepended from -the specified ByteBuffer in this ByteBuffer. Will clone and flip the specified ByteBuffer if its offset is -larger than its length (its offsets remain untouched through cloning).

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
src - - -* - - - - - - - -

ByteBuffer or any object that can be wrapped by one to prepend

offset - - -number - - - - - - <optional>
- - - -

Offset to prepend before. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the specified buffer is already destroyed -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

printDebug(out)

- - -
-
- - -
-

Prints debug information about this ByteBuffer's contents to console.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
out - - -Function= -| - -boolean - - - -

Output function to call with the result or true to return the data as a string. -Defaults to call console.log.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
- - - -
-

readByte(offset) → {number}

- - -
-
- - -
-

Reads a byte. This is an alias of ByteBuffer#readInt8.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+1 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readCString(offset) → {string|{string: string, length: number}}

- - -
-
- - -
-

Reads a string followed by a NULL character (Uint8).

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the string cannot be decoded -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The string read if offset is omitted, else the string read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -string -| - -{string: string, length: number} - - -
-
- - - - -
- - - -
-

readDouble(offset) → {number}

- - -
-
- - -
-

Reads a double. This is an alias of ByteBuffer#readFloat64.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+8 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readFloat(offset) → {number}

- - -
-
- - -
-

Reads a float. This is an alias of ByteBuffer#readFloat32.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+4 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readFloat32(offset) → {number}

- - -
-
- - -
-

Reads a 32bit float.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+4 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readFloat64(offset) → {number}

- - -
-
- - -
-

Reads a 64bit float.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+8 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readInt(offset) → {number}

- - -
-
- - -
-

Reads an integer. This is an alias of ByteBuffer#readInt32.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+4 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readInt8(offset) → {number}

- - -
-
- - -
-

Reads an 8bit singed integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+1 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readInt16(offset) → {number}

- - -
-
- - -
-

Reads a 16bit signed integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+2 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readInt32(offset) → {number}

- - -
-
- - -
-

Reads a 32bit signed integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+4 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readInt64(offset) → {Long}

- - -
-
- - -
-

Reads a 64bit integer. Utilizes Long.js to construct a new Long from the low and high 32 bits.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+8 is larger than the capacity or long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

readJSON(offset, parse) → {*|{data: *, length: number}}

- - -
-
- - -
-

Reads a JSON payload and unserializes it.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

parse - - -function - - - - - - <optional>
- - - -

Parse implementation to use. Defaults to JSON.parse.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the data cannot be decoded -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Data payload if offset is omitted, else the data payload and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -* -| - -{data: *, length: number} - - -
-
- - - - -
- - - -
-

readLong(offset) → {ByteBuffer.Long}

- - -
-
- - -
-

Reads a long. This is an alias of ByteBuffer#readInt64.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+8 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -ByteBuffer.Long - - -
-
- - - - -
- - - -
-

readLString(offset) → {string|{string: string, length: number}}

- - -
-
- - -
-

Reads a string with a prepended number of characters, which is also encoded as an UTF8 character.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the string cannot be decoded -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The string read if offset is omitted, else the string read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -string -| - -{string: string, length: number} - - -
-
- - - - -
- - - -
-

readShort(offset) → {number}

- - -
-
- - -
-

Reads a short value. This is an alias of ByteBuffer#readInt16.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+2 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readUint8(offset) → {number}

- - -
-
- - -
-

Reads an 8bit unsinged integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+1 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readUint16(offset) → {number}

- - -
-
- - -
-

Reads a 16bit unsigned integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+2 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readUint32(offset) → {number}

- - -
-
- - -
-

Reads a 32bit unsigned integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+4 is larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

readUint64(offset) → {Long}

- - -
-
- - -
-

Reads a 64bit unsigned integer. Utilizes Long.js to construct a new Long from the low and high 32 bits.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If offset+8 is larger than the capacity or long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -Long - - -
-
- - - - -
- - - -
-

readUTF8String(chars, offset) → {string|{string: string, length: number}}

- - -
-
- - -
-

Reads an UTF8 string.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
chars - - -number - - - - - - - -

Number of characters to read

offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the string cannot be decoded -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The string read if offset is omitted, else the string read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -string -| - -{string: string, length: number} - - -
-
- - - - -
- - - -
-

readUTF8StringBytes(length, offset) → {string|{string: string, length: number}}

- - -
-
- - -
-

Reads an UTF8 string with the specified byte length.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
length - - -number - - - - - - - -

Byte length

offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the length did not match or the string cannot be decoded -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The string read if offset is omitted, else the string read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -string -| - -{string: string, length: number} - - -
-
- - - - -
- - - -
-

readVarint(offset) → {number|{value: number, length: number}}

- - -
-
- - -
-

Reads a base 128 variable-length integer as used in protobuf. This is an alias of ByteBuffer#readVarint32.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

The value read if offset is omitted, else the value read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -number -| - -{value: number, length: number} - - -
-
- - - - -
- - - -
-

readVarint32(offset) → {number|{value: number, length: number}}

- - -
-
- - -
-

Reads a 32bit base 128 variable-length integer as used in protobuf.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If it's not a valid varint -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The value read if offset is omitted, else the value read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -number -| - -{value: number, length: number} - - -
-
- - - - -
- - - -
-

readVarint64(offset) → {Long|{value: Long, length: number}}

- - -
-
- - -
-

Reads a 32bit base 128 variable-length integer as used in protobuf.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If it's not a valid varint or long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The value read if offset is omitted, else the value read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -Long -| - -{value: Long, length: number} - - -
-
- - - - -
- - - -
-

readVString(offset) → {string|{string: string, length: number}}

- - -
-
- - -
-

Reads a string with a prepended number of characters, which is encoded as a 32bit base 128 variable-length integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the string cannot be decoded or the delimiter is not a valid varint -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The string read if offset is omitted, else the string read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -string -| - -{string: string, length: number} - - -
-
- - - - -
- - - -
-

readZigZagVarint(offset) → {number|{value: number, length: number}}

- - -
-
- - -
-

Reads a zigzag encoded base 128 variable-length integer as used in protobuf. This is an alias of ByteBuffer#readZigZagVarint32.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If it's not a valid varint -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The value read if offset is omitted, else the value read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -number -| - -{value: number, length: number} - - -
-
- - - - -
- - - -
-

readZigZagVarint32(offset) → {number|{value: number, length: number}}

- - -
-
- - -
-

Reads a zigzag encoded 32bit base 128 variable-length integer as used in protobuf.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If it's not a valid varint -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The value read if offset is omitted, else the value read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -number -| - -{value: number, length: number} - - -
-
- - - - -
- - - -
-

readZigZagVarint64(offset) → {Long|{value: Long, length: number}}

- - -
-
- - -
-

Reads a zigzag encoded 64bit base 128 variable-length integer as used in protobuf.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
offset - - -number - - - - - - <optional>
- - - -

Offset to read from. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If it's not a valid varint or long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

The value read if offset is omitted, else the value read and the actual number of bytes read.

-
- - - -
-
- Type -
-
- -Long -| - -{value: Long, length: number} - - -
-
- - - - -
- - - -
-

remaining() → {number}

- - -
-
- - -
-

Gets the number of remaining readable bytes. Contents are the bytes between offset and length, so this returns -length-offset.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Remaining readable bytes (may be negative if offset is larger than length)

-
- - - -
-
- Type -
-
- -number - - -
-
- - - - -
- - - -
-

reset() → {ByteBuffer}

- - -
-
- - -
-

Resets the ByteBuffer. If an offset has been marked through ByteBuffer#mark before, the offset will be -set to the marked offset and the marked offset will be discarded. Length will not be altered. If there is no -marked offset, sets offset=0 and length=0.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
See:
-
- -
- - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

resize(capacity) → {boolean}

- - -
-
- - -
-

Resizes the ByteBuffer to the given capacity.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
capacity - - -number - - - -

New capacity

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

true if actually resized, false if already that large or larger

-
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - -
- - - -
-

reverse() → {ByteBuffer}

- - -
-
- - -
-

Reverses the underlying back buffer and adapts offset and length to retain the same relative position on the -reversed data in inverse order. Example: "00<01 02>03 04".reverse() = "04 03<02 01>00".

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the buffer is already destroyed -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

slice(begin, end) → {ByteBuffer}

- - -
-
- - -
-

Slices the ByteBuffer. This is independent of the ByteBuffer's actual offsets. Does not compact the underlying -ArrayBuffer (use ByteBuffer#compact and maybe ByteBuffer.wrap instead).

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
begin - - -number - - - -

Begin offset

end - - -number - - - -

End offset

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the buffer cannot be sliced -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Clone of this ByteBuffer with the specified slicing applied, backed by the same ArrayBuffer

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

sliceAndCompact(begin, end) → {ByteBuffer}

- - -
-
- - -
-

Slices and compacts the ByteBuffer. The resulting ByteBuffer will have its own ArrayBuffer with the compacted contents -of this ByteBuffer's contents.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
begin - - -number - - - -

Begin offset

end - - -number - - - -

End offset

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the buffer cannot be sliced -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

toArrayBuffer(forceCopy) → {ArrayBuffer}

- - -
-
- - -
-

Returns an ArrayBuffer compacted to contain this ByteBuffer's actual contents. Will implicitly -ByteBuffer#flip the ByteBuffer if its offset is larger than its length. Will return a reference to -the unmodified backing buffer if offset=0 and length=capacity unless forceCopy is set to true.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
forceCopy - - -boolean - - - - - - <optional>
- - - -

Forces the creation of a copy if set to true. Defaults to false.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Compacted ArrayBuffer

-
- - - -
-
- Type -
-
- -ArrayBuffer - - -
-
- - - - -
- - - -
-

toASCII(wrap, asArray) → {string|Array.<string>}

- - -
-
- - -
-

Returns an ASCII representation of this ByteBuffer's contents. Beware: May be large.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
wrap - - -number - - - - - - <optional>
- - - -

Wrap length. Defaults to 16.

asArray - - -boolean - - - - - - <optional>
- - - -

Set to true to return an array of lines. Defaults to false.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

ASCII representation as of "abcdef..." (33-126, else ".", no marked offsets)

-
- - - -
-
- Type -
-
- -string -| - -Array.<string> - - -
-
- - - - -
- - - -
-

toBase64() → {string}

- - -
-
- - -
-

Returns the base64 encoded representation of the buffer's contents.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Base 64 encoded string

-
- - - -
-
- Type -
-
- -string - - -
-
- - - - -
- - - -
-

toBuffer() → {Buffer}

- - -
-
- - -
-

Returns a node Buffer compacted to contain this ByteBuffer's actual contents. Will implicitly -ByteBuffer#flip the ByteBuffer if its offset is larger than its length. Will also copy all data (not -a reference).

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If not running inside of node -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

Compacted Buffer

-
- - - -
-
- Type -
-
- -Buffer - - -
-
- - - - -
- - - -
-

toHex(wrap, asArray) → {string|Array.<string>}

- - -
-
- - -
-

Returns a hex representation of this ByteBuffer's contents. Beware: May be large.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
wrap - - -number - - - - - - <optional>
- - - -

Wrap length. Defaults to 16.

asArray - - -boolean - - - - - - <optional>
- - - -

Set to true to return an array of lines. Defaults to false.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

Hex representation as of " 00<01 02>03..." with marked offsets

-
- - - -
-
- Type -
-
- -string -| - -Array.<string> - - -
-
- - - - -
- - - -
-

toString(enc) → {string}

- - -
-
- - -
-

Returns a string representation.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
enc - - -string - - - - - - <optional>
- - - -

Output encoding. Returns a pretty printed debug table by default but also allows direct - conversion to "utf8" and "base64" encoding.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

String representation

-
- - - -
-
- Type -
-
- -string - - -
-
- - - - -
- - - -
-

toUTF8() → {string}

- - -
-
- - -
-

Returns the contents of the buffer as an UTF8 encoded string.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -string - - -
-
- - - - -
- - - -
-

writeByte(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a byte. This is an alias of {ByteBuffer#writeInt8}.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeCString(str, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a string followed by a NULL character (Uint8). Beware: The source string must not contain NULL characters -unless this is actually intended. This is not checked. If you have the option it is recommended to use -ByteBuffer#writeLString or ByteBuffer#writeVString with the corresponding reading methods instead.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
str - - -string - - - - - - - -

String to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeDouble(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a double. This is an alias of ByteBuffer#writeFloat64.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeFloat(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a float. This is an alias of ByteBuffer#writeFloat32.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeFloat32(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a 32bit float.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeFloat64(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a 64bit float.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeInt(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes an integer. This is an alias of ByteBuffer#writeInt32.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeInt8(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes an 8bit singed integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeInt16(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a 16bit signed integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeInt32(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a 32bit signed integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeInt64(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a 64bit integer. Utilizes Long.js to write the low and high 32 bits separately.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number -| - -Long - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeJSON(data, offset, stringify) → {ByteBuffer|number}

- - -
-
- - -
-

Serializes and writes a JSON payload.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
data - - -* - - - - - - - -

Data payload to serialize

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted,

stringify - - -function - - - - - - <optional>
- - - -

Stringify implementation to use. Defaults to JSON.stringify.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number if bytes written,

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeLong(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a long. This is an alias of ByteBuffer#writeInt64.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number -| - -ByteBuffer.Long - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeLString(str, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a string with prepended number of characters, which is also encoded as an UTF8 character..

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
str - - -string - - - - - - - -

String to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeShort(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a short value. This is an alias of ByteBuffer#writeInt16.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeUint8(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes an 8bit unsinged integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If the offset is equal to or larger than the capacity -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeUint16(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a 16bit unsigned integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeUint32(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a 32bit unsigned integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeUint64(value, offset) → {ByteBuffer}

- - -
-
- - -
-

Writes a 64bit unsigned integer. Utilizes Long.js to write the low and high 32 bits separately.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number -| - -Long - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this

-
- - - -
-
- Type -
-
- -ByteBuffer - - -
-
- - - - -
- - - -
-

writeUTF8String(str, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes an UTF8 string.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
str - - -string - - - - - - - -

String to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeVarint(value, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a base 128 variable-length integer as used in protobuf. This is an alias of ByteBuffer#writeVarint32.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeVarint32(value, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a 32bit base 128 variable-length integer as used in protobuf.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeVarint64(value, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a 64bit base 128 variable-length integer as used in protobuf.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number -| - -Long - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeVString(str, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a string with prepended number of characters, which is encoded as a 32bit base 128 variable-length integer.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
str - - -string - - - - - - - -

String to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeZigZagVarint(value, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a zigzag encoded base 128 encoded variable-length integer as used in protobuf. This is an alias of ByteBuffer#writeZigZagVarint32.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeZigZagVarint32(value, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a zigzag encoded 32bit base 128 encoded variable-length integer as used in protobuf.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- - - -
-

writeZigZagVarint64(value, offset) → {ByteBuffer|number}

- - -
-
- - -
-

Writes a zigzag encoded 64bit base 128 encoded variable-length integer as used in protobuf.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
value - - -number - - - - - - - -

Value to write

offset - - -number - - - - - - <optional>
- - - -

Offset to write to. Defaults to ByteBuffer#offset which will be modified only if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
Throws:
- - -
- If long support is not available -
- - - -
-
- Type -
-
- -Error - - -
-
- - - - -
Returns:
- - -
-

this if offset is omitted, else the actual number of bytes written.

-
- - - -
-
- Type -
-
- -ByteBuffer -| - -number - - -
-
- - - - -
- -
- - - - - -
- -
- - - - -
- - - -
- - - - diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index d25fb36..0000000 --- a/docs/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - Index - - - - - - - - - - -
- -

Index

- - - - - - - -

- - - - - - - - - - - - - - - - - - - -
- - - -
- - - - diff --git a/docs/scripts/html5.js b/docs/scripts/html5.js deleted file mode 100644 index 087417a..0000000 --- a/docs/scripts/html5.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed - Uncompressed source: https://github.com/aFarkas/html5shiv -*/ -(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); -a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; -c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| -"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); -for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/docs/scripts/prettify/prettify.js b/docs/scripts/prettify/prettify.js deleted file mode 100644 index eef5ad7..0000000 --- a/docs/scripts/prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p} + */ +ByteBuffer.prototype.readBitSet = function(offset) {}; + +/** + * @param {Array} value + * @param {number=} offset + * @returns {!ByteBuffer} + */ +ByteBuffer.prototype.writeBitSet = function(value, offset) {}; + +/** + * @param {number=} wrap + * @returns {string} * @nosideeffects */ +ByteBuffer.prototype.toColumns = function(wrap) {}; + +/** + * @param {function(string)=} out + */ ByteBuffer.prototype.printDebug = function(out) {}; /** - * @param {number=} wrap - * @param {boolean=} asArray - * @return {string|!Array.} + * @param {boolean=} debug + * @returns {string} * @nosideeffects */ -ByteBuffer.prototype.toHex = function(wrap, asArray) {}; +ByteBuffer.prototype.toHex = function(debug) {}; /** - * @param {number=} wrap - * @param {boolean=} asArray - * @return {string|!Array.} + * @returns {string} * @nosideeffects */ -ByteBuffer.prototype.toASCII = function(wrap, asArray) {}; +ByteBuffer.prototype.toBinary = function() {}; /** - * @return {string} + * @returns {string} * @nosideeffects */ ByteBuffer.prototype.toUTF8 = function() {}; /** - * @return {string} + * @returns {string} * @nosideeffects */ ByteBuffer.prototype.toBase64 = function() {}; /** * @param {string=} enc - * @return {string} + * @returns {string} * @nosideeffects */ ByteBuffer.prototype.toString = function(enc) {}; /** * @param {boolean=} forceCopy - * @return {ArrayBuffer} + * @returns {ArrayBuffer} * @nosideeffects */ ByteBuffer.prototype.toArrayBuffer = function(forceCopy) {}; @@ -726,7 +767,7 @@ ByteBuffer.prototype.toArrayBuffer = function(forceCopy) {}; /** * @param {!ByteBuffer} src * @param {number} offset - * @return {!{char: number, length: number}} + * @returns {!{char: number, length: number}} * @nosideeffects */ ByteBuffer.decodeUTF8Char = function(src, offset) {}; @@ -735,14 +776,14 @@ ByteBuffer.decodeUTF8Char = function(src, offset) {}; * @param {number} charCode * @param {!ByteBuffer} dst * @param {number} offset - * @return {number} + * @returns {number} * @throws {Error} */ ByteBuffer.encodeUTF8Char = function(charCode, dst, offset) {}; /** * @param {number} charCode - * @return {number} + * @returns {number} * @throws {Error} * @nosideeffects */ @@ -750,21 +791,21 @@ ByteBuffer.calculateUTF8Char = function(charCode) {}; /** * @param {number} n - * @return {number} + * @returns {number} * @nosideeffects */ ByteBuffer.zigZagEncode32 = function(n) {}; /** * @param {number} n - * @return {number} + * @returns {number} * @nosideeffects */ ByteBuffer.zigZagDecode32 = function(n) {}; /** - * @param {ByteBuffer} bb - * @return {string} + * @param {!ByteBuffer} bb + * @returns {string} * @throws {Error} * @nosideeffects */ @@ -772,11 +813,46 @@ ByteBuffer.encode64 = function(bb) {}; /** * @param {string} str - * @return {!ByteBuffer} + * @param {boolean=} littleEndian + * @returns {!ByteBuffer} + * @throws {Error} + * @nosideeffects + */ +ByteBuffer.decode64 = function(str, littleEndian) {}; + +/** + * @param {!ByteBuffer} bb + * @returns {string} + * @throws {Error} + * @nosideeffects + */ +ByteBuffer.encodeHex = function(bb) {}; + +/** + * @param {string} str + * @param {boolean=} littleEndian + * @returns {!ByteBuffer} + * @throws {Error} + * @nosideeffects + */ +ByteBuffer.decodeHex = function(str, littleEndian) {}; + +/** + * @param {!ByteBuffer} bb + * @returns {string} + * @throws {Error} + * @nosideeffects + */ +ByteBuffer.encodeBinary = function(bb) {}; + +/** + * @param {string} str + * @param {boolean=} littleEndian + * @returns {!ByteBuffer} * @throws {Error} * @nosideeffects */ -ByteBuffer.decode64 = function(str) {}; +ByteBuffer.decodeBinary = function(str, littleEndian) {}; /** * @type {number} diff --git a/externs/minimal-env.js b/externs/minimal-env.js new file mode 100644 index 0000000..d637a63 --- /dev/null +++ b/externs/minimal-env.js @@ -0,0 +1,52 @@ +/** + * @param {string} moduleName + * @returns {?} + */ +function require(moduleName) {}; + +/** + * @param {string} name + * @param {Array.} deps + * @param {function(...[*])} f + */ +function define(name, deps, f) {}; + +/** + * @param {number} size + * @constructor + * @extends Array + */ +function Buffer(size) {}; + +/** + * @param {*} buf + * @return {boolean} + */ +Buffer.isBuffer = function(buf) {}; + +/** + * @type {Object.} + */ +var console = {}; + +/** + * @param {string} s + */ +console.log = function(s) {}; + +/** + * @type {*} + */ +var module = {}; + +/** + * @param {...*} var_args + * @returns {string} + */ +String.fromCodePoint = function(var_args) {}; + +/** + * @param {number} offset + * @returns {number} + */ +String.prototype.codePointAt = function(offset) {}; diff --git a/externs/minimal-node-env.js b/externs/minimal-node-env.js deleted file mode 100644 index e12e5a9..0000000 --- a/externs/minimal-node-env.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @param {string} moduleName - * @returns {?} - */ -var require = function(moduleName) {}; - -/** - * @param {number} size - * @constructor - * @extends Array - */ -var Buffer = function(size) {}; - -/** - * @param {*} buf - * @return {boolean} - */ -Buffer.isBuffer = function(buf) {}; diff --git a/index.js b/index.js new file mode 100644 index 0000000..cf99dc9 --- /dev/null +++ b/index.js @@ -0,0 +1 @@ +module.exports = require("./dist/bytebuffer-node.js"); diff --git a/jsdoc.json b/jsdoc.json index 84c209e..856a2ab 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -3,7 +3,7 @@ "allowUnknownTags": true }, "source": { - "include": ["ByteBuffer.js"] + "include": ["dist/ByteBufferAB.js"] }, "opts": { "template": "templates/esoccer", diff --git a/package.json b/package.json index 5e50327..0a22299 100644 --- a/package.json +++ b/package.json @@ -1,37 +1,51 @@ { - "name": "bytebuffer", - "version": "1.6.1", - "author": "Daniel Wirtz ", - "description": "ByteBuffer.js: A Java-like, Netty-inspired ByteBuffer implementation using typed arrays.", - "main": "ByteBuffer.js", - "repository": { - "type": "git", - "url": "https://github.com/dcodeIO/ByteBuffer.js.git" - }, - "bugs": { - "url": "https://github.com/dcodeIO/ByteBuffer.js/issues" - }, - "keywords": ["net", "array", "buffer", "arraybuffer", "typed array", "bytebuffer", "json", "websocket", "webrtc"], - "dependencies": { - "long": "latest" - }, - "devDependencies": { - "testjs": "latest", - "preprocessor": "latest", - "closurecompiler": "latest" - }, - "license": "Apache-2.0", - "engines": { - "node": ">=0.6" - }, - "scripts": { - "prepublish": "npm test", - "test": "node node_modules/testjs/bin/testjs tests/suite.js", - - "make": "npm run-script build && npm run-script compile && npm run-script noexpose && npm test && npm run-script jsdoc", - "build": "preprocess src/ByteBuffer.js src/ > ByteBuffer.js", - "compile": "ccjs ByteBuffer.js --create_source_map=ByteBuffer.min.map --compilation_level=ADVANCED_OPTIMIZATIONS --externs=externs/Long.js > ByteBuffer.min.js", - "noexpose": "cat ByteBuffer.js | grep -v @expose > ByteBuffer.noexpose.js", - "jsdoc": "jsdoc -c jsdoc.json" - } + "name": "bytebuffer", + "version": "5.0.1", + "author": "Daniel Wirtz ", + "description": "The swiss army knife for binary data in JavaScript.", + "main": "dist/bytebuffer-node.js", + "browser": "dist/bytebuffer.js", + "repository": { + "type": "git", + "url": "https://github.com/dcodeIO/bytebuffer.js.git" + }, + "bugs": { + "url": "https://github.com/dcodeIO/bytebuffer.js/issues" + }, + "keywords": [ + "net", + "array", + "buffer", + "arraybuffer", + "typed array", + "bytebuffer", + "json", + "websocket", + "webrtc" + ], + "dependencies": { + "long": "~3" + }, + "devDependencies": { + "closurecompiler": "~1", + "lxiv": "~0.2", + "metascript": "~0", + "pretty-hrtime": "^1.0.0", + "testjs": "~1", + "utfx": "^1.0.1" + }, + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + }, + "scripts": { + "prepublish": "npm test", + "test": "node node_modules/testjs/bin/testjs tests/suite.js", + "make": "npm run-script build && npm run-script compile && npm run-script compress && npm test", + "build": "node scripts/build.js", + "compile": "npm run-script compile-default && npm run-script compile-dataview", + "compile-default": "ccjs dist/bytebuffer.js --create_source_map=dist/bytebuffer.min.map --externs=externs/minimal-env.js --externs=node_modules/long/externs/long.js > dist/bytebuffer.min.js", + "compile-dataview": "ccjs dist/bytebuffer-dataview.js --create_source_map=dist/bytebuffer-dataview.min.map --externs=externs/minimal-env.js --externs=node_modules/long/externs/long.js > dist/bytebuffer-dataview.min.js", + "compress": "gzip -c -9 dist/bytebuffer.min.js > dist/bytebuffer.min.js.gz && gzip -c -9 dist/bytebuffer-dataview.min.js > dist/bytebuffer-dataview.min.js.gz" + } } diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 0000000..3b6fb94 --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,113 @@ +/* + Copyright 2013 Daniel Wirtz + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +var MetaScript = require("metascript"), + path = require("path"), + fs = require("fs"); + +var rootDir = path.join(__dirname, ".."), + srcDir = path.join(__dirname, "..", "src"), + distDir = path.join(__dirname, "..", "dist"), + pkg = require(path.join(rootDir, "package.json")), + filename; + +var scope = { + VERSION : pkg.version, // Version + + // Encodings + + ENCODINGS : true, // Include encodings in general (catches all) + BASE64 : true, // Include base64 encoding + BINARY : true, // Include binary encoding + DEBUG : true, // Include debug encoding + HEX : true, // Include hex encoding + UTF8 : true, // Include utf8 encoding (required for STRINGS) + + // Primitive types + + BYTES : true, // Include bytes + INTS : true, // Include int types in general (catches all) + INT8 : true, // Include int8/uint8 + INT16 : true, // Include int16/uint16 + INT32 : true, // Include int32/uint32 + INT64 : true, // Include int64/uint64 with Long.js + + FLOATS : true, // Include float types in general (catches all) + FLOAT32 : true, // Include float32 + FLOAT64 : true, // Include float64 + + // Varint encoding + + VARINTS : true, // Include varint encoding in general (catches all) + VARINT32 : true, // Include varint32/zigZagVarint32 + VARINT64 : true, // Include varint64/zigZagVarint32 with Long.js + + // String support + + STRINGS : true, // Include string support in general (catches all) + UTF8STRING : true, // Include UTF8 encoded strings + CSTRING : true, // Include C-like null terminated strings + VSTRING : true, // Include varint32 length prefixed strings + ISTRING : true, // Include uint32 length prefixed strings + + // Other + + ALIASES : true, // Include aliases like writeByte, writeShort .. + INLINE : true, // Inline any assertion code + VERBOSE_MS : false // Include MetaScript details as comments +}; + +// Optimize for size : INLINE=false, ALIASES=false, VERBOSE_MS=false, WHATEVERYOUDONTNEED=false +// Optimize for speed : INLINE=true + +if (!scope.UTF8) scope.STRINGS = false; + +// Build node version using Buffers +scope.NODE = true; +console.log("Building bytebuffer-node with scope", JSON.stringify(scope, null, 2)); +fs.writeFileSync( + path.join(distDir, "bytebuffer-node.js"), + MetaScript.transform(fs.readFileSync(filename = path.join(srcDir, "wrap-node.js")), filename, scope, srcDir) +); + +// Build browser version using Typed Arrays +scope.NODE = false; +scope.DATAVIEW = false; +delete scope.BUFFERVIEW; +console.log("Building bytebuffer.js with scope", JSON.stringify(scope, null, 2)); +fs.writeFileSync( + path.join(distDir, "bytebuffer.js"), + MetaScript.transform(fs.readFileSync(filename = path.join(srcDir, "wrap.js")), filename, scope) +); + +// Build alternative browser version using a DataView +scope.NODE = false; +scope.DATAVIEW = true; +console.log("Building bytebuffer-dataview with scope", JSON.stringify(scope, null, 2)); +fs.writeFileSync( + path.join(distDir, "bytebuffer-dataview.js"), + MetaScript.transform(fs.readFileSync(filename = path.join(srcDir, "wrap.js")), filename, scope) +); + +// Update bower.json +scope = { VERSION: pkg.version }; +console.log("Updating bower.json with scope", JSON.stringify(scope, null, 2)); +fs.writeFileSync( + path.join(rootDir, "bower.json"), + MetaScript.transform(fs.readFileSync(filename = path.join(srcDir, "bower.json")), filename, scope, srcDir) +); + +console.log("Done"); diff --git a/src/ByteBuffer.js b/src/ByteBuffer.js deleted file mode 100644 index c28ff30..0000000 --- a/src/ByteBuffer.js +++ /dev/null @@ -1,2143 +0,0 @@ -/* - Copyright 2013 Daniel Wirtz - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/** - * @license ByteBuffer.js (c) 2013 Daniel Wirtz - * Released under the Apache License, Version 2.0 - * see: https://github.com/dcodeIO/ByteBuffer.js for details - */ -(function(global) { - "use strict"; - - // Note that this library carefully avoids using the array access operator - // (i.e. buffer[x]) on ArrayBufferView subclasses (e.g. Uint8Array), and - // uses DataView instead. This is required for IE 8 compatibility. - - function loadByteBuffer(Long) { - - // Support node's Buffer if available, http://nodejs.org/api/buffer.html - var Buffer = null; - if (typeof require === 'function') { - try { - var nodeBuffer = require("buffer"); - Buffer = nodeBuffer && typeof nodeBuffer['Buffer'] === 'function' && typeof nodeBuffer['Buffer']['isBuffer'] === 'function' - ? nodeBuffer['Buffer'] : null; - } catch (e) {} - } - - /** - * Constructs a new ByteBuffer. - * @exports ByteBuffer - * @class Provides a Java-like, Netty-inspired ByteBuffer implementation using typed arrays. It also tries to - * abstract a bit of the complexity away by providing convenience methods for those who just want to write stuff - * without caring about signed, unsigned and the actual bit sizes. - * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to false. - * @constructor - * @expose - */ - var ByteBuffer = function(capacity, littleEndian) { - - capacity = typeof capacity !== 'undefined' ? parseInt(capacity, 10) : ByteBuffer.DEFAULT_CAPACITY; - if (capacity < 1) capacity = ByteBuffer.DEFAULT_CAPACITY; - - /** - * Underlying ArrayBuffer. - * @type {ArrayBuffer} - * @expose - */ - this.array = arguments.length == 3 && arguments[2] === true ? null : new ArrayBuffer(capacity); - - /** - * DataView to mess with the ArrayBuffer. - * @type {DataView} - * @expose - */ - this.view = this.array != null ? new DataView(this.array) : null; - /** - * Current read/write offset. Length- and capacity-independent index. Contents are the bytes between offset and - * length, which are both absolute indexes. There is no capacity property, use {@link ByteBuffer#capacity} - * instead. - * @type {number} - * @expose - */ - this.offset = 0; - - /** - * Marked offset set through {@link ByteBuffer#mark}. Evaluates to -1 if there is no marked offset. - * @type {number} - * @expose - */ - this.markedOffset = -1; - - /** - * Length of the contained data. Offset- and capacity-independent index. Contents are the bytes between offset and - * length, which are both absolute indexes. There is no capacity property, use {@link ByteBuffer#capacity} - * instead. - * @type {number} - * @expose - */ - this.length = 0; - - /** - * Whether to use little endian multi byte values. - * @type {boolean} - * @expose - */ - this.littleEndian = typeof littleEndian != 'undefined' ? !!littleEndian : false; - }; - - /** - * Default buffer capacity of 16 if nothing else is stated. The ByteBuffer will be automatically resized by a factor - * of 2 if required. - * @type {number} - * @const - * @expose - */ - ByteBuffer.DEFAULT_CAPACITY = 16; - - /** - * Little endian constant for usage in constructors instead of a boolean value. Evaluates to true. - * @type {boolean} - * @const - * @expose - */ - ByteBuffer.LITTLE_ENDIAN = true; - - /** - * Big endian constant for usage in constructors instead of a boolean value. Evaluates to false. - * @type {boolean} - * @const - * @expose - */ - ByteBuffer.BIG_ENDIAN = false; - - /** - * Long class for int64 support. May be undefined if the Long class has not been loaded and int64 support is - * not available. - * @type {?Long} - * @const - * @expose - */ - ByteBuffer.Long = Long; - - /** - * Allocates a new ByteBuffer. - * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to true. - * @return {ByteBuffer} - * @expose - */ - ByteBuffer.allocate = function(capacity, littleEndian) { - return new ByteBuffer(capacity, littleEndian); - }; - - /** - * Converts a node.js <= 0.8 Buffer to an ArrayBuffer. - * @param {Buffer} buffer Buffer to convert - * @return {ArrayBuffer} Converted buffer - * @private - */ - function toArrayBuffer(buffer) { - var ab = new ArrayBuffer(buffer.length); - var view = new Uint8Array(ab); - for (var i = 0; i < buffer.length; ++i) { - view[i] = buffer[i]; - } - return ab; - } - - /** - * Wraps an ArrayBuffer, any object containing an ArrayBuffer or a string. Sets the created ByteBuffer's offset to 0 - * and its length to the wrapped objects byte length. - * @param {ArrayBuffer|Buffer|string|{array: ArrayBuffer}|{buffer: ArrayBuffer}|string} buffer ArrayBuffer, any object with an .array or .buffer property or a string to wrap - * @param {boolean=} littleEndian true to use little endian multi byte values, false for big endian. Defaults to true. - * @return {ByteBuffer} - * @throws {Error} If the specified object cannot be wrapped - * @expose - */ - ByteBuffer.wrap = function(buffer, littleEndian) { - // Wrap a string - if (typeof buffer === 'string') { - return new ByteBuffer().writeUTF8String(buffer).flip(); - } - var b; - // Wrap Buffer - if (Buffer && Buffer.isBuffer(buffer)) { - b = new Uint8Array(buffer).buffer; // noop on node <= 0.8 - buffer = (b === buffer) ? toArrayBuffer(buffer) : b; - } - // Refuse to wrap anything that's null or not an object - if (buffer === null || typeof buffer !== 'object') { - throw(new Error("Cannot wrap null or non-object")); - } - // Wrap ByteBuffer by cloning (preserve offsets) - if (buffer instanceof ByteBuffer) { - return buffer.clone(); - } - // Wrap any object that is or contains an ArrayBuffer - if (!!buffer["array"]) { - buffer = buffer["array"]; - } else if (!!buffer["buffer"]) { - buffer = buffer["buffer"]; - } - if (!(buffer instanceof ArrayBuffer)) { - throw(new Error("Cannot wrap buffer of type "+typeof(buffer)+", "+buffer.constructor.name)); - } - b = new ByteBuffer(0, littleEndian, /* shadow copy */ true); - b.array = buffer; - b.view = new DataView(b.array); - b.offset = 0; - b.length = buffer.byteLength; - return b; - }; - - /** - * Switches to little endian byte order. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.LE = function() { - this.littleEndian = true; - return this; - }; - - /** - * Switches to bid endian byte order. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.BE = function() { - this.littleEndian = false; - return this; - }; - - /** - * Resizes the ByteBuffer to the given capacity. - * @param {number} capacity New capacity - * @return {boolean} true if actually resized, false if already that large or larger - * @expose - */ - ByteBuffer.prototype.resize = function(capacity) { - if (capacity < 1) return false; - if (this.array == null) { // Silently recreate - this.array = new ArrayBuffer(capacity); - this.view = new DataView(this.array); - } - if (this.array.byteLength < capacity) { - var src = this.array; - var srcView = new Uint8Array(src); - var dst = new ArrayBuffer(capacity); - var dstView = new Uint8Array(dst); - dstView.set(srcView); - this.array = dst; - this.view = new DataView(dst); - return true; - } - return false; - }; - - /** - * Slices the ByteBuffer. This is independent of the ByteBuffer's actual offsets. Does not compact the underlying - * ArrayBuffer (use {@link ByteBuffer#compact} and maybe {@link ByteBuffer.wrap} instead). - * @param {number} begin Begin offset - * @param {number} end End offset - * @return {ByteBuffer} Clone of this ByteBuffer with the specified slicing applied, backed by the same ArrayBuffer - * @throws {Error} If the buffer cannot be sliced - * @expose - */ - ByteBuffer.prototype.slice = function(begin, end) { - if (this.array == null) { - throw(new Error(this+" cannot be sliced: Already destroyed")); - } - if (end <= begin) { - throw(new Error(this+" cannot be sliced: End ("+end+") is less than begin ("+begin+")")); - } - if (begin < 0 || begin > this.array.byteLength || end < 1 || end > this.array.byteLength) { - throw(new Error(this+" cannot be sliced: Index out of bounds (0-"+this.array.byteLength+" -> "+begin+"-"+end+")")); - } - var b = this.clone(); - b.offset = begin; - b.length = end; - return b; - }; - - /** - * Slices and compacts the ByteBuffer. The resulting ByteBuffer will have its own ArrayBuffer with the compacted contents - * of this ByteBuffer's contents. - * @param {number} begin Begin offset - * @param {number} end End offset - * @return {ByteBuffer} - * @throws {Error} If the buffer cannot be sliced - * @expose - */ - ByteBuffer.prototype.sliceAndCompact = function(begin, end) { - return ByteBuffer.wrap(this.slice(begin,end).toArrayBuffer(true)); - }; - - /** - * Makes sure that the specified capacity is available. If the current capacity is exceeded, it will be doubled. If - * double the previous capacity is less than the required capacity, the required capacity will be used. - * @param {number} capacity Required capacity - * @return {boolean} true if actually resized, false if already that large or larger - * @expose - */ - ByteBuffer.prototype.ensureCapacity = function(capacity) { - if (this.array == null) { - return this.resize(capacity); - } - if (this.array.byteLength < capacity) return this.resize(this.array.byteLength*2 >= capacity ? this.array.byteLength*2 : capacity); - return false; - }; - - /** - * Makes the buffer ready for a new sequence of write or relative read operations. Sets length=offset and offset=0. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.flip = function() { - this.length = this.array == null ? 0 : this.offset; - this.offset = 0; - return this; - }; - - /** - * Marks the current offset in {@link ByteBuffer#markedOffset}. - * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}. - * @return {ByteBuffer} this - * @throws {Error} If the mark cannot be set - * @see ByteBuffer#reset - * @expose - */ - ByteBuffer.prototype.mark = function(offset) { - if (this.array == null) { - throw(new Error(this+" cannot be marked: Already destroyed")); - } - offset = typeof offset !== 'undefined' ? parseInt(offset, 10) : this.offset; - if (offset < 0 || offset > this.array.byteLength) { - throw(new Error(this+" cannot be marked: Offset to mark is less than 0 or bigger than the capacity ("+this.array.byteLength+"): "+offset)); - } - this.markedOffset = offset; - return this; - }; - - /** - * Resets the ByteBuffer. If an offset has been marked through {@link ByteBuffer#mark} before, the offset will be - * set to the marked offset and the marked offset will be discarded. Length will not be altered. If there is no - * marked offset, sets offset=0 and length=0. - * @return {ByteBuffer} this - * @see ByteBuffer#mark - * @expose - */ - ByteBuffer.prototype.reset = function() { - if (this.markedOffset >= 0) { - this.offset = this.markedOffset; - this.markedOffset = -1; - } else { - this.offset = 0; - this.length = 0; - } - return this; - }; - - /** - * Clones this ByteBuffer. The returned cloned ByteBuffer shares the same ArrayBuffer but will have its own offsets. - * @return {ByteBuffer} - * @expose - */ - ByteBuffer.prototype.clone = function() { - // When cloning, an undocumented third parameter is used to set array and view manually. - var b = new ByteBuffer(-1, this.littleEndian, /* shadow copy */ true); - b.array = this.array; - b.view = this.view; - b.offset = this.offset; - b.length = this.length; - return b; - }; - - /** - * Copies this ByteBuffer. The returned copied ByteBuffer has its own ArrayBuffer and uses the same offsets as this one. - * @return {ByteBuffer} - * @expose - */ - ByteBuffer.prototype.copy = function() { - if (this.array == null) { - return this.clone(); - } - var b = new ByteBuffer(this.array.byteLength, this.littleEndian); - var src = new Uint8Array(this.array); - var dst = new Uint8Array(b.array); - dst.set(src); - b.offset = this.offset; - b.length = this.length; - return b; - }; - - /** - * Gets the number of remaining readable bytes. Contents are the bytes between offset and length, so this returns - * length-offset. - * @return {number} Remaining readable bytes (may be negative if offset is larger than length) - * @expose - */ - ByteBuffer.prototype.remaining = function() { - if (this.array == null) return 0; - return this.length - this.offset; - }; - - /** - * Gets the capacity of the backing buffer. May be larger but not less than the contents actual length. Contents are the - * bytes between offset and length, which is independent of the actual capacity. - * @return {number} Capacity of the backing buffer or 0 if destroyed - * @expose - */ - ByteBuffer.prototype.capacity = function() { - return this.array != null ? this.array.byteLength : 0; - }; - - /** - * Compacts the ByteBuffer to be backed by an ArrayBuffer of its actual length. Will {@link ByteBuffer#flip} the - * ByteBuffer if its offset is larger than its length. If the ByteBuffer's offset is less than its length, only the - * portion between its offset and length will be contained in the compacted backing buffer. Will set offset=0 and - * length=capacity. Will do nothing but flipping, if required, if already compacted. - * @return {ByteBuffer} this - * @throws {Error} If the buffer cannot be compacted - * @expose - */ - ByteBuffer.prototype.compact = function() { - if (this.array == null) { - throw(new Error(this+" cannot be compacted: Already destroyed")); - } - if (this.offset > this.length) { - this.flip(); - } - if (this.offset == this.length) { - throw(new Error(this+" cannot be compacted: Offset ("+this.offset+") is equal to its length ("+this.length+")")); - } - if (this.offset == 0 && this.length == this.array.byteLength) { - return this; // Already compacted - } - var srcView = new Uint8Array(this.array); - var dst = new ArrayBuffer(this.length-this.offset); - var dstView = new Uint8Array(dst); - dstView.set(srcView.subarray(this.offset, this.length)); - this.array = dst; - this.offset = 0; - this.length = this.array.byteLength; - return this; - }; - - /** - * Destroys the ByteBuffer, releasing all references to the backing array. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.destroy = function() { - if (this.array == null) return; // Already destroyed - this.array = null; - this.view = null; - this.offset = 0; - this.length = 0; - return this; - }; - - /** - * Reverses the underlying back buffer and adapts offset and length to retain the same relative position on the - * reversed data in inverse order. Example: "00<01 02>03 04".reverse() = "04 03<02 01>00". - * @return {ByteBuffer} this - * @throws {Error} If the buffer is already destroyed - * @expose - */ - ByteBuffer.prototype.reverse = function() { - if (this.array == null) { - throw(new Error(this+" cannot be reversed: Already destroyed")); - } - // Not sure what for, but other implementations seem to have it :-) - Array.prototype.reverse.call(new Uint8Array(this.array)); - var o = this.offset; - this.offset = this.array.byteLength - this.length; - this.length = this.array.byteLength - o; - this.view = new DataView(this.array); - return this; - }; - - /** - * Appends another ByteBuffer to this one. Appends only the portion between offset and length of the specified - * ByteBuffer and overwrites any contents behind the specified offset up to the number of bytes appended from - * the specified ByteBuffer in this ByteBuffer. Will clone and flip the specified ByteBuffer if its offset is - * larger than its length (its offsets remain untouched through cloning). - * @param {*} src ByteBuffer or any object that can be wrapped by one to prepend - * @param {number=} offset Offset to append behind. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the specified buffer is already destroyed - * @expose - */ - ByteBuffer.prototype.append = function(src, offset) { - if (!(src instanceof ByteBuffer)) { - src = ByteBuffer.wrap(src); - } - if (src.array == null) { - throw(new Error(src+" cannot be appended to "+this+": Already destroyed")); - } - var n = src.length - src.offset; - if (n == 0) return this; // Nothing to append - if (n < 0) { - src = src.clone().flip(); - n = src.length - src.offset; - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=n)-n; - this.ensureCapacity(offset+n); - var srcView = new Uint8Array(src.array); - var dstView = new Uint8Array(this.array); - dstView.set(srcView.subarray(src.offset, src.length), offset); - return this; - }; - - /** - * Prepends another ByteBuffer to this one. Prepends only the portion between offset and length of the specified - * ByteBuffer and overwrites any contents before the specified offsets up to the number of bytes prepended from - * the specified ByteBuffer in this ByteBuffer. Will clone and flip the specified ByteBuffer if its offset is - * larger than its length (its offsets remain untouched through cloning). - * @param {*} src ByteBuffer or any object that can be wrapped by one to prepend - * @param {number=} offset Offset to prepend before. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the specified buffer is already destroyed - * @expose - */ - ByteBuffer.prototype.prepend = function(src, offset) { - if (!(src instanceof ByteBuffer)) { - src = ByteBuffer.wrap(src); - } - if (src.array == null) { - throw(src+" cannot be prepended to "+this+": Already destroyed"); - } - var n = src.length - src.offset; - if (n == 0) return this; // Nothing to prepend - if (n < 0) { - src = src.clone().flip(); - n = src.length - src.offset; - } - var modify = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var diff = n-offset; - if (diff > 0) { - // Doesn't fit, so maybe resize and move the contents that are already contained - this.ensureCapacity(this.length+diff); - this.append(this, n); - this.offset += diff; - this.length += diff; - this.append(src, 0); - } else { - this.append(src, offset-n); - } - if (modify) { - this.offset -= n; - } - return this; - }; - - /** - * Writes an 8bit singed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeInt8 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=1)-1; - this.ensureCapacity(offset+1); - this.view.setInt8(offset, value); - return this; - }; - - /** - * Reads an 8bit singed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readInt8 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=1)-1; - if (offset >= this.array.byteLength) { - throw(new Error("Cannot read int8 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt8(offset); - }; - - /** - * Writes a byte. This is an alias of {ByteBuffer#writeInt8}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeByte = ByteBuffer.prototype.writeInt8; - - /** - * Reads a byte. This is an alias of {@link ByteBuffer#readInt8}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readByte = ByteBuffer.prototype.readInt8; - - /** - * Writes an 8bit unsinged integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If the offset is equal to or larger than the capacity - * @expose - */ - ByteBuffer.prototype.writeUint8 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=1)-1; - this.ensureCapacity(offset+1); - this.view.setUint8(offset, value); - return this; - }; - - /** - * Reads an 8bit unsinged integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+1 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readUint8 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=1)-1; - if (offset+1 > this.array.byteLength) { - throw(new Error("Cannot read uint8 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint8(offset); - }; - - /** - * Writes a 16bit signed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeInt16 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - this.ensureCapacity(offset+2); - this.view.setInt16(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 16bit signed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readInt16 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - if (offset+2 > this.array.byteLength) { - throw(new Error("Cannot read int16 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt16(offset, this.littleEndian); - }; - - /** - * Writes a short value. This is an alias of {@link ByteBuffer#writeInt16}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeShort = ByteBuffer.prototype.writeInt16; - - /** - * Reads a short value. This is an alias of {@link ByteBuffer#readInt16}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readShort = ByteBuffer.prototype.readInt16; - - /** - * Writes a 16bit unsigned integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeUint16 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - this.ensureCapacity(offset+2); - this.view.setUint16(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 16bit unsigned integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+2 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readUint16 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=2)-2; - if (offset+2 > this.array.byteLEngth) { - throw(new Error("Cannot read int16 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint16(offset, this.littleEndian); - }; - - /** - * Writes a 32bit signed integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeInt32 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setInt32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit signed integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readInt32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (offset+4 > this.array.byteLength) { - throw(new Error("Cannot read int32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getInt32(offset, this.littleEndian); - }; - - /** - * Writes an integer. This is an alias of {@link ByteBuffer#writeInt32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeInt = ByteBuffer.prototype.writeInt32; - - /** - * Reads an integer. This is an alias of {@link ByteBuffer#readInt32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readInt = ByteBuffer.prototype.readInt32; - - /** - * Writes a 32bit unsigned integer. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeUint32 = function(value, offset) { - offset = typeof offset != 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setUint32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit unsigned integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readUint32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (offset+4 > this.array.byteLength) { - throw(new Error("Cannot read uint32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getUint32(offset, this.littleEndian); - }; - - /** - * Writes a 32bit float. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeFloat32 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - this.ensureCapacity(offset+4); - this.view.setFloat32(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 32bit float. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readFloat32 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=4)-4; - if (this.array == null || offset+4 > this.array.byteLength) { - throw(new Error("Cannot read float32 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getFloat32(offset, this.littleEndian); - }; - - /** - * Writes a float. This is an alias of {@link ByteBuffer#writeFloat32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeFloat = ByteBuffer.prototype.writeFloat32; - - /** - * Reads a float. This is an alias of {@link ByteBuffer#readFloat32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+4 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readFloat = ByteBuffer.prototype.readFloat32; - - /** - * Writes a 64bit float. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeFloat64 = function(value, offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - this.ensureCapacity(offset+8); - this.view.setFloat64(offset, value, this.littleEndian); - return this; - }; - - /** - * Reads a 64bit float. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+8 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readFloat64 = function(offset) { - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - throw(new Error("Cannot read float64 from "+this+" at "+offset+": Capacity overflow")); - } - return this.view.getFloat64(offset, this.littleEndian); - }; - - /** - * Writes a double. This is an alias of {@link ByteBuffer#writeFloat64}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeDouble = ByteBuffer.prototype.writeFloat64; - - /** - * Reads a double. This is an alias of {@link ByteBuffer#readFloat64}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number} - * @throws {Error} If offset+8 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readDouble = ByteBuffer.prototype.readFloat64; - - /** - * Writes a 64bit integer. Utilizes Long.js to write the low and high 32 bits separately. - * @function - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.prototype.writeInt64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - this.ensureCapacity(offset+8); - if (this.littleEndian) { - this.view.setInt32(offset, value.getLowBits(), true); - this.view.setInt32(offset+4, value.getHighBits(), true); - } else { - this.view.setInt32(offset, value.getHighBits(), false); - this.view.setInt32(offset+4, value.getLowBits(), false); - } - return this; - }; - - /** - * Reads a 64bit integer. Utilizes Long.js to construct a new Long from the low and high 32 bits. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long} - * @throws {Error} If offset+8 is larger than the capacity or long support is not available - * @expose - */ - ByteBuffer.prototype.readInt64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - this.offset -= 8; - throw(new Error("Cannot read int64 from "+this+" at "+offset+": Capacity overflow")); - } - var value; - if (this.littleEndian) { - value = Long.fromBits(this.view.getInt32(offset, true), this.view.getInt32(offset+4, true), false); - } else { - value = Long.fromBits(this.view.getInt32(offset+4, false), this.view.getInt32(offset, false), false); - } - return value; - }; - - /** - * Writes a 64bit unsigned integer. Utilizes Long.js to write the low and high 32 bits separately. - * @function - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.prototype.writeUint64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, true); - this.ensureCapacity(offset+8); - if (this.littleEndian) { - this.view.setUint32(offset, value.getLowBitsUnsigned(), true); - this.view.setUint32(offset+4, value.getHighBitsUnsigned(), true); - } else { - this.view.setUint32(offset, value.getHighBitsUnsigned(), false); - this.view.setUint32(offset+4, value.getLowBitsUnsigned(), false); - } - return this; - }; - - /** - * Reads a 64bit unsigned integer. Utilizes Long.js to construct a new Long from the low and high 32 bits. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long} - * @throws {Error} If offset+8 is larger than the capacity or long support is not available - * @expose - */ - ByteBuffer.prototype.readUint64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - offset = typeof offset !== 'undefined' ? offset : (this.offset+=8)-8; - if (this.array == null || offset+8 > this.array.byteLength) { - this.offset -= 8; - throw(new Error("Cannot read int64 from "+this+" at "+offset+": Capacity overflow")); - } - var value; - if (this.littleEndian) { - value = Long.fromBits(this.view.getUint32(offset, true), this.view.getUint32(offset+4, true), true); - } else { - value = Long.fromBits(this.view.getUint32(offset+4, false), this.view.getUint32(offset, false), true); - } - return value; - }; - - /** - * Writes a long. This is an alias of {@link ByteBuffer#writeInt64}. - * @function - * @param {number|ByteBuffer.Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer} this - * @expose - */ - ByteBuffer.prototype.writeLong = ByteBuffer.prototype.writeInt64; - - /** - * Reads a long. This is an alias of {@link ByteBuffer#readInt64}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer.Long} - * @throws {Error} If offset+8 is larger than the capacity - * @expose - */ - ByteBuffer.prototype.readLong = ByteBuffer.prototype.readInt64; - - /** - * Maximum number of bytes required to store a 32bit base 128 variable-length integer. - * @type {number} - * @const - * @expose - */ - ByteBuffer.MAX_VARINT32_BYTES = 5; - - /** - * Writes a 32bit base 128 variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeVarint32 = function(value, offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - // ref: http://code.google.com/searchframe#WTeibokF6gE/trunk/src/google/protobuf/io/coded_stream.cc - value = value >>> 0; - this.ensureCapacity(offset+ByteBuffer.calculateVarint32(value)); - var dst = this.view, - size = 0; - dst.setUint8(offset, value | 0x80); - if (value >= (1 << 7)) { - dst.setUint8(offset+1, (value >> 7) | 0x80); - if (value >= (1 << 14)) { - dst.setUint8(offset+2, (value >> 14) | 0x80); - if (value >= (1 << 21)) { - dst.setUint8(offset+3, (value >> 21) | 0x80); - if (value >= (1 << 28)) { - dst.setUint8(offset+4, (value >> 28) & 0x7F); - size = 5; - } else { - dst.setUint8(offset+3, dst.getUint8(offset+3) & 0x7F); - size = 4; - } - } else { - dst.setUint8(offset+2, dst.getUint8(offset+2) & 0x7F); - size = 3; - } - } else { - dst.setUint8(offset+1, dst.getUint8(offset+1) & 0x7F); - size = 2; - } - } else { - dst.setUint8(offset, dst.getUint8(offset) & 0x7F); - size = 1; - } - if (advance) { - this.offset += size; - return this; - } else { - return size; - } - }; - - /** - * Reads a 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - * @expose - */ - ByteBuffer.prototype.readVarint32 = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - // ref: src/google/protobuf/io/coded_stream.cc - - var count = 0, b, - src = this.view; - var value = 0 >>> 0; - do { - b = src.getUint8(offset+count); - if (count < ByteBuffer.MAX_VARINT32_BYTES) { - value |= ((b&0x7F)<<(7*count)) >>> 0; - } - ++count; - } while (b & 0x80); - value = value | 0; // Make sure to discard the higher order bits - if (advance) { - this.offset += count; - return value; - } else { - return { - "value": value, - "length": count - }; - } - }; - - /** - * Writes a zigzag encoded 32bit base 128 encoded variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeZigZagVarint32 = function(value, offset) { - return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset); - }; - - /** - * Reads a zigzag encoded 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - * @expose - */ - ByteBuffer.prototype.readZigZagVarint32 = function(offset) { - var dec = this.readVarint32(offset); - if (typeof dec === 'object') { - dec['value'] = ByteBuffer.zigZagDecode32(dec['value']); - return dec; - } - return ByteBuffer.zigZagDecode32(dec); - }; - - /** - * Maximum number of bytes required to store a 64bit base 128 variable-length integer. - * @type {number} - * @const - * @expose - */ - ByteBuffer.MAX_VARINT64_BYTES = 10; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_7_DBL = 1 << 7; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_14_DBL = TWO_PWR_7_DBL * TWO_PWR_7_DBL; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_21_DBL = TWO_PWR_7_DBL * TWO_PWR_14_DBL; - - /** - * @type {number} - * @const - * @private - */ - var TWO_PWR_28_DBL = TWO_PWR_14_DBL * TWO_PWR_14_DBL; - - /** - * Writes a 64bit base 128 variable-length integer as used in protobuf. - * @param {number|Long} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.prototype.writeVarint64 = function(value, offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - - var part0 = value.toInt() >>> 0, - part1 = value.shiftRightUnsigned(28).toInt() >>> 0, - part2 = value.shiftRightUnsigned(56).toInt() >>> 0, - size = ByteBuffer.calculateVarint64(value); - - this.ensureCapacity(offset+size); - var dst = this.view; - switch (size) { - case 10: dst.setUint8(offset+9, (part2 >>> 7) | 0x80); - case 9 : dst.setUint8(offset+8, (part2 ) | 0x80); - case 8 : dst.setUint8(offset+7, (part1 >>> 21) | 0x80); - case 7 : dst.setUint8(offset+6, (part1 >>> 14) | 0x80); - case 6 : dst.setUint8(offset+5, (part1 >>> 7) | 0x80); - case 5 : dst.setUint8(offset+4, (part1 ) | 0x80); - case 4 : dst.setUint8(offset+3, (part0 >>> 21) | 0x80); - case 3 : dst.setUint8(offset+2, (part0 >>> 14) | 0x80); - case 2 : dst.setUint8(offset+1, (part0 >>> 7) | 0x80); - case 1 : dst.setUint8(offset+0, (part0 ) | 0x80); - } - dst.setUint8(offset+size-1, dst.getUint8(offset+size-1) & 0x7F); - if (advance) { - this.offset += size; - return this; - } else { - return size; - } - }; - - /** - * Reads a 32bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long|{value: Long, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint or long support is not available - * @expose - */ - ByteBuffer.prototype.readVarint64 = function(offset) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var start = offset; - // ref: src/google/protobuf/io/coded_stream.cc - - var src = this.view, - part0, part1 = 0, part2 = 0, b; - b = src.getUint8(offset++); part0 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 7; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 14; if (b & 0x80) { - b = src.getUint8(offset++); part0 |= (b & 0x7F) << 21; if (b & 0x80) { - b = src.getUint8(offset++); part1 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 7; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 14; if (b & 0x80) { - b = src.getUint8(offset++); part1 |= (b & 0x7F) << 21; if (b & 0x80) { - b = src.getUint8(offset++); part2 = (b & 0x7F) ; if (b & 0x80) { - b = src.getUint8(offset++); part2 |= (b & 0x7F) << 7; if (b & 0x80) { - throw(new Error("Data must be corrupt: Buffer overrun")); }}}}}}}}}} - var value = Long.from28Bits(part0, part1, part2, false); - if (advance) { - this.offset = offset; - return value; - } else { - return { - "value": value, - "length": offset-start - }; - } - }; - - /** - * Writes a zigzag encoded 64bit base 128 encoded variable-length integer as used in protobuf. - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.prototype.writeZigZagVarint64 = function(value, offset) { - return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); - }; - - /** - * Reads a zigzag encoded 64bit base 128 variable-length integer as used in protobuf. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {Long|{value: Long, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint or long support is not available - * @expose - */ - ByteBuffer.prototype.readZigZagVarint64 = function(offset) { - var dec = this.readVarint64(offset); - if (typeof dec === 'object' && !(dec instanceof Long)) { - dec['value'] = ByteBuffer.zigZagDecode64(dec['value']); - return dec; - } - return ByteBuffer.zigZagDecode64(dec); - }; - - /** - * Writes a base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#writeVarint32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeVarint = ByteBuffer.prototype.writeVarint32; - - /** - * Reads a base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#readVarint32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @expose - */ - ByteBuffer.prototype.readVarint = ByteBuffer.prototype.readVarint32; - - /** - * Writes a zigzag encoded base 128 encoded variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#writeZigZagVarint32}. - * @function - * @param {number} value Value to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeZigZagVarint = ByteBuffer.prototype.writeZigZagVarint32; - - /** - * Reads a zigzag encoded base 128 variable-length integer as used in protobuf. This is an alias of {@link ByteBuffer#readZigZagVarint32}. - * @function - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {number|{value: number, length: number}} The value read if offset is omitted, else the value read and the actual number of bytes read. - * @throws {Error} If it's not a valid varint - * @expose - */ - ByteBuffer.prototype.readZigZagVarint = ByteBuffer.prototype.readZigZagVarint32; - - /** - * Calculates the actual number of bytes required to encode a 32bit base 128 variable-length integer. - * @param {number} value Value to encode - * @return {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES} (35bit). No overflow error. - * @expose - */ - ByteBuffer.calculateVarint32 = function(value) { - // ref: src/google/protobuf/io/coded_stream.cc - value = value >>> 0; - if (value < TWO_PWR_7_DBL) { - return 1; - } else if (value < TWO_PWR_14_DBL) { - return 2; - } else if (value < TWO_PWR_21_DBL) { - return 3; - } else if (value < TWO_PWR_28_DBL) { - return 4; - } else { - return 5; - } - }; - - /** - * Calculates the actual number of bytes required to encode a 64bit base 128 variable-length integer. - * @param {number|Long} value Value to encode - * @return {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES}. No overflow error. - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.calculateVarint64 = function(value) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/io/coded_stream.cc - if (!(typeof value === 'object' && value instanceof Long)) value = Long.fromNumber(value, false); - - var part0 = value.toInt() >>> 0, - part1 = value.shiftRightUnsigned(28).toInt() >>> 0, - part2 = value.shiftRightUnsigned(56).toInt() >>> 0; - - if (part2 == 0) { - if (part1 == 0) { - if (part0 < TWO_PWR_14_DBL) { - return part0 < TWO_PWR_7_DBL ? 1 : 2; - } else { - return part0 < TWO_PWR_21_DBL ? 3 : 4; - } - } else { - if (part1 < TWO_PWR_14_DBL) { - return part1 < TWO_PWR_7_DBL ? 5 : 6; - } else { - return part1 < TWO_PWR_21_DBL ? 7 : 8; - } - } - } else { - return part2 < TWO_PWR_7_DBL ? 9 : 10; - } - }; - - /** - * Encodes a signed 32bit integer so that it can be effectively used with varint encoding. - * @param {number} n Signed 32bit integer - * @return {number} Unsigned zigzag encoded 32bit integer - * @expose - */ - ByteBuffer.zigZagEncode32 = function(n) { - // ref: src/google/protobuf/wire_format_lite.h - return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; - }; - - /** - * Decodes a zigzag encoded signed 32bit integer. - * @param {number} n Unsigned zigzag encoded 32bit integer - * @return {number} Signed 32bit integer - * @expose - */ - ByteBuffer.zigZagDecode32 = function(n) { - // ref: src/google/protobuf/wire_format_lite.h - return ((n >>> 1) ^ -(n & 1)) | 0; - }; - - /** - * Encodes a signed 64bit integer so that it can be effectively used with varint encoding. - * @param {number|Long} n Signed long - * @return {Long} Unsigned zigzag encoded long - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.zigZagEncode64 = function(n) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/wire_format_lite.h - if (typeof n === 'object' && n instanceof Long) { - if (n.unsigned) n = n.toSigned(); - } else { - n = Long.fromNumber(n, false); - } - return n.shiftLeft(1).xor(n.shiftRight(63)).toUnsigned(); - }; - - /** - * Decodes a zigzag encoded signed 64bit integer. - * @param {Long} n Unsigned zigzag encoded long - * @return {Long} Signed long - * @throws {Error} If long support is not available - * @expose - */ - ByteBuffer.zigZagDecode64 = function(n) { - if (!Long) { - throw(new Error("Long support is not available: See https://github.com/dcodeIO/ByteBuffer.js#on-long-int64-support for details")) - } - // ref: src/google/protobuf/wire_format_lite.h - if (typeof n === 'object' && n instanceof Long) { - if (!n.unsigned) n = n.toUnsigned(); - } else { - n = Long.fromNumber(n, true); - } - return n.shiftRightUnsigned(1).xor(n.and(Long.ONE).toSigned().negate()).toSigned(); - }; - - /** - * Decodes a single UTF8 character from the specified ByteBuffer. The ByteBuffer's offsets are not modified. - * @param {ByteBuffer} src - * @param {number} offset Offset to read from - * @return {{char: number, length: number}} Decoded char code and the actual number of bytes read - * @throws {Error} If the character cannot be decoded or there is a capacity overflow - * @expose - */ - ByteBuffer.decodeUTF8Char = function(src, offset) { - var a = src.readUint8(offset), b, c, d, e, f, start = offset, charCode; - // ref: http://en.wikipedia.org/wiki/UTF-8#Description - // It's quite huge but should be pretty fast. - if ((a&0x80)==0) { - charCode = a; - offset += 1; - } else if ((a&0xE0)==0xC0) { - b = src.readUint8(offset+1); - charCode = ((a&0x1F)<<6) | (b&0x3F); - offset += 2; - } else if ((a&0xF0)==0xE0) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - charCode = ((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F); - offset += 3; - } else if ((a&0xF8)==0xF0) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - charCode = ((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F); - offset += 4; - } else if ((a&0xFC)==0xF8) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - e = src.readUint8(offset+4); - charCode = ((a&0x03)<<24) | ((b&0x3F)<<18) | ((c&0x3F)<<12) | ((d&0x3F)<<6) | (e&0x3F); - offset += 5; - } else if ((a&0xFE)==0xFC) { - b = src.readUint8(offset+1); - c = src.readUint8(offset+2); - d = src.readUint8(offset+3); - e = src.readUint8(offset+4); - f = src.readUint8(offset+5); - charCode = ((a&0x01)<<30) | ((b&0x3F)<<24) | ((c&0x3F)<<18) | ((d&0x3F)<<12) | ((e&0x3F)<<6) | (f&0x3F); - offset += 6; - } else { - throw(new Error("Cannot decode UTF8 character at offset "+offset+": charCode (0x"+a.toString(16)+") is invalid")); - } - return { - "char": charCode , - "length": offset-start - }; - }; - - /** - * Encodes a single UTF8 character to the specified ByteBuffer. The ByteBuffer's offsets are not modified. - * @param {number} charCode Character to encode as char code - * @param {ByteBuffer} dst ByteBuffer to encode to - * @param {number} offset Offset to write to - * @return {number} Actual number of bytes written - * @throws {Error} If the character cannot be encoded - * @expose - */ - ByteBuffer.encodeUTF8Char = function(charCode, dst, offset) { - var start = offset; - // ref: http://en.wikipedia.org/wiki/UTF-8#Description - // It's quite huge but should be pretty fast. - if (charCode < 0) { - throw(new Error("Cannot encode UTF8 character: charCode ("+charCode+") is negative")); - } - if (charCode < 0x80) { - dst.writeUint8(charCode&0x7F, offset); - offset += 1; - } else if (charCode < 0x800) { - dst.writeUint8(((charCode>>6)&0x1F)|0xC0, offset) - .writeUint8((charCode&0x3F)|0x80, offset+1); - offset += 2; - } else if (charCode < 0x10000) { - dst.writeUint8(((charCode>>12)&0x0F)|0xE0, offset) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+1) - .writeUint8((charCode&0x3F)|0x80, offset+2); - offset += 3; - } else if (charCode < 0x200000) { - dst.writeUint8(((charCode>>18)&0x07)|0xF0, offset) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+2) - .writeUint8((charCode&0x3F)|0x80, offset+3); - offset += 4; - } else if (charCode < 0x4000000) { - dst.writeUint8(((charCode>>24)&0x03)|0xF8, offset) - .writeUint8(((charCode>>18)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+2) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+3) - .writeUint8((charCode&0x3F)|0x80, offset+4); - offset += 5; - } else if (charCode < 0x80000000) { - dst.writeUint8(((charCode>>30)&0x01)|0xFC, offset) - .writeUint8(((charCode>>24)&0x3F)|0x80, offset+1) - .writeUint8(((charCode>>18)&0x3F)|0x80, offset+2) - .writeUint8(((charCode>>12)&0x3F)|0x80, offset+3) - .writeUint8(((charCode>>6)&0x3F)|0x80, offset+4) - .writeUint8((charCode&0x3F)|0x80, offset+5); - offset += 6; - } else { - throw(new Error("Cannot encode UTF8 character: charCode (0x"+charCode.toString(16)+") is too large (>= 0x80000000)")); - } - return offset-start; - }; - - /** - * Calculates the actual number of bytes required to encode the specified char code. - * @param {number} charCode Character to encode as char code - * @return {number} Number of bytes required to encode the specified char code - * @throws {Error} If the character cannot be calculated (too large) - * @expose - */ - ByteBuffer.calculateUTF8Char = function(charCode) { - if (charCode < 0) { - throw(new Error("Cannot calculate length of UTF8 character: charCode ("+charCode+") is negative")); - } - if (charCode < 0x80) { - return 1; - } else if (charCode < 0x800) { - return 2; - } else if (charCode < 0x10000) { - return 3; - } else if (charCode < 0x200000) { - return 4; - } else if (charCode < 0x4000000) { - return 5; - } else if (charCode < 0x80000000) { - return 6; - } else { - throw(new Error("Cannot calculate length of UTF8 character: charCode (0x"+charCode.toString(16)+") is too large (>= 0x80000000)")); - } - }; - - /** - * Calculates the number of bytes required to store an UTF8 encoded string. - * @param {string} str String to calculate - * @return {number} Number of bytes required - */ - ByteBuffer.calculateUTF8String = function(str) { - str = ""+str; - var bytes = 0; - for (var i=0; i i ? bb.readUint8(i++) : 0; - o3 = bb.length > i ? bb.readUint8(i++) : 0; - bits = o1 << 16 | o2 << 8 | o3; - h1 = bits >> 18 & 0x3f; - h2 = bits >> 12 & 0x3f; - h3 = bits >> 6 & 0x3f; - h4 = bits & 0x3f; - out[oi++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); - } while (i < bb.length); - var enc = out.join(''), - r = (bb.length - bb.offset) % 3; - return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3); - }; - - /** - * Decodes a base6 encoded string to a ByteBuffer. - * @param {string} str Base64 encoded string - * @returns {!ByteBuffer} ByteBuffer - * @throws {Error} If the argument is not a valid base64 encoded string - * @expose - */ - ByteBuffer.decode64 = function(str) { - // ref: http://phpjs.org/functions/base64_decode/ - if (typeof str !== 'string') { - throw(new Error("Illegal argument: Not a string")); - } - var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, - out = new ByteBuffer(Math.ceil(str.length / 3)); - do { - h1 = b64.indexOf(str.charAt(i++)); - h2 = b64.indexOf(str.charAt(i++)); - h3 = b64.indexOf(str.charAt(i++)); - h4 = b64.indexOf(str.charAt(i++)); - if (h1 < 0 || h2 < 0 || h3 < 0 || h4 < 0) { - throw(new Error("Illegal argument: Not a valid base64 encoded string")); - } - bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; - o1 = bits >> 16 & 0xff; - o2 = bits >> 8 & 0xff; - o3 = bits & 0xff; - if (h3 == 64) { - out.writeUint8(o1); - } else if (h4 == 64) { - out.writeUint8(o1) - .writeUint8(o2); - } else { - out.writeUint8(o1) - .writeUint8(o2) - .writeUint8(o3); - } - } while (i < str.length); - return out.flip(); - }; - - - /** - * Writes an UTF8 string. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeUTF8String = function(str, offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var start = offset; - var encLen = ByteBuffer.calculateUTF8String(str), i; // See [1] - this.ensureCapacity(offset+encLen); - for (i=0; ilength ? "+" : "")+offset-length)+" bytes")); - } - if (advance) { - this.offset = offset; - return result; - } else { - return { - "string": result, - "length": offset-start - } - } - }; - - /** - * Writes a string with prepended number of characters, which is also encoded as an UTF8 character.. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeLString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = ByteBuffer.encodeUTF8Char(str.length, this, offset); - encLen += this.writeUTF8String(str, offset+encLen); - if (advance) { - this.offset += encLen; - return this; - } else { - return encLen; - } - }; - - /** - * Reads a string with a prepended number of characters, which is also encoded as an UTF8 character. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded - * @expose - */ - ByteBuffer.prototype.readLString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var lenDec = ByteBuffer.decodeUTF8Char(this, offset); - var dec = this.readUTF8String(lenDec["char"], offset+lenDec["length"]); - if (advance) { - this.offset += lenDec["length"]+dec["length"]; - return dec["string"]; - } else { - return { - "string": dec["string"], - "length": lenDec["length"]+dec["length"] - }; - } - }; - - /** - * Writes a string with prepended number of characters, which is encoded as a 32bit base 128 variable-length integer. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeVString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = this.writeVarint32(ByteBuffer.calculateUTF8String(str), offset); - encLen += this.writeUTF8String(str, offset+encLen); - if (advance) { - this.offset += encLen; - return this; - } else { - return encLen; - } - }; - - /** - * Reads a string with a prepended number of characters, which is encoded as a 32bit base 128 variable-length integer. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded or the delimiter is not a valid varint - * @expose - */ - ByteBuffer.prototype.readVString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var lenDec = this.readVarint32(offset); - var dec = this.readUTF8StringBytes(lenDec["value"], offset+lenDec["length"]); - if (advance) { - this.offset += lenDec["length"]+dec["length"]; - return dec["string"]; - } else { - return { - "string": dec["string"], - "length": lenDec["length"]+dec["length"] - }; - } - }; - - /** - * Writes a string followed by a NULL character (Uint8). Beware: The source string must not contain NULL characters - * unless this is actually intended. This is not checked. If you have the option it is recommended to use - * {@link ByteBuffer#writeLString} or {@link ByteBuffer#writeVString} with the corresponding reading methods instead. - * @param {string} str String to write - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. - * @expose - */ - ByteBuffer.prototype.writeCString = function(str, offset) { - str = ""+str; - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var encLen = this.writeUTF8String(str, offset); - this.writeUint8(0, offset+encLen); - if (advance) { - this.offset += encLen+1; - return this; - } else { - return encLen+1; - } - }; - - /** - * Reads a string followed by a NULL character (Uint8). - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @return {string|{string: string, length: number}} The string read if offset is omitted, else the string read and the actual number of bytes read. - * @throws {Error} If the string cannot be decoded - * @expose - */ - ByteBuffer.prototype.readCString = function(offset) { - var advance = typeof offset === 'undefined'; - offset = typeof offset !== 'undefined' ? offset : this.offset; - var dec, result = "", start = offset; - do { - dec = ByteBuffer.decodeUTF8Char(this, offset); - offset += dec["length"]; - if (dec["char"] != 0) result += String.fromCharCode(dec["char"]); - } while (dec["char"] != 0); - if (advance) { - this.offset = offset; - return result; - } else { - return { - "string": result, - "length": offset-start - }; - } - }; - - /** - * Serializes and writes a JSON payload. - * @param {*} data Data payload to serialize - * @param {number=} offset Offset to write to. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted, - * @param {function=} stringify Stringify implementation to use. Defaults to {@link JSON.stringify}. - * @return {ByteBuffer|number} this if offset is omitted, else the actual number if bytes written, - * @expose - */ - ByteBuffer.prototype.writeJSON = function(data, offset, stringify) { - stringify = typeof stringify === 'function' ? stringify : JSON.stringify; - return this.writeLString(stringify(data), offset); - }; - - /** - * Reads a JSON payload and unserializes it. - * @param {number=} offset Offset to read from. Defaults to {@link ByteBuffer#offset} which will be modified only if omitted. - * @param {function=} parse Parse implementation to use. Defaults to {@link JSON.parse}. - * @return {*|{data: *, length: number}} Data payload if offset is omitted, else the data payload and the actual number of bytes read. - * @throws {Error} If the data cannot be decoded - * @expose - */ - ByteBuffer.prototype.readJSON = function(offset, parse) { - parse = typeof parse === 'function' ? parse : JSON.parse; - var result = this.readLString(offset); - if (typeof result === 'string') { - return parse(result); - } else { - return { - "data": parse(result["string"]), - "length": result["length"] - }; - } - }; - - /** - * Prints debug information about this ByteBuffer's contents to console. - * @param {!Function=|boolean} out Output function to call with the result or true to return the data as a string. - * Defaults to call console.log. - * @expose - */ - ByteBuffer.prototype.printDebug = function(out) { - var s = (this.array != null ? "ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")" : "ByteBuffer(DESTROYED)")+"\n"+ - "-------------------------------------------------------------------\n"; - var h = this.toHex(16, true); - var a = this.toASCII(16, true); - for (var i=0; i} Hex representation as of " 00<01 02>03..." with marked offsets - * @expose - */ - ByteBuffer.prototype.toHex = function(wrap, asArray) { - if (this.array == null) return "DESTROYED"; - asArray = !!asArray; - wrap = typeof wrap !== 'undefined' ? parseInt(wrap, 10) : 16; - if (wrap < 1) wrap = 16; - var out = "", - lines = [], - view = this.view; - if (this.offset == 0 && this.length == 0) { - out += "|"; - } else if (this.length == 0) { - out += ">"; - } else if (this.offset == 0) { - out += "<"; - } else { - out += " "; - } - for (var i=0; i0 && i%wrap == 0) { - lines.push(out); - out = " "; - } - var val = view.getUint8(i); - val = val.toString(16).toUpperCase(); - if (val.length < 2) val = "0"+val; - out += val; - if (i+1 == this.offset && i+1 == this.length) { - out += "|"; - } else if (i+1 == this.offset) { - out += "<"; - } else if (i+1 == this.length) { - out += ">"; - } else { - out += " "; - } - } - if (asArray) { - while (out.length < 3*wrap+1) out += " "; // Make it equal to maybe show something on the right - } - lines.push(out); - return asArray ? lines : lines.join("\n"); - }; - - /** - * Returns an ASCII representation of this ByteBuffer's contents. Beware: May be large. - * @param {number=} wrap Wrap length. Defaults to 16. - * @param {boolean=} asArray Set to true to return an array of lines. Defaults to false. - * @return {string|Array.} ASCII representation as of "abcdef..." (33-126, else ".", no marked offsets) - * @expose - */ - ByteBuffer.prototype.toASCII = function(wrap, asArray) { - if (this.array == null) return ""; - asArray = !!asArray; - wrap = typeof wrap !== 'undefined' ? parseInt(wrap, 10) : 16; - if (wrap < 1) wrap = 16; - var out = "", lines = [], src = this.view; - for (var i=0; i0 && i%wrap == 0) { - lines.push(out); - out = ""; - } - var val = src.getUint8(i); - if (val > 32 && val < 127) { - val = String.fromCharCode(val); - } else { - val = "."; - } - out += val; - } - lines.push(out); - return asArray ? lines : lines.join("\n")+"\n"; - }; - - /** - * Returns the base64 encoded representation of the buffer's contents. - * @returns {string} Base 64 encoded string - * @expose - */ - ByteBuffer.prototype.toBase64 = function() { - if (this.array == null || this.offset >= this.length) return ""; - return ByteBuffer.encode64(this); - }; - - /** - * Returns the contents of the buffer as an UTF8 encoded string. - * @returns {string} - * @expose - */ - ByteBuffer.prototype.toUTF8 = function() { - if (this.array == null || this.offset >= this.length) return ""; - return this.readUTF8StringBytes(this.length - this.offset, this.offset).string; - }; - - /** - * Returns a string representation. - * @param {string=} enc Output encoding. Returns a pretty printed debug table by default but also allows direct - * conversion to "utf8" and "base64" encoding. - * @return {string} String representation - * @expose - */ - ByteBuffer.prototype.toString = function(enc) { - enc = enc || "debug"; - switch (enc) { - case "utf8": - return this.toUTF8(); - case "base64": - return this.toBase64(); - default: - if (this.array == null) { - return "ByteBuffer(DESTROYED)"; - } - return "ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")"; - } - }; - - /** - * Returns an ArrayBuffer compacted to contain this ByteBuffer's actual contents. Will implicitly - * {@link ByteBuffer#flip} the ByteBuffer if its offset is larger than its length. Will return a reference to - * the unmodified backing buffer if offset=0 and length=capacity unless forceCopy is set to true. - * @param {boolean=} forceCopy Forces the creation of a copy if set to true. Defaults to false. - * @return {ArrayBuffer} Compacted ArrayBuffer - * @expose - */ - ByteBuffer.prototype.toArrayBuffer = function(forceCopy) { - var b = this.clone(); - if (b.offset > b.length) { - b.flip(); - } - var copied = false; - if (b.offset > 0 || b.length < b.array.byteLength) { - b.compact(); // Will always create a new backing buffer because of the above condition - copied = true; - } - return forceCopy && !copied ? b.copy().array : b.array; - }; - - /** - * Returns a node Buffer compacted to contain this ByteBuffer's actual contents. Will implicitly - * {@link ByteBuffer#flip} the ByteBuffer if its offset is larger than its length. Will also copy all data (not - * a reference). - * @returns {Buffer} Compacted Buffer - * @throws {Error} If not running inside of node - * @expose - */ - ByteBuffer.prototype.toBuffer = function() { - if (Buffer) { - var offset = this.offset, length = this.length; - if (offset > length) { - var temp = offset; - offset = length; - length = temp; - } - var srcView = new Uint8Array(this.array); - return new Buffer(srcView.subarray(offset, length)); - } - throw(new Error("Conversion to Buffer is available under node.js only")); - }; - - /** - * Extends the ByteBuffer prototype with additional methods. - * @param {string} name Method name - * @param {!Function} func Prototype function - * @throws {Error} If the arguments are invalid - * @expose - */ - ByteBuffer.extend = function(name, func) { - if (typeof name === 'string' && typeof func === 'function') { - ByteBuffer.prototype[name] = func; - } else { - throw(new Error("Cannot extend prototype with "+name+"="+func+" (exptected string and function)")); - } - }; - - return ByteBuffer; - } - - - - // Enable module loading if available - if (typeof module !== 'undefined' && module["exports"]) { // CommonJS - /** @expose */ - module["exports"] = loadByteBuffer(require("long")); - } else if (typeof define !== 'undefined' && define["amd"]) { // AMD - define("ByteBuffer", ["Math/Long"], function(Long) { return loadByteBuffer(Long); }); - } else { // Shim - if (!global["dcodeIO"]) { - /** @expose */ - global["dcodeIO"] = {}; - } - /** @expose */ - global["dcodeIO"]["ByteBuffer"] = loadByteBuffer(dcodeIO.Long); - } - -})(this); diff --git a/src/bower.json b/src/bower.json new file mode 100644 index 0000000..99dc4a3 --- /dev/null +++ b/src/bower.json @@ -0,0 +1,12 @@ +{ + "name": "bytebuffer", + "version": "/*?= VERSION */", + "author": "Daniel Wirtz ", + "description": "A full-featured ByteBuffer implementation using typed arrays.", + "main": "dist/bytebuffer.js", + "keywords": ["net", "array", "buffer", "arraybuffer", "typed array", "bytebuffer", "json", "websocket", "webrtc"], + "dependencies": { + "long": "latest" + }, + "license": "Apache-2.0" +} diff --git a/src/bytebuffer.js b/src/bytebuffer.js new file mode 100644 index 0000000..73f75cc --- /dev/null +++ b/src/bytebuffer.js @@ -0,0 +1,220 @@ +//? include("macros.js"); +/** + * Constructs a new ByteBuffer. + * @class The swiss army knife for binary data in JavaScript. + * @exports ByteBuffer + * @constructor + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @expose + */ +var ByteBuffer = function(capacity, littleEndian, noAssert) { + if (typeof capacity === 'undefined') + capacity = ByteBuffer.DEFAULT_CAPACITY; + if (typeof littleEndian === 'undefined') + littleEndian = ByteBuffer.DEFAULT_ENDIAN; + if (typeof noAssert === 'undefined') + noAssert = ByteBuffer.DEFAULT_NOASSERT; + if (!noAssert) { + capacity = capacity | 0; + if (capacity < 0) + throw RangeError("Illegal capacity"); + littleEndian = !!littleEndian; + noAssert = !!noAssert; + } + //? if (NODE) { + + /** + * Backing node Buffer. + * @type {!Buffer} + * @expose + */ + this.buffer = capacity === 0 ? EMPTY_BUFFER : new Buffer(capacity); + //? } else { + + /** + * Backing ArrayBuffer. + * @type {!ArrayBuffer} + * @expose + */ + this.buffer = capacity === 0 ? EMPTY_BUFFER : new ArrayBuffer(capacity); + + //? if (DATAVIEW) { + /** + * DataView utilized to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`. + * @type {?DataView} + * @expose + */ + this.view = capacity === 0 ? null : new DataView(this.buffer); + //? } else { + /** + * Uint8Array utilized to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`. + * @type {?Uint8Array} + * @expose + */ + this.view = capacity === 0 ? null : new Uint8Array(this.buffer); + //? } + //? } + + /** + * Absolute read/write offset. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.offset = 0; + + /** + * Marked offset. + * @type {number} + * @expose + * @see ByteBuffer#mark + * @see ByteBuffer#reset + */ + this.markedOffset = -1; + + /** + * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.limit = capacity; + + /** + * Whether to use little endian byte order, defaults to `false` for big endian. + * @type {boolean} + * @expose + */ + this.littleEndian = littleEndian; + + /** + * Whether to skip assertions of offsets and values, defaults to `false`. + * @type {boolean} + * @expose + */ + this.noAssert = noAssert; +}; + +/** + * ByteBuffer version. + * @type {string} + * @const + * @expose + */ +ByteBuffer.VERSION = "/*?= VERSION */"; + +/** + * Little endian constant that can be used instead of its boolean value. Evaluates to `true`. + * @type {boolean} + * @const + * @expose + */ +ByteBuffer.LITTLE_ENDIAN = true; + +/** + * Big endian constant that can be used instead of its boolean value. Evaluates to `false`. + * @type {boolean} + * @const + * @expose + */ +ByteBuffer.BIG_ENDIAN = false; + +/** + * Default initial capacity of `16`. + * @type {number} + * @expose + */ +ByteBuffer.DEFAULT_CAPACITY = 16; + +/** + * Default endianess of `false` for big endian. + * @type {boolean} + * @expose + */ +ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN; + +/** + * Default no assertions flag of `false`. + * @type {boolean} + * @expose + */ +ByteBuffer.DEFAULT_NOASSERT = false; +//? if (NODE) { + +/** + * A `Long` class for representing a 64-bit two's-complement integer value. + * @type {!Long} + * @const + * @see https://npmjs.org/package/long + * @expose + */ +ByteBuffer.Long = Long; +//? } else { + +/** + * A `Long` class for representing a 64-bit two's-complement integer value. May be `null` if Long.js has not been loaded + * and int64 support is not available. + * @type {?Long} + * @const + * @see https://github.com/dcodeIO/long.js + * @expose + */ +ByteBuffer.Long = Long || null; +//? } + +/** + * @alias ByteBuffer.prototype + * @inner + */ +var ByteBufferPrototype = ByteBuffer.prototype; + +/** + * An indicator used to reliably determine if an object is a ByteBuffer or not. + * @type {boolean} + * @const + * @expose + * @private + */ +ByteBufferPrototype.__isByteBuffer__; + +Object.defineProperty(ByteBufferPrototype, "__isByteBuffer__", { + value: true, + enumerable: false, + configurable: false +}); + +//? include("helpers.js"); + +//? include("methods/static/*.js"); +//? if (BYTES) { + +//? include("types/bytes/*.js"); +//? } +//? if (INTS) { + +//? include("types/ints/*.js"); +//? } +//? if (FLOATS) { + +//? include("types/floats/float*.js"); +//? } +//? if (VARINTS) { + +//? include("types/varints/*.js"); +//? } +//? if (UTF8 && STRINGS) { + +//? include("types/strings/*.js"); +//? } + +//? include("methods/*.js"); +//? if (ENCODINGS) { + +//? include("encodings/*.js"); +//? } \ No newline at end of file diff --git a/src/encodings/base64.js b/src/encodings/base64.js new file mode 100644 index 0000000..583ffe9 --- /dev/null +++ b/src/encodings/base64.js @@ -0,0 +1,88 @@ +//? if (BASE64) { +//? if (!NODE) { +// lxiv-embeddable + +//? include("../../node_modules/lxiv/dist/lxiv-embeddable.js"); + +//? } +// encodings/base64 + +/** + * Encodes this ByteBuffer's contents to a base64 encoded string. + * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}. + * @returns {string} Base64 encoded string + * @throws {RangeError} If `begin` or `end` is out of bounds + * @expose + */ +ByteBufferPrototype.toBase64 = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin = begin | 0; end = end | 0; + if (begin < 0 || end > this.capacity || begin > end) + throw RangeError("begin, end"); + //? if (NODE) + return this.buffer.toString("base64", begin, end); + //? else { + var sd; lxiv.encode(function() { + //? if (DATAVIEW) + return begin < end ? this.view.getUint8(begin++) : null; + //? else + return begin < end ? this.view[begin++] : null; + }.bind(this), sd = stringDestination()); + return sd(); + //? } +}; + +/** + * Decodes a base64 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ +ByteBuffer.fromBase64 = function(str, littleEndian) { + //? if (NODE) { + return ByteBuffer.wrap(new Buffer(str, "base64"), littleEndian); + //? } else { + if (typeof str !== 'string') + throw TypeError("str"); + var bb = new ByteBuffer(str.length/4*3, littleEndian), + i = 0; + lxiv.decode(stringSource(str), function(b) { + //? if (DATAVIEW) + bb.view.setUint8(i++, b); + //? else + bb.view[i++] = b; + }); + bb.limit = i; + //? } + return bb; +}; + +/** + * Encodes a binary string to base64 like `window.btoa` does. + * @param {string} str Binary string + * @returns {string} Base64 encoded string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa + * @expose + */ +ByteBuffer.btoa = function(str) { + return ByteBuffer.fromBinary(str).toBase64(); +}; + +/** + * Decodes a base64 encoded string to binary like `window.atob` does. + * @param {string} b64 Base64 encoded string + * @returns {string} Binary string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob + * @expose + */ +ByteBuffer.atob = function(b64) { + return ByteBuffer.fromBase64(b64).toBinary(); +}; + +//? } \ No newline at end of file diff --git a/src/encodings/binary.js b/src/encodings/binary.js new file mode 100644 index 0000000..ef9c531 --- /dev/null +++ b/src/encodings/binary.js @@ -0,0 +1,74 @@ +//? if (BINARY) { +// encodings/binary + +/** + * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes. + * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}. + * @returns {string} Binary encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ +ByteBufferPrototype.toBinary = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin |= 0; end |= 0; + if (begin < 0 || end > this.capacity() || begin > end) + throw RangeError("begin, end"); + //? if (NODE) + return this.buffer.toString("binary", begin, end); + //? else { + if (begin === end) + return ""; + var chars = [], + parts = []; + while (begin < end) { + //? if (NODE) + chars.push(this.buffer[begin++]); + //? else if (DATAVIEW) + chars.push(this.view.getUint8(begin++)); + //? else + chars.push(this.view[begin++]); + if (chars.length >= 1024) + parts.push(String.fromCharCode.apply(String, chars)), + chars = []; + } + return parts.join('') + String.fromCharCode.apply(String, chars); + //? } +}; + +/** + * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ +ByteBuffer.fromBinary = function(str, littleEndian) { + //? if (NODE) { + return ByteBuffer.wrap(new Buffer(str, "binary"), littleEndian); + //? } else { + if (typeof str !== 'string') + throw TypeError("str"); + var i = 0, + k = str.length, + charCode, + bb = new ByteBuffer(k, littleEndian); + while (i 0xff) + throw RangeError("illegal char code: "+charCode); + //? if (DATAVIEW) + bb.view.setUint8(i++, charCode); + //? else + bb.view[i++] = charCode; + } + bb.limit = k; + //? } + return bb; +}; + +//? } \ No newline at end of file diff --git a/src/encodings/debug.js b/src/encodings/debug.js new file mode 100644 index 0000000..939311a --- /dev/null +++ b/src/encodings/debug.js @@ -0,0 +1,211 @@ +//? if (DEBUG) { +// encodings/debug + +/** + * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are: + * * `<` : offset, + * * `'` : markedOffset, + * * `>` : limit, + * * `|` : offset and limit, + * * `[` : offset and markedOffset, + * * `]` : markedOffset and limit, + * * `!` : offset, markedOffset and limit + * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false` + * @returns {string|!Array.} Debug string or array of lines if `asArray = true` + * @expose + * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3` + * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4` + * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1` + * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1` + */ +ByteBufferPrototype.toDebug = function(columns) { + var i = -1, + //? if (NODE) + k = this.buffer.length, + //? else + k = this.buffer.byteLength, + b, + hex = "", + asc = "", + out = ""; + while (i 32 && b < 127 ? String.fromCharCode(b) : '.'; + } + ++i; + if (columns) { + if (i > 0 && i % 16 === 0 && i !== k) { + while (hex.length < 3*16+3) hex += " "; + out += hex+asc+"\n"; + hex = asc = ""; + } + } + if (i === this.offset && i === this.limit) + hex += i === this.markedOffset ? "!" : "|"; + else if (i === this.offset) + hex += i === this.markedOffset ? "[" : "<"; + else if (i === this.limit) + hex += i === this.markedOffset ? "]" : ">"; + else + hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : ""); + } + if (columns && hex !== " ") { + while (hex.length < 3*16+3) + hex += " "; + out += hex + asc + "\n"; + } + return columns ? out : hex; +}; + +/** + * Decodes a hex encoded string with marked offsets to a ByteBuffer. + * @param {string} str Debug string to decode (not be generated with `columns = true`) + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + * @see ByteBuffer#toDebug + */ +ByteBuffer.fromDebug = function(str, littleEndian, noAssert) { + /*? + // "<60 61 62 63>"; // 13 = 4 + // "60<61 62]63" // 11 = 4 + // "<61 61 61>"; // 10 = 3 => C = ((L+1)/3) | 0 + // "61<61>61"; // 8 = 3 + // "<61 61>"; // 7 = 2 + */ + var k = str.length, + bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert); + var i = 0, j = 0, ch, b, + rs = false, // Require symbol next + ho = false, hm = false, hl = false, // Already has offset (ho), markedOffset (hm), limit (hl)? + fail = false; + while (i': + if (!noAssert) { + if (hl) { + fail = true; + break; + } + hl = true; + } + bb.limit = j; + rs = false; + break; + case "'": + if (!noAssert) { + if (hm) { + fail = true; + break; + } + hm = true; + } + bb.markedOffset = j; + rs = false; + break; + case ' ': + rs = false; + break; + default: + if (!noAssert) { + if (rs) { + fail = true; + break; + } + } + b = parseInt(ch+str.charAt(i++), 16); + if (!noAssert) { + if (isNaN(b) || b < 0 || b > 255) + throw TypeError("Illegal str: Not a debug encoded string"); + } + //? if (NODE) + bb.buffer[j++] = b; + //? else if (DATAVIEW) + bb.view.setUint8(j++, b); + //? else + bb.view[j++] = b; + rs = true; + } + if (fail) + throw TypeError("Illegal str: Invalid symbol at "+i); + } + if (!noAssert) { + if (!ho || !hl) + throw TypeError("Illegal str: Missing offset or limit"); + //? if (NODE) + if (j 255) + throw TypeError("Illegal str: Contains non-hex characters"); + //? if (DATAVIEW) + bb.view.setUint8(j++, b); + //? else + bb.view[j++] = b; + } + bb.limit = j; + //? } + return bb; +}; + +//? } \ No newline at end of file diff --git a/src/encodings/impl/base64.js b/src/encodings/impl/base64.js new file mode 100644 index 0000000..9d2dfd3 --- /dev/null +++ b/src/encodings/impl/base64.js @@ -0,0 +1,3 @@ +// encodings/impl/base64 + +// TODO diff --git a/src/encodings/impl/binary.js b/src/encodings/impl/binary.js new file mode 100644 index 0000000..773a1c7 --- /dev/null +++ b/src/encodings/impl/binary.js @@ -0,0 +1,65 @@ +// encodings/impl/binary + +/** + * Encodes a binary JavaScript string to bytes. + * @param {string} src Source string + * @param {number} srcOffset Source offset + * @param {!ByteBuffer} dst Destination ByteBuffer + * @param {number} dstOffset Destination offset + * @param {number} count Number of char codes to encode + * @returns {number} Number of bytes encoded + * @inner + */ +function binary_encode(src, srcOffset, dst, dstOffset, count) { + var n = 0; + while (count--) { + var cc = src.charCodeAt(srcOffset++); + if (cc > 255) + throw Error("illegal binary char code: "+cc); + //? SET('cc', 'dstOffset++', 'dst'); + ++n; + } + return n; +} + +/** + * Decodes bytes to a binary JavaScript string. + * @param {!ByteBuffer} src Source ByteBuffer + * @param {number} srcOffset Source offset + * @param {number} count Number of bytes to decode + * @returns {string} Decoded string + * @inner + */ +function binary_decode(src, srcOffset, count) { + if (count === 0) + return ""; + var parts = [], // readily assembled parts + batch = []; // char codes for batch processing + while (count--) { + batch.push(/*? GET('srcOffset++', 'src') */); + if (batch.length > 1023) { + parts.push(String.fromCharCode.apply(String, batch)); + batch.length = 0; + } + } + if (batch.length > 0) { + if (parts.length === 0) + return String.fromCharCode.apply(String, batch); + parts.push(String.fromCharCode.apply(String, batch)); + } + return parts.join(''); +} + +/** + * Calculates the number of bytes required to store a binary JavaScript string. + * @param {string} src Source string + * @param {number} srcOffset Source offset + * @param {number} count Number of char codes to calculate + * @returns {number} Number of bytes required + * @inner + */ +function binary_calculate(src, srcOffset, count) { + return count; +} + +ByteBuffer.registerEncoding("binary", binary_encode, binary_decode, binary_calculate); diff --git a/src/encodings/impl/debug.js b/src/encodings/impl/debug.js new file mode 100644 index 0000000..e3f0617 --- /dev/null +++ b/src/encodings/impl/debug.js @@ -0,0 +1,3 @@ +// encodings/impl/debug + +// TODO diff --git a/src/encodings/impl/hex.js b/src/encodings/impl/hex.js new file mode 100644 index 0000000..148a463 --- /dev/null +++ b/src/encodings/impl/hex.js @@ -0,0 +1,101 @@ +// encodings/impl/hex + +/** + * Encodes a hexadecimal JavaScript string to bytes. + * @param {string} src Source string + * @param {number} srcOffset Source offset + * @param {!ByteBuffer} dst Destination ByteBuffer + * @param {number} dstOffset Destination offset + * @param {number} count Number of char codes to encode + * @returns {number} Number of bytes encoded + * @inner + */ +function hex_encode(src, srcOffset, dst, dstOffset, count) { + if (count === 0) + return 0; + var n = 0; + while (count--) { + if (count === 0) + throw Error("truncated hex sequence"); + --count; + var value = 0, + shift = 0; + for (var i=0; i<2; ++i) { + var cc = src.charCodeAt(srcOffset++); + switch (cc) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: + value |= (cc - 0x30) << shift; + break; + case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: + value |= (cc - 0x4B) << shift; + break; + case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: + value |= (cc - 0x6B) << shift; + break; + default: + throw Error("illegal hex char code: "+cc); + } + shift += 4; + } + //? SET('value', 'dstOffset++', 'dst'); + ++n; + } + return n; +} + +/** + * Decodes bytes to a hexadecimal JavaScript string. + * @param {!ByteBuffer} src Source ByteBuffer + * @param {number} srcOffset Source offset + * @param {number} count Number of bytes to decode + * @returns {string} Decoded string + * @inner + */ +function hex_decode(src, srcOffset, count) { + if (count === 0) + return ""; + var parts = [], // readily assembled parts + batch = []; // char codes for batch processing + while (count--) { + var value = /*? GET('srcOffset++', 'src') */, + shift = 4; + for (var i=0; i<2; ++i) { + var c = (value >>> shift) & 0xf; + switch (c) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: + batch.push(0x30 + c); + break; + case 10: case 11: case 12: case 13: case 14: case 15: + batch.push(0x37 + c); + break; + } + shift = 0; + } + if (batch.length > 1023) { + parts.push(String.fromCharCode.apply(String, batch)); + batch.length = 0; + } + } + if (batch.length > 0) { + if (parts.length === 0) + return String.fromCharCode.apply(String, batch); + parts.push(String.fromCharCode.apply(String, batch)); + } + return parts.join(''); +} + +/** + * Calculates the number of bytes required to store a hexadecimal JavaScript string. + * @param {string} src Source string + * @param {number} srcOffset Source offset + * @param {number} count Number of char codes to calculate + * @returns {number} Number of bytes required + * @inner + */ +function hex_calculate(src, srcOffset, count) { + if ((count % 2) !== 0) + throw Error("illegal number of hex char codes: "+count); + return count / 2; +} + +ByteBuffer.registerEncoding("hex", hex_encode, hex_decode, hex_calculate); diff --git a/src/encodings/impl/utf8.js b/src/encodings/impl/utf8.js new file mode 100644 index 0000000..109a8a1 --- /dev/null +++ b/src/encodings/impl/utf8.js @@ -0,0 +1,126 @@ +// encodings/impl/utf8 + +/** + * Encodes a standard JavaScript string to UTF8 bytes. + * @param {string} src Source string + * @param {number} srcOffset Source offset + * @param {!ByteBuffer} dst Destination ByteBuffer + * @param {number} dstOffset Destination offset + * @param {number} count Number of char codes to encode + * @returns {number} Number of bytes encoded + * @inner + */ +function utf8_encode(src, srcOffset, dst, dstOffset, count) { + if (count === 0) + return 0; + var n = 0; + //? // SET(varValue, varOffset, varTarget) with varTarget referencing a ByteBuffer + do { + var cc = src.charCodeAt(srcOffset++); + --count; + if (cc < 0x80) { + n += 1; + //? SET('cc', 'dstOffset++', 'dst'); + } else if (cc < 0x800) { + n += 2; + //? SET('0xC0 | (cc >> 6)', 'dstOffset++', 'dst'); + //? SET('0x80 | (cc & 0x3F)', 'dstOffset++', 'dst'); + } else if (cc < 0xD800 || cc >= 0xE000) { + n += 3; + //? SET('0xE0 | (cc >> 12)', 'dstOffset++', 'dst'); + //? SET('0x80 | ((cc >> 6) & 0x3F)', 'dstOffset++', 'dst'); + //? SET('0x80 | (cc & 0x3F)', 'dstOffset++', 'dst'); + } else { // surrogate + if (count === 0) + throw Error("truncated utf8 surrogate"); + cc = 0x10000 + (((cc & 0x3FF) << 10) | (src.charCodeAt(srcOffset++) & 0x3FF)); + --count; + n += 4; + //? SET('0xF0 | (cc >> 18)', 'dstOffset++', 'dst'); + //? SET('0x80 | ((cc >> 12) & 0x3F)', 'dstOffset++', 'dst'); + //? SET('0x80 | ((cc >> 6) & 0x3F)', 'dstOffset++', 'dst'); + //? SET('0x80 | (cc & 0x3F)', 'dstOffset++', 'dst'); + } + } while (count > 0); + return n; +} + +/** + * Decodes UTF8 bytes to a standard JavaScript string. + * @param {!ByteBuffer} src Source ByteBuffer + * @param {number} srcOffset Source offset + * @param {number} count Number of bytes to decode + * @returns {string} Decoded string + * @inner + */ +function utf8_decode(src, srcOffset, count) { + if (count === 0) + return ""; + var parts = [], // readily assembled parts + batch = []; // char codes for batch processing + //? // GET(varOffset, varTarget) with varTarget referencing a ByteBuffer + while (count--) { + var c = /*? GET('srcOffset++', 'src') */, + c2, c3; + switch (c >> 4) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + batch.push(c); + break; + case 12: case 13: + if (count < 1) + throw Error("truncated utf8 sequence"); + c2 = /*? GET('srcOffset++', 'src') */; + --count; + batch.push(((c & 0x1F) << 6) | (c2 & 0x3F)); + break; + case 14: + if (count < 2) + throw Error("truncated utf8 sequence"); + c2 = /*? GET('srcOffset++', 'src') */; + c3 = /*? GET('srcOffset++', 'src') */; + count -= 2; + batch.push(((c & 0x0F) << 12) | ((c2 & 0x3F) << 6) | ((c3 & 0x3F) << 0)); + break; + } + if (batch.length > 1023) { + parts.push(String.fromCharCode.apply(String, batch)); + batch.length = 0; + } + } + if (batch.length > 0) { + if (parts.length === 0) + return String.fromCharCode.apply(String, batch); + parts.push(String.fromCharCode.apply(String, batch)); + } + return parts.join(''); +} + +/** + * Calculates the number of UTF8 bytes required to store a standard JavaScript string. + * @param {string} src Source string + * @param {number} srcOffset Source offset + * @param {number} count Number of char codes to calculate + * @returns {number} Number of bytes required + * @inner + */ +function utf8_calculate(src, srcOffset, count) { + if (count === 0) + return 0; + var n = 0; + do { + var cc = src.charCodeAt(srcOffset++); + --count; + if (cc < 0x80) { + n += 1; + } else if (cc < 0x800) { + n += 2; + } else if (cc < 0xD800 || cc >= 0xE000) { + n += 3; + } else { + n += 4; + } + } while (count > 0); + return n; +} + +ByteBuffer.registerEncoding("utf8", utf8_encode, utf8_decode, utf8_calculate); diff --git a/src/encodings/utf8.js b/src/encodings/utf8.js new file mode 100644 index 0000000..c1f7b54 --- /dev/null +++ b/src/encodings/utf8.js @@ -0,0 +1,71 @@ +//? if (UTF8) { +// utfx-embeddable + +//? include("../../node_modules/utfx/dist/utfx-embeddable.js"); + +// encodings/utf8 + +/** + * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded + * string. + * @returns {string} Hex encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ +ByteBufferPrototype.toUTF8 = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + //? ASSERT_RANGE(); + } + //? if (NODE) + return this.buffer.toString("utf8", begin, end); + //? else { + var sd; try { + utfx.decodeUTF8toUTF16(function() { + //? if (DATAVIEW) + return begin < end ? this.view.getUint8(begin++) : null; + //? else + return begin < end ? this.view[begin++] : null; + }.bind(this), sd = stringDestination()); + } catch (e) { + if (begin !== end) + throw RangeError("Illegal range: Truncated data, "+begin+" != "+end); + } + return sd(); + //? } +}; + +/** + * Decodes an UTF8 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ +ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) { + if (!noAssert) + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + //? if (NODE) { + var bb = new ByteBuffer(0, littleEndian, noAssert); + bb.buffer = new Buffer(str, "utf8"); + bb.limit = bb.buffer.length; + //? } else { + var bb = new ByteBuffer(utfx.calculateUTF16asUTF8(stringSource(str), true)[1], littleEndian, noAssert), + i = 0; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + //? if (DATAVIEW) + bb.view.setUint8(i++, b); + //? else + bb.view[i++] = b; + }); + bb.limit = i; + //? } + return bb; +}; + +//? } \ No newline at end of file diff --git a/src/helpers.js b/src/helpers.js new file mode 100644 index 0000000..3e27c45 --- /dev/null +++ b/src/helpers.js @@ -0,0 +1,143 @@ +// helpers +//? if (NODE) { + +/** + * @type {!Buffer} + * @inner + */ +var EMPTY_BUFFER = new Buffer(0); +//? } else { + +/** + * @type {!ArrayBuffer} + * @inner + */ +var EMPTY_BUFFER = new ArrayBuffer(0); +//? } +//? if (!INLINE) { + +/** + * Asserts that a value is an integer and returns the type-safe value. + * @param {number} value Value to assert + * @param {boolean=} unsigned Whether explicitly unsigned + * @returns {number} Type-safe value + * @throws {TypeError} If `value` is not an integer + * @inner + */ +function assertInteger(value, unsigned) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+offset+" (not an integer)"); + return unsigned ? value >>> 0 : value | 0; +} + +/** + * Asserts that a value is an integer or Long. + * @param {number|!Long} value Value to assert + * @param {boolean=} unsigned Whether explicitly unsigned + * @returns {number|!Long} Type-safe value + * @throws {TypeError} If `value` is not an integer or Long + * @inner + */ +function assertLong(value, unsigned) { + if (typeof value === 'number') { + return Long.fromNumber(value, unsigned); + } else if (typeof value === 'string') { + return Long.fromString(value, unsigned); + } else if (value && value instanceof Long) { + if (typeof unsigned !== 'undefined') { + if (unsigned && !value.unsigned) return value.toUnsigned(); + if (!unsigned && value.unsigned) return value.toSigned(); + } + return value; + } else + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); +} + +/** + * Asserts that `min <= offset <= cap-size` and returns the type-safe offset. + * @param {number} offset Offset to assert + * @param {number} min Minimum offset + * @param {number} cap Cap offset + * @param {number} size Required size in bytes + * @returns {number} Type-safe offset + * @throws {TypeError} If `offset` is not an integer + * @throws {RangeError} If `offset < min || offset > cap-size` + * @inner + */ +function assertOffset(offset, min, cap, size) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset = offset | 0; + if (offset < min || offset > cap-size) + throw RangeError("Illegal offset: "+min+" <= "+value+" <= "+cap+"-"+size); + return offset; +} + +/** + * assertRange return value. + * @type {Array.} + */ +var rangeVal = new Array(2); + +/** + * Asserts that `min <= begin <= end <= cap`. Updates `rangeVal` with the type-safe range. + * @param {number} begin Begin offset + * @param {number} end End offset + * @param {number} min Minimum offset + * @param {number} cap Cap offset + * @throws {TypeError} If `begin` or `end` is not an integer + * @throws {RangeError} If `begin < min || begin > end || end > cap` + * @inner + */ +function assertRange(begin, end, min, cap) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: "+begin+" (not a number)"); + begin = begin | 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: "+range[1]+" (not a number)"); + end = end | 0; + if (begin < min || begin > end || end > cap) + throw RangeError("Illegal range: "+min+" <= "+begin+" <= "+end+" <= "+cap); + rangeVal[0] = begin; rangeVal[1] = end; +} +//? } +//? if (BASE64 || UTF8) { + +/** + * String.fromCharCode reference for compile-time renaming. + * @type {function(...number):string} + * @inner + */ +var stringFromCharCode = String.fromCharCode; + +/** + * Creates a source function for a string. + * @param {string} s String to read from + * @returns {function():number|null} Source function returning the next char code respectively `null` if there are + * no more characters left. + * @throws {TypeError} If the argument is invalid + * @inner + */ +function stringSource(s) { + var i=0; return function() { + return i < s.length ? s.charCodeAt(i++) : null; + }; +} + +/** + * Creates a destination function for a string. + * @returns {function(number=):undefined|string} Destination function successively called with the next char code. + * Returns the final string when called without arguments. + * @inner + */ +function stringDestination() { + var cs = [], ps = []; return function() { + if (arguments.length === 0) + return ps.join('')+stringFromCharCode.apply(String, cs); + if (cs.length + arguments.length > 1024) + ps.push(stringFromCharCode.apply(String, cs)), + cs.length = 0; + Array.prototype.push.apply(cs, arguments); + }; +} +//? } diff --git a/src/macros.js b/src/macros.js new file mode 100644 index 0000000..0726369 --- /dev/null +++ b/src/macros.js @@ -0,0 +1,222 @@ +//?... +// Welcome to the crazy world of MetaScript! Tell it what you need, it will not moan, and there it is. + +// Substitute for the backing buffer's capacity +CAPACITY = NODE ? 'this.buffer.length' : 'this.buffer.byteLength'; + +// Asserts that a variable is an integer +ASSERT_INTEGER = function(varValue, unsigned) { + if (VERBOSE_MS) writeln(__+'// '); + if (INLINE) { + writeln(__+'if (typeof '+varValue+' !== \'number\' || '+varValue+' % 1 !== 0)'); + writeln(__+' throw TypeError("Illegal '+varValue+': "+'+varValue+'+" (not an integer)");'); + writeln(__+varValue+' '+(unsigned ? '>>>' : '|')+'= 0;'); + } else { + writeln(__+varValue+' = assertInteger('+varValue+(typeof unsigned !== 'undefined' ? ', '+unsigned : '')+');'); + } + if (VERBOSE_MS) writeln(__+'// '); +}; + +// Asserts that a variable is a number or Long +ASSERT_LONG = function(varValue, unsigned) { + if (typeof varValue === 'undefined') varValue = 'value'; + if (VERBOSE_MS) writeln(__+'// '); + if (INLINE) { + writeln(__+'if (typeof '+varValue+' === \'number\')'); + writeln(__+' '+varValue+' = Long.fromNumber('+varValue+');'); + writeln(__+'else if (typeof '+varValue+' === \'string\')'); + writeln(__+' '+varValue+' = Long.fromString('+varValue+');'); + if (typeof unsigned !== 'undefined') { // When explicitly specified only + writeln(__+'else if ('+varValue+' && '+varValue+' instanceof Long)'); + if (unsigned) { + writeln(__+' if (!'+varValue+'.unsigned) '+varValue+' = '+varValue+'.toUnsigned();'); + } else { + writeln(__+' if ('+varValue+'.unsigned) '+varValue+' = '+varValue+'.toSigned();'); + } + writeln(__+'else'); + } else { + writeln(__+'else if (!('+varValue+' && '+varValue+' instanceof Long))'); + } + writeln(__+' throw TypeError("Illegal '+varValue+': "+'+varValue+'+" (not an integer or Long)");'); + } else { + writeln(__+varValue+' = assertLong('+varValue+(typeof unsigned !== 'undefined' ? ', '+unsigned : '')+');'); + } + if (VERBOSE_MS) writeln(__+'// '); +}; + +// Casts a variable to a Long if necessary +LONG = function(varValue, unsigned) { + if (typeof varValue === 'undefined') varValue = 'value'; + if (VERBOSE_MS) writeln(__+'// '); + writeln(__+'if (typeof '+varValue+' === \'number\')'); + writeln(__+' '+varValue+' = Long.fromNumber('+varValue+(typeof unsigned === 'boolean' ? ', '+unsigned : '')+');'); + writeln(__+'else if (typeof '+varValue+' === \'string\')'); + writeln(__+' '+varValue+' = Long.fromString('+varValue+(typeof unsigned === 'boolean' ? ', '+unsigned : '')+');'); + if (typeof unsigned === 'boolean') { + writeln(__+'else if ('+varValue+'.unsigned !== '+unsigned+') '+varValue+' = '+varValue+'.'+(unsigned ? 'toUnsigned' : 'toSigned')+'();'); + } + if (VERBOSE_MS) writeln(__+'// '); +}; + +// Asserts that an offset is valid +ASSERT_OFFSET = function(size, varOffset) { + if (typeof size === 'undefined') size = 0; + if (typeof varOffset === 'undefined') varOffset = 'offset'; + if (VERBOSE_MS) writeln(__+'// '); + if (INLINE) { + writeln(__+'if (typeof '+varOffset+' !== \'number\' || '+varOffset+' % 1 !== 0)'); + writeln(__+' throw TypeError("Illegal '+varOffset+': "+'+varOffset+'+" (not an integer)");'); + writeln(__+varOffset+' >>>= 0;'); + writeln(__+'if ('+varOffset+' < 0 || '+varOffset+' + '+size+' > '+CAPACITY+')'); + writeln(__+' throw RangeError("Illegal '+varOffset+': 0 <= "+'+varOffset+'+" (+"+'+size+'+") <= "+'+CAPACITY+');'); + } else { + writeln(__+varOffset+' = assertOffset('+varOffset+', 0, '+CAPACITY+', '+size+');'); + } + if (VERBOSE_MS) writeln(__+'// '); +}; + +// Asserts that a range is valid +ASSERT_RANGE = function(varBegin, varEnd) { + if (typeof varBegin === 'undefined') varBegin = 'begin'; + if (typeof varEnd === 'undefined') varEnd = 'end'; + if (VERBOSE_MS) writeln(__+'// '); + if (INLINE) { + writeln(__+'if (typeof '+varBegin+' !== \'number\' || '+varBegin+' % 1 !== 0)'); + writeln(__+' throw TypeError("Illegal '+varBegin+': Not an integer");'); + writeln(__+varBegin+' >>>= 0;'); + writeln(__+'if (typeof '+varEnd+' !== \'number\' || '+varEnd+' % 1 !== 0)'); + writeln(__+' throw TypeError("Illegal '+varEnd+': Not an integer");'); + writeln(__+varEnd+' >>>= 0;'); + writeln(__+'if ('+varBegin+' < 0 || '+varBegin+' > '+varEnd+' || '+varEnd+' > '+CAPACITY+')'); + writeln(__+' throw RangeError("Illegal range: 0 <= "+'+varBegin+'+" <= "+'+varEnd+'+" <= "+'+CAPACITY+');'); + } else { + writeln(__+'assertRange('+varBegin+', '+varEnd+', 0, '+CAPACITY+');'); + writeln(__+varBegin+' = rangeVal[0]; '+varEnd+' = rangeVal[1];'); + } + if (VERBOSE_MS) writeln(__+'// '); +}; + +// ENSURE_CAPACITY counter in case that multiple calls are used in a single method +var ECN = 0; + +// Ensures that a ByteBuffer is backed by a buffer that takes `size` additional capacity +ENSURE_CAPACITY = function(size, varOffset) { + if (typeof varOffset === 'undefined') varOffset = 'offset'; + if (VERBOSE_MS) writeln(__+'// '); + if (INLINE) { + writeln(__+varOffset+' += '+size+';'); + writeln(__+'var capacity'+ECN+' = '+CAPACITY+';'); + writeln(__+'if ('+varOffset+' > capacity'+ECN+')'); + writeln(__+' this.resize((capacity'+ECN+' *= 2) > '+varOffset+' ? capacity'+ECN+' : '+varOffset+');'); + writeln(__+varOffset+' -= '+size+';'); + } else { + writeln(__+'this.ensureCapacity('+varOffset+'+'+size+');'); + } + if (VERBOSE_MS) writeln(__+'// '); + ++ECN; +}; + +// Sets up a relative operation if `size` is omitted, else increases offset by `size` +RELATIVE = function(size, varOffset, varRelOffset) { + if (VERBOSE_MS) writeln(__+'// '); + if (typeof size === 'undefined') { + if (typeof varOffset === 'undefined') varOffset = "offset"; + if (typeof varRelOffset === 'undefined') varRelOffset = "this.offset"; + writeln(__+'var relative = typeof '+varOffset+' === \'undefined\';'); + writeln(__+'if (relative) '+varOffset+' = '+varRelOffset+';'); + } else { + if (typeof varOffset === 'undefined') varOffset = "this.offset"; + writeln(__+'if (relative) this.offset += '+size+';'); + } + if (VERBOSE_MS) writeln(__+'// '); +}; + +// Reads an uint32 from an array +READ_UINT32_ARRAY = function(varValue, varOffset, varTarget, varEndian) { + if (typeof varValue === 'undefined') varValue = 'value'; + if (typeof varOffset === 'undefined') varOffset = 'offset'; + if (typeof varTarget === 'undefined') varTarget = NODE ? 'this.buffer' : 'this.view'; + var ____ = typeof varEndian !== 'boolean' ? ' ' : ''; + if (VERBOSE_MS) writeln(__+'// '); + if (NODE || !DATAVIEW) { + if (typeof varEndian !== 'boolean') + writeln(__+'if ('+(varEndian || 'this.littleEndian')+') {'); + if (typeof varEndian !== 'boolean' || varEndian === true) { + writeln(__+____+varValue+' = '+varTarget+'['+varOffset+'+2] << 16;'); + writeln(__+____+varValue+' |= '+varTarget+'['+varOffset+'+1] << 8;'); + writeln(__+____+varValue+' |= '+varTarget+'['+varOffset+' ];'); + writeln(__+____+varValue+' += '+varTarget+'['+varOffset+'+3] << 24 >>> 0;'); + } + if (typeof varEndian !== 'boolean') + writeln(__+'} else {'); + if (typeof varEndian !== 'boolean' || varEndian === false) { + writeln(__+____+varValue+' = '+varTarget+'['+varOffset+'+1] << 16;'); + writeln(__+____+varValue+' |= '+varTarget+'['+varOffset+'+2] << 8;'); + writeln(__+____+varValue+' |= '+varTarget+'['+varOffset+'+3];'); + writeln(__+____+varValue+' += '+varTarget+'['+varOffset+' ] << 24 >>> 0;'); + } + if (typeof varEndian !== 'boolean') + writeln(__+'}'); + } else { + writeln(__+varTarget+'.getUint32('+varOffset+', '+varEndian+');'); + } + if (VERBOSE_MS) writeln(__+'// '); +}; + +// Writes an uint32 to an array +WRITE_UINT32_ARRAY = function(varValue, varOffset, varTarget, varEndian) { + if (typeof varValue === 'undefined') varValue = 'value'; + if (typeof varOffset === 'undefined') varOffset = 'offset'; + if (typeof varTarget === 'undefined') varTarget = NODE ? 'this.buffer' : 'this.view'; + var ____ = typeof varEndian !== 'boolean' ? ' ' : ''; + if (VERBOSE_MS) writeln(__+'// '); + if (NODE || !DATAVIEW) { + if (typeof varEndian !== 'boolean') + writeln(__+'if ('+(varEndian || 'this.littleEndian')+') {'); + if (typeof varEndian !== 'boolean' || varEndian === true) { + writeln(__+____+varTarget+'['+varOffset+'+3] = ('+varValue+' >>> 24) & 0xFF;'); + writeln(__+____+varTarget+'['+varOffset+'+2] = ('+varValue+' >>> 16) & 0xFF;'); + writeln(__+____+varTarget+'['+varOffset+'+1] = ('+varValue+' >>> 8) & 0xFF;'); + writeln(__+____+varTarget+'['+varOffset+' ] = '+varValue+' & 0xFF;'); + } + if (typeof varEndian !== 'boolean') + writeln(__+'} else {'); + if (typeof varEndian !== 'boolean' || varEndian === false) { + writeln(__+____+varTarget+'['+varOffset+' ] = ('+varValue+' >>> 24) & 0xFF;'); + writeln(__+____+varTarget+'['+varOffset+'+1] = ('+varValue+' >>> 16) & 0xFF;'); + writeln(__+____+varTarget+'['+varOffset+'+2] = ('+varValue+' >>> 8) & 0xFF;'); + writeln(__+____+varTarget+'['+varOffset+'+3] = '+varValue+' & 0xFF;'); + } + if (typeof varEndian !== 'boolean') + writeln(__+'}'); + } else { + writeln(__+varTarget+'.setUint32('+varValue+', '+varOffset+', '+varEndian+');'); + } + if (VERBOSE_MS) writeln(__+'// '); +}; + +SET = function(varValue, varOffset, varTarget) { // with varTarget referencing a ByteBuffer + if (typeof varValue === 'undefined') varValue = 'value'; + if (typeof varOffset === 'undefined') varOffset = 'offset'; + if (typeof varTarget === 'undefined') varTarget = 'this'; + if (NODE) { + writeln(__+varTarget+'.buffer['+varOffset+'] = '+varValue+';'); + } else if (DATAVIEW) { + writeln(__+varTarget+'.view.setUint8('+varValue+', '+varOffset+');'); + } else { + writeln(__+varTarget+'.view['+varOffset+'] = '+varValue+';'); + } +}; + +GET = function(varOffset, varTarget) { // with varTarget referencing a ByteBuffer + if (typeof varOffset === 'undefined') varOffset = 'offset'; + if (typeof varTarget === 'undefined') varTarget = 'this'; + if (NODE) { + write(varTarget+'.buffer['+varOffset+']'); + } else if (DATAVIEW) { + write(varTarget+'.view.getUint8('+varOffset+')'); + } else { + write(varTarget+'.view['+varOffset+']'); + } +}; +//?. \ No newline at end of file diff --git a/src/methods/append.js b/src/methods/append.js new file mode 100644 index 0000000..1dcefa7 --- /dev/null +++ b/src/methods/append.js @@ -0,0 +1,75 @@ +/** + * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended + * data's length. +//? if (NODE) { + * @param {!ByteBuffer|!Buffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its + * offsets will be modified according to the performed read operation. +//? } else { + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its offsets + * will be modified according to the performed read operation. +//? } + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|` + * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|` + */ +ByteBufferPrototype.append = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var length = source.limit - source.offset; + if (length <= 0) return this; // Nothing to append + //? ENSURE_CAPACITY('length'); + //? if (NODE) + source.buffer.copy(this.buffer, offset, source.offset, source.limit); + //? else if (DATAVIEW) + new Uint8Array(this.buffer, offset).set(new Uint8Array(source.buffer).subarray(source.offset, source.limit)); + //? else + this.view.set(source.view.subarray(source.offset, source.limit), offset); + source.offset += length; + //? RELATIVE('length'); + return this; +}; + +/** + * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents at and after the + specified offset up to the length of this ByteBuffer's data. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#append + */ +ByteBufferPrototype.appendTo = function(target, offset) { + target.append(this, offset); + return this; +}; + +/** + * Writes a payload of bytes. This is an alias of {@link ByteBuffer#append}. + * @function + //? if (NODE) { + * @param {!ByteBuffer|!Buffer|!ArrayBuffer|!Uint8Array|string} source Data to write. If `source` is a ByteBuffer, its + * offsets will be modified according to the performed read operation. + //? } else { + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to write. If `source` is a ByteBuffer, its offsets + * will be modified according to the performed read operation. + //? } + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeBytes = ByteBufferPrototype.append; diff --git a/src/methods/assert.js b/src/methods/assert.js new file mode 100644 index 0000000..52edfbd --- /dev/null +++ b/src/methods/assert.js @@ -0,0 +1,12 @@ +/** + * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to + * disable them if your code already makes sure that everything is valid. + * @param {boolean} assert `true` to enable assertions, otherwise `false` + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.assert = function(assert) { + this.noAssert = !assert; + return this; +}; + diff --git a/src/methods/capacity.js b/src/methods/capacity.js new file mode 100644 index 0000000..8b6b34a --- /dev/null +++ b/src/methods/capacity.js @@ -0,0 +1,8 @@ +/** + * Gets the capacity of this ByteBuffer's backing buffer. + * @returns {number} Capacity of the backing buffer + * @expose + */ +ByteBufferPrototype.capacity = function() { + return /*?= CAPACITY */; +}; diff --git a/src/methods/clear.js b/src/methods/clear.js new file mode 100644 index 0000000..be5aa28 --- /dev/null +++ b/src/methods/clear.js @@ -0,0 +1,13 @@ +/** + * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the + * backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.clear = function() { + this.offset = 0; + this.limit = /*?= CAPACITY */; + this.markedOffset = -1; + return this; +}; + diff --git a/src/methods/clone.js b/src/methods/clone.js new file mode 100644 index 0000000..67bded2 --- /dev/null +++ b/src/methods/clone.js @@ -0,0 +1,34 @@ +/** + * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset}, + * {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}. + * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false` + * @returns {!ByteBuffer} Cloned instance + * @expose + */ +ByteBufferPrototype.clone = function(copy) { + var bb = new ByteBuffer(0, this.littleEndian, this.noAssert); + if (copy) { + //? if (NODE) { + var buffer = new Buffer(this.buffer.length); + this.buffer.copy(buffer); + bb.buffer = buffer; + //? } else { + bb.buffer = new ArrayBuffer(this.buffer.byteLength); + //? if (DATAVIEW) { + new Uint8Array(bb.buffer).set(this.buffer); + bb.view = new DataView(bb.buffer); + //? } else { + bb.view = new Uint8Array(bb.buffer); + //? } + //? } + } else { + bb.buffer = this.buffer; + //? if (!NODE) + bb.view = this.view; + } + bb.offset = this.offset; + bb.markedOffset = this.markedOffset; + bb.limit = this.limit; + return bb; +}; + diff --git a/src/methods/compact.js b/src/methods/compact.js new file mode 100644 index 0000000..8888378 --- /dev/null +++ b/src/methods/compact.js @@ -0,0 +1,49 @@ +/** + * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes + * between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and + * adapt {@link ByteBuffer#markedOffset} to the same relative position if set. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.compact = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + //? ASSERT_RANGE(); + } + if (begin === 0 && end === /*?= CAPACITY */) + return this; // Already compacted + var len = end - begin; + if (len === 0) { + this.buffer = EMPTY_BUFFER; + //? if (!NODE) + this.view = null; + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = 0; + return this; + } + //? if (NODE) { + var buffer = new Buffer(len); + this.buffer.copy(buffer, 0, begin, end); + this.buffer = buffer; + //? } else if (DATAVIEW) { + var buffer = new ArrayBuffer(len); + new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(begin, end)); + this.buffer = buffer; + this.view = new DataView(buffer); + //? } else { + var buffer = new ArrayBuffer(len); + var view = new Uint8Array(buffer); + view.set(this.view.subarray(begin, end)); + this.buffer = buffer; + this.view = view; + //? } + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = len; + return this; +}; + diff --git a/src/methods/copy.js b/src/methods/copy.js new file mode 100644 index 0000000..38eea6e --- /dev/null +++ b/src/methods/copy.js @@ -0,0 +1,73 @@ +/** + * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Copy + * @expose + */ +ByteBufferPrototype.copy = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + //? ASSERT_RANGE(); + } + if (begin === end) + return new ByteBuffer(0, this.littleEndian, this.noAssert); + var capacity = end - begin, + bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert); + bb.offset = 0; + bb.limit = capacity; + if (bb.markedOffset >= 0) bb.markedOffset -= begin; + this.copyTo(bb, 0, begin, end); + return bb; +}; + +/** + * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset} + * by the number of bytes copied if omitted. + * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the + * number of bytes copied if omitted. + * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) { + var relative, + targetRelative; + if (!this.noAssert) { + if (!ByteBuffer.isByteBuffer(target)) + throw TypeError("Illegal target: Not a ByteBuffer"); + } + targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0; + sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0; + sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0; + + //? var TARGET_CAPACITY = NODE ? 'target.buffer.length' : 'target.buffer.byteLength'; + if (targetOffset < 0 || targetOffset > /*?= TARGET_CAPACITY */) + throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+/*?= TARGET_CAPACITY */); + if (sourceOffset < 0 || sourceLimit > /*?= CAPACITY */) + throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+/*?= CAPACITY */); + + var len = sourceLimit - sourceOffset; + if (len === 0) + return target; // Nothing to copy + + target.ensureCapacity(targetOffset + len); + + //? if (NODE) + this.buffer.copy(target.buffer, targetOffset, sourceOffset, sourceLimit); + //? else if (DATAVIEW) + new Uint8Array(target.buffer).set(new Uint8Array(this.buffer).subarray(sourceOffset, sourceLimit), targetOffset); + //? else + target.view.set(this.view.subarray(sourceOffset, sourceLimit), targetOffset); + + if (relative) this.offset += len; + if (targetRelative) target.offset += len; + + return this; +}; + diff --git a/src/methods/ensureCapacity.js b/src/methods/ensureCapacity.js new file mode 100644 index 0000000..6c30fd1 --- /dev/null +++ b/src/methods/ensureCapacity.js @@ -0,0 +1,15 @@ +/** + * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the + * current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity, + * the required capacity will be used instead. + * @param {number} capacity Required capacity + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.ensureCapacity = function(capacity) { + var current = /*?= CAPACITY */; + if (current < capacity) + return this.resize((current *= 2) > capacity ? current : capacity); + return this; +}; + diff --git a/src/methods/fill.js b/src/methods/fill.js new file mode 100644 index 0000000..a83d882 --- /dev/null +++ b/src/methods/fill.js @@ -0,0 +1,35 @@ +/** + * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {number|string} value Byte value to fill with. If given as a string, the first character is used. + * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} this + * @expose + * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes + */ +ByteBufferPrototype.fill = function(value, begin, end) { + //? RELATIVE(undefined, 'begin'); + if (typeof value === 'string' && value.length > 0) + value = value.charCodeAt(0); + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + //? ASSERT_INTEGER('value'); + //? ASSERT_RANGE(); + } + if (begin >= end) + return this; // Nothing to fill + //? if (NODE) { + this.buffer.fill(value, begin, end); + begin = end; + //? } else if (DATAVIEW) { + while (begin < end) this.view.setUint8(begin++, value); + //? } else { + while (begin < end) this.view[begin++] = value; + //? } + if (relative) this.offset = begin; + return this; +}; + diff --git a/src/methods/flip.js b/src/methods/flip.js new file mode 100644 index 0000000..ca93329 --- /dev/null +++ b/src/methods/flip.js @@ -0,0 +1,11 @@ +/** + * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and + * `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.flip = function() { + this.limit = this.offset; + this.offset = 0; + return this; +}; diff --git a/src/methods/mark.js b/src/methods/mark.js new file mode 100644 index 0000000..c81c791 --- /dev/null +++ b/src/methods/mark.js @@ -0,0 +1,17 @@ +/** + * Marks an offset on this ByteBuffer to be used later. + * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}. + * @returns {!ByteBuffer} this + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @see ByteBuffer#reset + * @expose + */ +ByteBufferPrototype.mark = function(offset) { + offset = typeof offset === 'undefined' ? this.offset : offset; + if (!this.noAssert) { + //? ASSERT_OFFSET(); + } + this.markedOffset = offset; + return this; +}; diff --git a/src/methods/order.js b/src/methods/order.js new file mode 100644 index 0000000..2d11d67 --- /dev/null +++ b/src/methods/order.js @@ -0,0 +1,36 @@ +/** + * Sets the byte order. + * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.order = function(littleEndian) { + if (!this.noAssert) { + if (typeof littleEndian !== 'boolean') + throw TypeError("Illegal littleEndian: Not a boolean"); + } + this.littleEndian = !!littleEndian; + return this; +}; + +/** + * Switches (to) little endian byte order. + * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.LE = function(littleEndian) { + this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true; + return this; +}; + +/** + * Switches (to) big endian byte order. + * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.BE = function(bigEndian) { + this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false; + return this; +}; diff --git a/src/methods/prepend.js b/src/methods/prepend.js new file mode 100644 index 0000000..879c1e8 --- /dev/null +++ b/src/methods/prepend.js @@ -0,0 +1,87 @@ +/** + * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + //? if (NODE) { + * @param {!ByteBuffer|string||!Buffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be modified + * according to the performed read operation. + //? } else { + * @param {!ByteBuffer|string|!ArrayBuffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be + * modified according to the performed read operation. + //? } + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|` + * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|` + */ +ByteBufferPrototype.prepend = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var len = source.limit - source.offset; + if (len <= 0) return this; // Nothing to prepend + var diff = len - offset; + if (diff > 0) { // Not enough space before offset, so resize + move + //? if (NODE) { + var buffer = new Buffer(this.buffer.length + diff); + this.buffer.copy(buffer, len, offset, this.buffer.length); + this.buffer = buffer; + //? } else if (DATAVIEW) { + var buffer = new ArrayBuffer(this.buffer.byteLength + diff); + var arrayView = new Uint8Array(buffer); + arrayView.set(new Uint8Array(this.buffer).subarray(offset, this.buffer.byteLength), len); + this.buffer = buffer; + this.view = new DataView(buffer); + //? } else { + var buffer = new ArrayBuffer(this.buffer.byteLength + diff); + var view = new Uint8Array(buffer); + view.set(this.view.subarray(offset, this.buffer.byteLength), len); + this.buffer = buffer; + this.view = view; + //? } + this.offset += diff; + if (this.markedOffset >= 0) this.markedOffset += diff; + this.limit += diff; + offset += diff; + }/*? if (!NODE) { */ else { + var arrayView = new Uint8Array(this.buffer); + } + //? } + //? if (NODE) + source.buffer.copy(this.buffer, offset - len, source.offset, source.limit); + //? else if (DATAVIEW) + arrayView.set(new Uint8Array(source.buffer).subarray(source.offset, source.limit), offset - len); + //? else + this.view.set(source.view.subarray(source.offset, source.limit), offset - len); + + source.offset = source.limit; + if (relative) + this.offset -= len; + return this; +}; + +/** + * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#prepend + */ +ByteBufferPrototype.prependTo = function(target, offset) { + target.prepend(this, offset); + return this; +}; diff --git a/src/methods/printDebug.js b/src/methods/printDebug.js new file mode 100644 index 0000000..4e089bd --- /dev/null +++ b/src/methods/printDebug.js @@ -0,0 +1,16 @@ +//? if (DEBUG) { +/** + * Prints debug information about this ByteBuffer's contents. + * @param {function(string)=} out Output function to call, defaults to console.log + * @expose + */ +ByteBufferPrototype.printDebug = function(out) { + if (typeof out !== 'function') out = console.log.bind(console); + out( + this.toString()+"\n"+ + "-------------------------------------------------------------------\n"+ + this.toDebug(/* columns */ true) + ); +}; + +//? } diff --git a/src/methods/remaining.js b/src/methods/remaining.js new file mode 100644 index 0000000..a23e21d --- /dev/null +++ b/src/methods/remaining.js @@ -0,0 +1,9 @@ +/** + * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}, so this returns `limit - offset`. + * @returns {number} Remaining readable bytes. May be negative if `offset > limit`. + * @expose + */ +ByteBufferPrototype.remaining = function() { + return this.limit - this.offset; +}; diff --git a/src/methods/reset.js b/src/methods/reset.js new file mode 100644 index 0000000..3665eaa --- /dev/null +++ b/src/methods/reset.js @@ -0,0 +1,17 @@ +/** + * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark} + * before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been + * marked, sets `offset = 0`. + * @returns {!ByteBuffer} this + * @see ByteBuffer#mark + * @expose + */ +ByteBufferPrototype.reset = function() { + if (this.markedOffset >= 0) { + this.offset = this.markedOffset; + this.markedOffset = -1; + } else { + this.offset = 0; + } + return this; +}; diff --git a/src/methods/resize.js b/src/methods/resize.js new file mode 100644 index 0000000..b015795 --- /dev/null +++ b/src/methods/resize.js @@ -0,0 +1,39 @@ +/** + * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that + * large or larger. + * @param {number} capacity Capacity required + * @returns {!ByteBuffer} this + * @throws {TypeError} If `capacity` is not a number + * @throws {RangeError} If `capacity < 0` + * @expose + */ +ByteBufferPrototype.resize = function(capacity) { + if (!this.noAssert) { + //? ASSERT_INTEGER('capacity'); + if (capacity < 0) + throw RangeError("Illegal capacity: 0 <= "+capacity); + } + //? if (NODE) { + if (this.buffer.length < capacity) { + var buffer = new Buffer(capacity); + this.buffer.copy(buffer); + this.buffer = buffer; + } + //? } else { + if (this.buffer.byteLength < capacity) { + //? if (DATAVIEW) { + var buffer = new ArrayBuffer(capacity); + new Uint8Array(buffer).set(new Uint8Array(this.buffer)); + this.buffer = buffer; + this.view = new DataView(buffer); + //? } else { + var buffer = new ArrayBuffer(capacity); + var view = new Uint8Array(buffer); + view.set(this.view); + this.buffer = buffer; + this.view = view; + //? } + } + //? } + return this; +}; diff --git a/src/methods/reverse.js b/src/methods/reverse.js new file mode 100644 index 0000000..b249d2a --- /dev/null +++ b/src/methods/reverse.js @@ -0,0 +1,25 @@ +/** + * Reverses this ByteBuffer's contents. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.reverse = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + //? ASSERT_RANGE(); + } + if (begin === end) + return this; // Nothing to reverse + //? if (NODE) + Array.prototype.reverse.call(this.buffer.slice(begin, end)); + //? else if (DATAVIEW) { + Array.prototype.reverse.call(new Uint8Array(this.buffer).subarray(begin, end)); + this.view = new DataView(this.buffer); // FIXME: Why exactly is this necessary? + //? } else { + Array.prototype.reverse.call(this.view.subarray(begin, end)); + //? } + return this; +}; diff --git a/src/methods/skip.js b/src/methods/skip.js new file mode 100644 index 0000000..5dfb7a2 --- /dev/null +++ b/src/methods/skip.js @@ -0,0 +1,19 @@ +/** + * Skips the next `length` bytes. This will just advance + * @param {number} length Number of bytes to skip. May also be negative to move the offset back. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.skip = function(length) { + if (!this.noAssert) { + //? ASSERT_INTEGER('length'); + } + var offset = this.offset + length; + if (!this.noAssert) { + if (offset < 0 || offset > /*?= CAPACITY */) + throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+/*?= CAPACITY */); + } + this.offset = offset; + return this; +}; + diff --git a/src/methods/slice.js b/src/methods/slice.js new file mode 100644 index 0000000..20c5767 --- /dev/null +++ b/src/methods/slice.js @@ -0,0 +1,18 @@ +/** + * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer} + * @expose + */ +ByteBufferPrototype.slice = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + //? ASSERT_RANGE(); + } + var bb = this.clone(); + bb.offset = begin; + bb.limit = end; + return bb; +}; diff --git a/src/methods/static/accessor.js b/src/methods/static/accessor.js new file mode 100644 index 0000000..5a24a40 --- /dev/null +++ b/src/methods/static/accessor.js @@ -0,0 +1,13 @@ +/** + * Gets the accessor type. + * @returns {Function} `Buffer` under node.js, `Uint8Array` respectively `DataView` in the browser (classes) + * @expose + */ +ByteBuffer.accessor = function() { + //? if (NODE) + return Buffer; + //? else if (DATAVIEW) + return DataView; + //? else + return Uint8Array; +}; diff --git a/src/methods/static/allocate.js b/src/methods/static/allocate.js new file mode 100644 index 0000000..41ab26b --- /dev/null +++ b/src/methods/static/allocate.js @@ -0,0 +1,14 @@ +/** + * Allocates a new ByteBuffer backed by a buffer of the specified capacity. + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} + * @expose + */ +ByteBuffer.allocate = function(capacity, littleEndian, noAssert) { + return new ByteBuffer(capacity, littleEndian, noAssert); +}; + diff --git a/src/methods/static/concat.js b/src/methods/static/concat.js new file mode 100644 index 0000000..d5f2841 --- /dev/null +++ b/src/methods/static/concat.js @@ -0,0 +1,55 @@ +/** + * Concatenates multiple ByteBuffers into one. +//? if (NODE) { + * @param {!Array.} buffers Buffers to concatenate +//? } else { + * @param {!Array.} buffers Buffers to concatenate +//? } + * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary", + * defaults to "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults + * to {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} Concatenated ByteBuffer + * @expose + */ +ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) { + if (typeof encoding === 'boolean' || typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + var capacity = 0; + for (var i=0, k=buffers.length, length; i 0) capacity += length; + } + if (capacity === 0) + return new ByteBuffer(0, littleEndian, noAssert); + var bb = new ByteBuffer(capacity, littleEndian, noAssert), + bi; + //? if (!NODE && DATAVIEW) + var view = new Uint8Array(bb.buffer); + i=0; while (i} buffer Anything that can be wrapped +//? } else { + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string|!Array.} buffer Anything that can be wrapped +//? } + * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to + * "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer` + * @expose + */ +ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) { + if (typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + if (typeof buffer === 'string') { + if (typeof encoding === 'undefined') + encoding = "utf8"; + switch (encoding) { + //? if (BASE64) { + case "base64": + return ByteBuffer.fromBase64(buffer, littleEndian); + //? } if (HEX) { + case "hex": + return ByteBuffer.fromHex(buffer, littleEndian); + //? } if (BINARY) { + case "binary": + return ByteBuffer.fromBinary(buffer, littleEndian); + //? } if (UTF8) { + case "utf8": + return ByteBuffer.fromUTF8(buffer, littleEndian); + //? } if (DEBUG) { + case "debug": + return ByteBuffer.fromDebug(buffer, littleEndian); + //? } + default: + throw Error("Unsupported encoding: "+encoding); + } + } + if (buffer === null || typeof buffer !== 'object') + throw TypeError("Illegal buffer"); + var bb; + if (ByteBuffer.isByteBuffer(buffer)) { + bb = ByteBufferPrototype.clone.call(buffer); + bb.markedOffset = -1; + return bb; + } + //? if (NODE) { + var i = 0, + k = 0, + b; + if (buffer instanceof Uint8Array) { // Extract bytes from Uint8Array + b = new Buffer(buffer.length); + if (memcpy) { // Fast + memcpy(b, 0, buffer.buffer, buffer.byteOffset, buffer.byteOffset + buffer.length); + } else { // Slow + for (i=0, k=buffer.length; i 0) { // Avoid references to more than one EMPTY_BUFFER + bb.buffer = buffer; + bb.limit = buffer.length; + } + //? } else { + if (buffer instanceof Uint8Array) { // Extract ArrayBuffer from Uint8Array + bb = new ByteBuffer(0, littleEndian, noAssert); + if (buffer.length > 0) { // Avoid references to more than one EMPTY_BUFFER + bb.buffer = buffer.buffer; + bb.offset = buffer.byteOffset; + bb.limit = buffer.byteOffset + buffer.byteLength; + //? if (DATAVIEW) + bb.view = new DataView(buffer.buffer); + //? else + bb.view = new Uint8Array(buffer.buffer); + } + } else if (buffer instanceof ArrayBuffer) { // Reuse ArrayBuffer + bb = new ByteBuffer(0, littleEndian, noAssert); + if (buffer.byteLength > 0) { + bb.buffer = buffer; + bb.offset = 0; + bb.limit = buffer.byteLength; + //? if (DATAVIEW) + bb.view = buffer.byteLength > 0 ? new DataView(buffer) : null; + //? else + bb.view = buffer.byteLength > 0 ? new Uint8Array(buffer) : null; + } + } else if (Object.prototype.toString.call(buffer) === "[object Array]") { // Create from octets + bb = new ByteBuffer(buffer.length, littleEndian, noAssert); + bb.limit = buffer.length; + for (var i=0; i} value Array of booleans to write + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ +ByteBufferPrototype.writeBitSet = function(value, offset) { + //? RELATIVE() + if (!this.noAssert) { + if (!(value instanceof Array)) + throw TypeError("Illegal BitSet: Not an array"); + //? ASSERT_OFFSET(); + } + + var start = offset, + bits = value.length, + bytes = (bits >> 3), + bit = 0, + k; + + offset += this.writeVarint32(bits,offset); + + while(bytes--) { + k = (!!value[bit++] & 1) | + ((!!value[bit++] & 1) << 1) | + ((!!value[bit++] & 1) << 2) | + ((!!value[bit++] & 1) << 3) | + ((!!value[bit++] & 1) << 4) | + ((!!value[bit++] & 1) << 5) | + ((!!value[bit++] & 1) << 6) | + ((!!value[bit++] & 1) << 7); + this.writeByte(k,offset++); + } + + if(bit < bits) { + var m = 0; k = 0; + while(bit < bits) k = k | ((!!value[bit++] & 1) << (m++)); + this.writeByte(k,offset++); + } + + if (relative) { + this.offset = offset; + return this; + } + return offset - start; +} + +/** + * Reads a BitSet as an array of booleans. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {Array + * @expose + */ +ByteBufferPrototype.readBitSet = function(offset) { + //? RELATIVE() + + var ret = this.readVarint32(offset), + bits = ret.value, + bytes = (bits >> 3), + bit = 0, + value = [], + k; + + offset += ret.length; + + while(bytes--) { + k = this.readByte(offset++); + value[bit++] = !!(k & 0x01); + value[bit++] = !!(k & 0x02); + value[bit++] = !!(k & 0x04); + value[bit++] = !!(k & 0x08); + value[bit++] = !!(k & 0x10); + value[bit++] = !!(k & 0x20); + value[bit++] = !!(k & 0x40); + value[bit++] = !!(k & 0x80); + } + + if(bit < bits) { + var m = 0; + k = this.readByte(offset++); + while(bit < bits) value[bit++] = !!((k >> (m++)) & 1); + } + + if (relative) { + this.offset = offset; + } + return value; +} diff --git a/src/types/bytes/bytes.js b/src/types/bytes/bytes.js new file mode 100644 index 0000000..18fc3d0 --- /dev/null +++ b/src/types/bytes/bytes.js @@ -0,0 +1,17 @@ +/** + * Reads the specified number of bytes. + * @param {number} length Number of bytes to read + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ +ByteBufferPrototype.readBytes = function(length, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET('length'); + } + var slice = this.slice(offset, offset + length); + //? RELATIVE('length'); + return slice; +}; + diff --git a/src/types/floats/float32.js b/src/types/floats/float32.js new file mode 100644 index 0000000..a9208ae --- /dev/null +++ b/src/types/floats/float32.js @@ -0,0 +1,81 @@ +//? if (FLOAT32) { +// types/floats/float32 +//? if (!NODE && !DATAVIEW) { + +//? include("ieee754.js"); +//? } + +/** + * Writes a 32bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeFloat32 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + //? ASSERT_OFFSET(); + } + //? ENSURE_CAPACITY(4); + //? if (NODE) { // FIXME: Is there any way to inline the following in a sane way? + this.littleEndian + ? this.buffer.writeFloatLE(value, offset) + : this.buffer.writeFloatBE(value, offset); + //? } else if (DATAVIEW) + this.view.setFloat32(offset, value, this.littleEndian); + //? else + ieee754_write(this.view, value, offset, this.littleEndian, 23, 4); + //? RELATIVE(4); + return this; +}; +//? if (ALIASES) { + +/** + * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32; +//? } + +/** + * Reads a 32bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ +ByteBufferPrototype.readFloat32 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(4); + } + //? if (NODE) { + var value = this.littleEndian + ? this.buffer.readFloatLE(offset, true) + : this.buffer.readFloatBE(offset, true); + //? } else if (DATAVIEW) + var value = this.view.getFloat32(offset, this.littleEndian); + //? else + var value = ieee754_read(this.view, offset, this.littleEndian, 23, 4); + //? RELATIVE(4); + return value; +}; +//? if (ALIASES) { + +/** + * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ +ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32; +//? } + +//? } \ No newline at end of file diff --git a/src/types/floats/float64.js b/src/types/floats/float64.js new file mode 100644 index 0000000..5a2584c --- /dev/null +++ b/src/types/floats/float64.js @@ -0,0 +1,77 @@ +//? if (FLOAT64) { +// types/floats/float64 + +/** + * Writes a 64bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeFloat64 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + //? ASSERT_OFFSET(); + } + //? ENSURE_CAPACITY(8); + //? if (NODE) { + this.littleEndian + ? this.buffer.writeDoubleLE(value, offset) + : this.buffer.writeDoubleBE(value, offset); + //? } else if (DATAVIEW) + this.view.setFloat64(offset, value, this.littleEndian); + //? else + ieee754_write(this.view, value, offset, this.littleEndian, 52, 8); + //? RELATIVE(8); + return this; +}; +//? if (ALIASES) { + +/** + * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64; +//? } + +/** + * Reads a 64bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ +ByteBufferPrototype.readFloat64 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(8); + } + //? if (NODE) { + var value = this.littleEndian + ? this.buffer.readDoubleLE(offset) + : this.buffer.readDoubleBE(offset); + //? } else if (DATAVIEW) + var value = this.view.getFloat64(offset, this.littleEndian); + //? else + var value = ieee754_read(this.view, offset, this.littleEndian, 52, 8); + //? RELATIVE(8); + return value; +}; +//? if (ALIASES) { + +/** + * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ +ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64; +//? } + +//? } \ No newline at end of file diff --git a/src/types/floats/ieee754.js b/src/types/floats/ieee754.js new file mode 100644 index 0000000..f03bf7f --- /dev/null +++ b/src/types/floats/ieee754.js @@ -0,0 +1,130 @@ +/* + ieee754 - https://github.com/feross/ieee754 + + The MIT License (MIT) + + Copyright (c) Feross Aboukhadijeh + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/** + * Reads an IEEE754 float from a byte array. + * @param {!Array} buffer + * @param {number} offset + * @param {boolean} isLE + * @param {number} mLen + * @param {number} nBytes + * @returns {number} + * @inner + */ +function ieee754_read(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); +} + +/** + * Writes an IEEE754 float to a byte array. + * @param {!Array} buffer + * @param {number} value + * @param {number} offset + * @param {boolean} isLE + * @param {number} mLen + * @param {number} nBytes + * @inner + */ +function ieee754_write(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; +} diff --git a/src/types/ints/int16.js b/src/types/ints/int16.js new file mode 100644 index 0000000..bc609d5 --- /dev/null +++ b/src/types/ints/int16.js @@ -0,0 +1,167 @@ +//? if (INT16) { +// types/ints/int16 + +/** + * Writes a 16bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ +ByteBufferPrototype.writeInt16 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_INTEGER('value'); + //? ASSERT_OFFSET(); + } + //? ENSURE_CAPACITY(2); + //? if (NODE || !DATAVIEW) { var dst = NODE ? 'this.buffer' : 'this.view'; + if (this.littleEndian) { + /*?= dst */[offset+1] = (value & 0xFF00) >>> 8; + /*?= dst */[offset ] = value & 0x00FF; + } else { + /*?= dst */[offset] = (value & 0xFF00) >>> 8; + /*?= dst */[offset+1] = value & 0x00FF; + } + //? } else + this.view.setInt16(offset, value, this.littleEndian); + //? RELATIVE(2); + return this; +}; +//? if (ALIASES) { + +/** + * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ +ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16; +//? } + +/** + * Reads a 16bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ +ByteBufferPrototype.readInt16 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(2); + } + //? if (NODE || !DATAVIEW) { var dst = NODE ? 'this.buffer' : 'this.view'; + var value = 0; + if (this.littleEndian) { + value = /*?= dst */[offset ]; + value |= /*?= dst */[offset+1] << 8; + } else { + value = /*?= dst */[offset ] << 8; + value |= /*?= dst */[offset+1]; + } + if ((value & 0x8000) === 0x8000) value = -(0xFFFF - value + 1); // Cast to signed + //? } else + var value = this.view.getInt16(offset, this.littleEndian); + //? RELATIVE(2); + return value; +}; +//? if (ALIASES) { + +/** + * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ +ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16; +//? } + +/** + * Writes a 16bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ +ByteBufferPrototype.writeUint16 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_INTEGER('value', true); + //? ASSERT_OFFSET(); + } + //? ENSURE_CAPACITY(2); + //? if (NODE || !DATAVIEW) { var dst = NODE ? 'this.buffer' : 'this.view'; + if (this.littleEndian) { + /*?= dst */[offset+1] = (value & 0xFF00) >>> 8; + /*?= dst */[offset ] = value & 0x00FF; + } else { + /*?= dst */[offset] = (value & 0xFF00) >>> 8; + /*?= dst */[offset+1] = value & 0x00FF; + } + //? } else + this.view.setUint16(offset, value, this.littleEndian); + //? RELATIVE(2); + return this; +}; + +/** + * Writes a 16bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ +ByteBufferPrototype.writeUInt16 = ByteBufferPrototype.writeUint16; + +/** + * Reads a 16bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ +ByteBufferPrototype.readUint16 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(2); + } + //? if (NODE || !DATAVIEW) { var dst = NODE ? 'this.buffer' : 'this.view'; + var value = 0; + if (this.littleEndian) { + value = /*?= dst */[offset ]; + value |= /*?= dst */[offset+1] << 8; + } else { + value = /*?= dst */[offset ] << 8; + value |= /*?= dst */[offset+1]; + } + //? } else + var value = this.view.getUint16(offset, this.littleEndian); + //? RELATIVE(2); + return value; +}; + +/** + * Reads a 16bit unsigned integer. This is an alias of {@link ByteBuffer#readUint16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ +ByteBufferPrototype.readUInt16 = ByteBufferPrototype.readUint16; + +//? } \ No newline at end of file diff --git a/src/types/ints/int32.js b/src/types/ints/int32.js new file mode 100644 index 0000000..7ae48af --- /dev/null +++ b/src/types/ints/int32.js @@ -0,0 +1,125 @@ +//? if (INT32) { +// types/ints/int32 + +/** + * Writes a 32bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ +ByteBufferPrototype.writeInt32 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_INTEGER('value'); + //? ASSERT_OFFSET(); + } + //? ENSURE_CAPACITY(4); + //? if (NODE || !DATAVIEW) { + //? WRITE_UINT32_ARRAY(); + //? } else + this.view.setInt32(offset, value, this.littleEndian); + //? RELATIVE(4); + return this; +}; +//? if (ALIASES) { + +/** + * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ +ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32; +//? } + +/** + * Reads a 32bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ +ByteBufferPrototype.readInt32 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(4); + } + //? if (NODE || !DATAVIEW) { + var value = 0; + //? READ_UINT32_ARRAY(); + value |= 0; // Cast to signed + //? } else + var value = this.view.getInt32(offset, this.littleEndian); + //? RELATIVE(4); + return value; +}; +//? if (ALIASES) { + +/** + * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ +ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32; +//? } + +/** + * Writes a 32bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ +ByteBufferPrototype.writeUint32 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_INTEGER('value', true); + //? ASSERT_OFFSET(); + } + //? ENSURE_CAPACITY(4); + //? if (NODE || !DATAVIEW) { + //? WRITE_UINT32_ARRAY(); + //? } else + this.view.setUint32(offset, value, this.littleEndian); + //? RELATIVE(4); + return this; +}; + +/** + * Writes a 32bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ +ByteBufferPrototype.writeUInt32 = ByteBufferPrototype.writeUint32; + +/** + * Reads a 32bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ +ByteBufferPrototype.readUint32 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(4); + } + //? if (NODE || !DATAVIEW) { + var value = 0; + //? READ_UINT32_ARRAY(); + //? } else + var value = this.view.getUint32(offset, this.littleEndian); + //? RELATIVE(4); + return value; +}; + +/** + * Reads a 32bit unsigned integer. This is an alias of {@link ByteBuffer#readUint32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ +ByteBufferPrototype.readUInt32 = ByteBufferPrototype.readUint32; + +//? } \ No newline at end of file diff --git a/src/types/ints/int64.js b/src/types/ints/int64.js new file mode 100644 index 0000000..f930a29 --- /dev/null +++ b/src/types/ints/int64.js @@ -0,0 +1,194 @@ +//? if (INT64) { +// types/ints/int64 + +if (Long) { + + /** + * Writes a 64bit signed integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt64 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_LONG('value'); + //? ASSERT_OFFSET(); + } + //? LONG('value'); + //? ENSURE_CAPACITY(8); + //? if (NODE || !DATAVIEW) { + var lo = value.low, + hi = value.high; + if (this.littleEndian) { + //? WRITE_UINT32_ARRAY('lo', undefined, undefined, true); + offset += 4; + //? WRITE_UINT32_ARRAY('hi', undefined, undefined, true); + } else { + //? WRITE_UINT32_ARRAY('hi', undefined, undefined, false); + offset += 4; + //? WRITE_UINT32_ARRAY('lo', undefined, undefined, false); + } + //? } else { + if (this.littleEndian) { + this.view.setInt32(offset , value.low , true); + this.view.setInt32(offset+4, value.high, true); + } else { + this.view.setInt32(offset , value.high, false); + this.view.setInt32(offset+4, value.low , false); + } + //? } + //? RELATIVE(8); + return this; + }; + //? if (ALIASES) { + + /** + * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64; + //? } + + /** + * Reads a 64bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readInt64 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(8); + } + //? if (NODE || !DATAVIEW) { + var lo = 0, + hi = 0; + if (this.littleEndian) { + //? READ_UINT32_ARRAY('lo', undefined, undefined, true); + offset += 4; + //? READ_UINT32_ARRAY('hi', undefined, undefined, true); + } else { + //? READ_UINT32_ARRAY('hi', undefined, undefined, false); + offset += 4; + //? READ_UINT32_ARRAY('lo', undefined, undefined, false); + } + var value = new Long(lo, hi, false); + //? } else { + var value = this.littleEndian + ? new Long(this.view.getInt32(offset , true ), this.view.getInt32(offset+4, true ), false) + : new Long(this.view.getInt32(offset+4, false), this.view.getInt32(offset , false), false); + //? } + //? RELATIVE(8); + return value; + }; + //? if (ALIASES) { + + /** + * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64; + //? } + + /** + * Writes a 64bit unsigned integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint64 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_LONG('value'); + //? ASSERT_OFFSET(); + } + //? LONG('value'); + //? ENSURE_CAPACITY(8); + //? if (NODE || !DATAVIEW) { + var lo = value.low, + hi = value.high; + if (this.littleEndian) { + //? WRITE_UINT32_ARRAY('lo', undefined, undefined, true); + offset += 4; + //? WRITE_UINT32_ARRAY('hi', undefined, undefined, true); + } else { + //? WRITE_UINT32_ARRAY('hi', undefined, undefined, false); + offset += 4; + //? WRITE_UINT32_ARRAY('lo', undefined, undefined, false); + } + //? } else { + if (this.littleEndian) { + this.view.setInt32(offset , value.low , true); + this.view.setInt32(offset+4, value.high, true); + } else { + this.view.setInt32(offset , value.high, false); + this.view.setInt32(offset+4, value.low , false); + } + //? } + //? RELATIVE(8); + return this; + }; + + /** + * Writes a 64bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint64}. + * @function + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt64 = ByteBufferPrototype.writeUint64; + + /** + * Reads a 64bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUint64 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(8); + } + //? if (NODE || !DATAVIEW) { + var lo = 0, + hi = 0; + if (this.littleEndian) { + //? READ_UINT32_ARRAY('lo', undefined, undefined, true); + offset += 4; + //? READ_UINT32_ARRAY('hi', undefined, undefined, true); + } else { + //? READ_UINT32_ARRAY('hi', undefined, undefined, false); + offset += 4; + //? READ_UINT32_ARRAY('lo', undefined, undefined, false); + } + var value = new Long(lo, hi, true); + //? } else { + var value = this.littleEndian + ? new Long(this.view.getInt32(offset , true ), this.view.getInt32(offset+4, true ), true) + : new Long(this.view.getInt32(offset+4, false), this.view.getInt32(offset , false), true); + //? } + //? RELATIVE(8); + return value; + }; + + /** + * Reads a 64bit unsigned integer. This is an alias of {@link ByteBuffer#readUint64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUInt64 = ByteBufferPrototype.readUint64; + +} // Long + +//? } \ No newline at end of file diff --git a/src/types/ints/int8.js b/src/types/ints/int8.js new file mode 100644 index 0000000..37b0eef --- /dev/null +++ b/src/types/ints/int8.js @@ -0,0 +1,137 @@ +//? if (INT8) { +// types/ints/int8 + +/** + * Writes an 8bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeInt8 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_INTEGER('value'); + //? ASSERT_OFFSET(); + } + //? ENSURE_CAPACITY(1); + //? if (NODE) + this.buffer[offset] = value; + //? else if (DATAVIEW) + this.view.setInt8(offset, value); + //? else + this.view[offset] = value; + //? RELATIVE(1); + return this; +}; + +/** + * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8; + +/** + * Reads an 8bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ +ByteBufferPrototype.readInt8 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(1); + } + //? if (NODE) { + var value = this.buffer[offset]; + if ((value & 0x80) === 0x80) value = -(0xFF - value + 1); // Cast to signed + //? } else if (DATAVIEW) { + var value = this.view.getInt8(offset); + //? } else { + var value = this.view[offset]; + if ((value & 0x80) === 0x80) value = -(0xFF - value + 1); // Cast to signed + //? } + //? RELATIVE(1); + return value; +}; +//? if (ALIASES) { + +/** + * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ +ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8; +//? } + +/** + * Writes an 8bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeUint8 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_INTEGER('value', true); + //? ASSERT_OFFSET(); + } + //? ENSURE_CAPACITY(1); + //? if (NODE) + this.buffer[offset] = value; + //? else if (DATAVIEW) + this.view.setUint8(offset, value); + //? else + this.view[offset] = value; + //? RELATIVE(1); + return this; +}; + +/** + * Writes an 8bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ +ByteBufferPrototype.writeUInt8 = ByteBufferPrototype.writeUint8; + +/** + * Reads an 8bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ +ByteBufferPrototype.readUint8 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(1); + } + //? if (NODE) + var value = this.buffer[offset]; + //? else if (DATAVIEW) + var value = this.view.getUint8(offset); + //? else + var value = this.view[offset]; + //? RELATIVE(1); + return value; +}; + +/** + * Reads an 8bit unsigned integer. This is an alias of {@link ByteBuffer#readUint8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ +ByteBufferPrototype.readUInt8 = ByteBufferPrototype.readUint8; + +//? } \ No newline at end of file diff --git a/src/types/strings/cstring.js b/src/types/strings/cstring.js new file mode 100644 index 0000000..62b7f47 --- /dev/null +++ b/src/types/strings/cstring.js @@ -0,0 +1,110 @@ +//? if (CSTRING) { +// types/strings/cstring + +/** + * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL + * characters itself. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * contained in `str` + 1 if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written + * @expose + */ +ByteBufferPrototype.writeCString = function(str, offset) { + //? RELATIVE(); + var i, + k = str.length; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + for (i=0; i= this.buffer.length) + throw RangeError("Index out of range: "+offset+" <= "+this.buffer.length); + temp = this.buffer[offset++]; + } while (temp !== 0); + var str = this.buffer.toString("utf8", start, offset-1); + if (relative) { + this.offset = offset; + return str; + } else { + return { + "string": str, + "length": offset - start + }; + } + //? } else { // getUint8 asserts on its own + var sd, b = -1; + utfx.decodeUTF8toUTF16(function() { + if (b === 0) return null; + if (offset >= this.limit) + throw RangeError("Illegal range: Truncated data, "+offset+" < "+this.limit); + //? if (DATAVIEW) + b = this.view.getUint8(offset++); + //? else + b = this.view[offset++]; + return b === 0 ? null : b; + }.bind(this), sd = stringDestination(), true); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + //? } +}; + +//? } diff --git a/src/types/strings/istring.js b/src/types/strings/istring.js new file mode 100644 index 0000000..2bd26a5 --- /dev/null +++ b/src/types/strings/istring.js @@ -0,0 +1,81 @@ +//? if (ISTRING) { +// types/strings/istring + +/** + * Writes a length as uint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ +ByteBufferPrototype.writeIString = function(str, offset) { + //? RELATIVE(); + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + //? ASSERT_OFFSET(); + } + var start = offset, + k; + //? if (NODE) { + k = Buffer.byteLength(str, "utf8"); + //? ENSURE_CAPACITY('4+k'); + //? WRITE_UINT32_ARRAY('k'); + offset += 4; + offset += this.buffer.write(str, offset, k, "utf8"); + //? } else { + k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1]; + //? ENSURE_CAPACITY('4+k'); + //? if (DATAVIEW) + this.view.setUint32(offset, k, this.littleEndian); + //? else + //? WRITE_UINT32_ARRAY('k'); + offset += 4; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + //? if (DATAVIEW) + this.view.setUint8(offset++, b); + //? else + this.view[offset++] = b; + }.bind(this)); + if (offset !== start + 4 + k) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+4+k)); + //? } + if (relative) { + this.offset = offset; + return this; + } + return offset - start; +}; + +/** + * Reads a length as uint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ +ByteBufferPrototype.readIString = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(4); + } + var start = offset; + var len = this.readUint32(offset); + var str = this.readUTF8String(len, ByteBuffer.METRICS_BYTES, offset += 4); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } +}; + +//? } \ No newline at end of file diff --git a/src/types/strings/utf8string.js b/src/types/strings/utf8string.js new file mode 100644 index 0000000..5b25c6b --- /dev/null +++ b/src/types/strings/utf8string.js @@ -0,0 +1,214 @@ +//? if (UTF8STRING && UTF8) { +// types/strings/utf8string + +/** + * Metrics representing number of UTF8 characters. Evaluates to `c`. + * @type {string} + * @const + * @expose + */ +ByteBuffer.METRICS_CHARS = 'c'; + +/** + * Metrics representing number of bytes. Evaluates to `b`. + * @type {string} + * @const + * @expose + */ +ByteBuffer.METRICS_BYTES = 'b'; + +/** + * Writes an UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ +ByteBufferPrototype.writeUTF8String = function(str, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(); + } + var k; + //? if (NODE) { + k = Buffer.byteLength(str, "utf8"); + //? ENSURE_CAPACITY('k'); + offset += this.buffer.write(str, offset, k, "utf8"); + if (relative) { + this.offset = offset; + return this; + } + return k; + //? } else { + var start = offset; + k = utfx.calculateUTF16asUTF8(stringSource(str))[1]; + //? ENSURE_CAPACITY('k'); + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + //? if (DATAVIEW) + this.view.setUint8(offset++, b); + //? else + this.view[offset++] = b; + }.bind(this)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + //? } +}; +//? if (ALIASES) { + +/** + * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}. + * @function + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ +ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String; +//? } + +/** + * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's + * `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 characters + * @expose + */ +ByteBuffer.calculateUTF8Chars = function(str) { + return utfx.calculateUTF16asUTF8(stringSource(str))[0]; +}; + +/** + * Calculates the number of UTF8 bytes of a string. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ +ByteBuffer.calculateUTF8Bytes = function(str) { + //? if (NODE) { + if (typeof str !== 'string') + throw TypeError("Illegal argument: "+(typeof str)); + return Buffer.byteLength(str, "utf8"); + //? } else + return utfx.calculateUTF16asUTF8(stringSource(str))[1]; +}; +//? if (ALIASES) { + +/** + * Calculates the number of UTF8 bytes of a string. This is an alias of {@link ByteBuffer.calculateUTF8Bytes}. + * @function + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ +ByteBuffer.calculateString = ByteBuffer.calculateUTF8Bytes; +//? } + +/** + * Reads an UTF8 encoded string. + * @param {number} length Number of characters or bytes to read. + * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ +ByteBufferPrototype.readUTF8String = function(length, metrics, offset) { + if (typeof metrics === 'number') { + offset = metrics; + metrics = undefined; + } + //? RELATIVE(); + if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS; + if (!this.noAssert) { + //? ASSERT_INTEGER('length'); + //? ASSERT_OFFSET(); + } + var i = 0, + start = offset, + //? if (NODE) + temp, + sd; + if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser + sd = stringDestination(); + utfx.decodeUTF8(function() { + //? if (NODE) + return i < length && offset < this.limit ? this.buffer[offset++] : null; + //? else if (DATAVIEW) + return i < length && offset < this.limit ? this.view.getUint8(offset++) : null; + //? else + return i < length && offset < this.limit ? this.view[offset++] : null; + }.bind(this), function(cp) { + ++i; utfx.UTF8toUTF16(cp, sd); + }); + if (i !== length) + throw RangeError("Illegal range: Truncated data, "+i+" == "+length); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + } else if (metrics === ByteBuffer.METRICS_BYTES) { + if (!this.noAssert) { + //? ASSERT_OFFSET('length'); + } + //? if (NODE) { + temp = this.buffer.toString("utf8", offset, offset+length); + if (relative) { + this.offset += length; + return temp; + } else { + return { + 'string': temp, + 'length': length + }; + } + //? } else { + var k = offset + length; + utfx.decodeUTF8toUTF16(function() { + //? if (DATAVIEW) + return offset < k ? this.view.getUint8(offset++) : null; + //? else + return offset < k ? this.view[offset++] : null; + }.bind(this), sd = stringDestination(), this.noAssert); + if (offset !== k) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+k); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + 'string': sd(), + 'length': offset - start + }; + } + //? } + } else + throw TypeError("Unsupported metrics: "+metrics); +}; +//? if (ALIASES) { + +/** + * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}. + * @function + * @param {number} length Number of characters or bytes to read + * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ +ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String; +//? } + +//? } \ No newline at end of file diff --git a/src/types/strings/vstring.js b/src/types/strings/vstring.js new file mode 100644 index 0000000..67d3a5c --- /dev/null +++ b/src/types/strings/vstring.js @@ -0,0 +1,78 @@ +//? if (VSTRING && VARINTS && VARINT32) { +// types/strings/vstring + +/** + * Writes a length as varint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ +ByteBufferPrototype.writeVString = function(str, offset) { + //? RELATIVE() + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + //? ASSERT_OFFSET(); + } + var start = offset, + k, l; + //? if (NODE) { + k = Buffer.byteLength(str, "utf8"); + l = ByteBuffer.calculateVarint32(k); + //? ENSURE_CAPACITY('l+k'); + offset += this.writeVarint32(k, offset); + offset += this.buffer.write(str, offset, k, "utf8"); + //? } else { + k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1]; + l = ByteBuffer.calculateVarint32(k); + //? ENSURE_CAPACITY('l+k'); + offset += this.writeVarint32(k, offset); + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + //? if (DATAVIEW) + this.view.setUint8(offset++, b); + //? else + this.view[offset++] = b; + }.bind(this)); + if (offset !== start+k+l) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+k+l)); + //? } + if (relative) { + this.offset = offset; + return this; + } + return offset - start; +}; + +/** + * Reads a length as varint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ +ByteBufferPrototype.readVString = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(1); + } + var start = offset; + var len = this.readVarint32(offset); + var str = this.readUTF8String(len['value'], ByteBuffer.METRICS_BYTES, offset += len['length']); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } +}; + +//? } diff --git a/src/types/varints/varint32.js b/src/types/varints/varint32.js new file mode 100644 index 0000000..60b39d2 --- /dev/null +++ b/src/types/varints/varint32.js @@ -0,0 +1,164 @@ +//? if (VARINT32) { +// types/varints/varint32 + +/** + * Maximum number of bytes required to store a 32bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ +ByteBuffer.MAX_VARINT32_BYTES = 5; + +/** + * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer. + * @param {number} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES} + * @expose + */ +ByteBuffer.calculateVarint32 = function(value) { + // ref: src/google/protobuf/io/coded_stream.cc + value = value >>> 0; + if (value < 1 << 7 ) return 1; + else if (value < 1 << 14) return 2; + else if (value < 1 << 21) return 3; + else if (value < 1 << 28) return 4; + else return 5; +}; + +/** + * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding. + * @param {number} n Signed 32bit integer + * @returns {number} Unsigned zigzag encoded 32bit integer + * @expose + */ +ByteBuffer.zigZagEncode32 = function(n) { + return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h +}; + +/** + * Decodes a zigzag encoded signed 32bit integer. + * @param {number} n Unsigned zigzag encoded 32bit integer + * @returns {number} Signed 32bit integer + * @expose + */ +ByteBuffer.zigZagDecode32 = function(n) { + return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h +}; + +/** + * Writes a 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ +ByteBufferPrototype.writeVarint32 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_INTEGER('value'); + //? ASSERT_OFFSET(); + } + var size = ByteBuffer.calculateVarint32(value), + b; + //? ENSURE_CAPACITY('size'); + value >>>= 0; + while (value >= 0x80) { + b = (value & 0x7f) | 0x80; + //? if (NODE) + this.buffer[offset++] = b; + //? else if (DATAVIEW) + this.view.setUint8(offset++, b); + //? else + this.view[offset++] = b; + value >>>= 7; + } + //? if (NODE) + this.buffer[offset++] = value; + //? else if (DATAVIEW) + this.view.setUint8(offset++, value); + //? else + this.view[offset++] = value; + if (relative) { + this.offset = offset; + return this; + } + return size; +}; + +/** + * Writes a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ +ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) { + return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset); +}; + +/** + * Reads a 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available + * to fully decode the varint. + * @expose + */ +ByteBufferPrototype.readVarint32 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(1); + } + var c = 0, + value = 0 >>> 0, + b; + do { + if (!this.noAssert && offset > this.limit) { + var err = Error("Truncated"); + err['truncated'] = true; + throw err; + } + //? if (NODE) + b = this.buffer[offset++]; + //? else if (DATAVIEW) + b = this.view.getUint8(offset++); + //? else + b = this.view[offset++]; + if (c < 5) + value |= (b & 0x7f) << (7*c); + ++c; + } while ((b & 0x80) !== 0); + value |= 0; + if (relative) { + this.offset = offset; + return value; + } + return { + "value": value, + "length": c + }; +}; + +/** + * Reads a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ +ByteBufferPrototype.readVarint32ZigZag = function(offset) { + var val = this.readVarint32(offset); + if (typeof val === 'object') + val["value"] = ByteBuffer.zigZagDecode32(val["value"]); + else + val = ByteBuffer.zigZagDecode32(val); + return val; +}; + +//? } \ No newline at end of file diff --git a/src/types/varints/varint64.js b/src/types/varints/varint64.js new file mode 100644 index 0000000..d9cddcc --- /dev/null +++ b/src/types/varints/varint64.js @@ -0,0 +1,208 @@ +//? if (VARINT64) { +// types/varints/varint64 + +if (Long) { + + /** + * Maximum number of bytes required to store a 64bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT64_BYTES = 10; + + /** + * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer. + * @param {number|!Long} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES} + * @expose + */ + ByteBuffer.calculateVarint64 = function(value) { + //? LONG('value'); + // ref: src/google/protobuf/io/coded_stream.cc + var part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + if (part2 == 0) { + if (part1 == 0) { + if (part0 < 1 << 14) + return part0 < 1 << 7 ? 1 : 2; + else + return part0 < 1 << 21 ? 3 : 4; + } else { + if (part1 < 1 << 14) + return part1 < 1 << 7 ? 5 : 6; + else + return part1 < 1 << 21 ? 7 : 8; + } + } else + return part2 < 1 << 7 ? 9 : 10; + }; + + /** + * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding. + * @param {number|!Long} value Signed long + * @returns {!Long} Unsigned zigzag encoded long + * @expose + */ + ByteBuffer.zigZagEncode64 = function(value) { + //? LONG('value', false); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned(); + }; + + /** + * Decodes a zigzag encoded signed 64bit integer. + * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number + * @returns {!Long} Signed long + * @expose + */ + ByteBuffer.zigZagDecode64 = function(value) { + //? LONG('value', false); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned(); + }; + + /** + * Writes a 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64 = function(value, offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_LONG('value'); + //? ASSERT_OFFSET(); + } + //? LONG('value', false); + var size = ByteBuffer.calculateVarint64(value), + part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + //? ENSURE_CAPACITY('size'); + switch (size) { + //? if (NODE || !DATAVIEW) { var dst = NODE ? 'this.buffer' : 'this.view'; + case 10: /*?= dst */[offset+9] = (part2 >>> 7) & 0x01; + case 9 : /*?= dst */[offset+8] = size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F; + case 8 : /*?= dst */[offset+7] = size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F; + case 7 : /*?= dst */[offset+6] = size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F; + case 6 : /*?= dst */[offset+5] = size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F; + case 5 : /*?= dst */[offset+4] = size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F; + case 4 : /*?= dst */[offset+3] = size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F; + case 3 : /*?= dst */[offset+2] = size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F; + case 2 : /*?= dst */[offset+1] = size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F; + case 1 : /*?= dst */[offset ] = size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F; + //? } else { + case 10: this.view.setUint8(offset+9, (part2 >>> 7) & 0x01); + case 9 : this.view.setUint8(offset+8, size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F); + case 8 : this.view.setUint8(offset+7, size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F); + case 7 : this.view.setUint8(offset+6, size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F); + case 6 : this.view.setUint8(offset+5, size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F); + case 5 : this.view.setUint8(offset+4, size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F); + case 4 : this.view.setUint8(offset+3, size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F); + case 3 : this.view.setUint8(offset+2, size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F); + case 2 : this.view.setUint8(offset+1, size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F); + case 1 : this.view.setUint8(offset , size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F); + //? } + } + if (relative) { + this.offset += size; + return this; + } else { + return size; + } + }; + + /** + * Writes a zig-zag encoded 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) { + return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); + }; + + /** + * Reads a 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64 = function(offset) { + //? RELATIVE(); + if (!this.noAssert) { + //? ASSERT_OFFSET(1); + } + // ref: src/google/protobuf/io/coded_stream.cc + var start = offset, + part0 = 0, + part1 = 0, + part2 = 0, + b = 0; + //? if (NODE || !DATAVIEW) { var dst = NODE ? 'this.buffer' : 'this.view'; + b = /*?= dst */[offset++]; part0 = (b & 0x7F) ; if ( b & 0x80 ) { + b = /*?= dst */[offset++]; part0 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = /*?= dst */[offset++]; part0 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = /*?= dst */[offset++]; part0 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = /*?= dst */[offset++]; part1 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = /*?= dst */[offset++]; part1 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = /*?= dst */[offset++]; part1 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = /*?= dst */[offset++]; part1 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = /*?= dst */[offset++]; part2 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = /*?= dst */[offset++]; part2 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + throw Error("Buffer overrun"); }}}}}}}}}} + //? } else { // Asserts on its own + b = this.view.getUint8(offset++); part0 = (b & 0x7F) ; if (b & 0x80) { + b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 7; if (b & 0x80) { + b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 14; if (b & 0x80) { + b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 21; if (b & 0x80) { + b = this.view.getUint8(offset++); part1 = (b & 0x7F) ; if (b & 0x80) { + b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 7; if (b & 0x80) { + b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 14; if (b & 0x80) { + b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 21; if (b & 0x80) { + b = this.view.getUint8(offset++); part2 = (b & 0x7F) ; if (b & 0x80) { + b = this.view.getUint8(offset++); part2 |= (b & 0x7F) << 7; if (b & 0x80) { + throw Error("Buffer overrun"); }}}}}}}}}} + //? } + var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false); + if (relative) { + this.offset = offset; + return value; + } else { + return { + 'value': value, + 'length': offset-start + }; + } + }; + + /** + * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64ZigZag = function(offset) { + var val = this.readVarint64(offset); + if (val && val['value'] instanceof Long) + val["value"] = ByteBuffer.zigZagDecode64(val["value"]); + else + val = ByteBuffer.zigZagDecode64(val); + return val; + }; + +} // Long + +//? } \ No newline at end of file diff --git a/src/wrap-node.js b/src/wrap-node.js new file mode 100644 index 0000000..6d157c3 --- /dev/null +++ b/src/wrap-node.js @@ -0,0 +1,50 @@ +/* + Copyright 2013-2014 Daniel Wirtz + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +//? NODE = true; + +/** + * @license bytebuffer.js (c) 2015 Daniel Wirtz + * Backing buffer / Accessor: node Buffer + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/bytebuffer.js for details + */ +module.exports = (function() { + "use strict"; + + var buffer = require("buffer"), + Buffer = buffer["Buffer"], + Long = require("long"), + memcpy = null; try { memcpy = require("memcpy"); } catch (e) {} + + //? include("ByteBuffer.js"); + + /** + * node-memcpy. This is an optional binding dependency and may not be present. + * @function + * @param {!(Buffer|ArrayBuffer|Uint8Array)} target Destination + * @param {number|!(Buffer|ArrayBuffer)} targetStart Destination start, defaults to 0. + * @param {(!(Buffer|ArrayBuffer|Uint8Array)|number)=} source Source + * @param {number=} sourceStart Source start, defaults to 0. + * @param {number=} sourceEnd Source end, defaults to capacity. + * @returns {number} Number of bytes copied + * @throws {Error} If any index is out of bounds + * @expose + */ + ByteBuffer.memcpy = memcpy; + + return ByteBuffer; + +})(); diff --git a/src/wrap.js b/src/wrap.js new file mode 100644 index 0000000..2a9136e --- /dev/null +++ b/src/wrap.js @@ -0,0 +1,43 @@ +/* + Copyright 2013-2014 Daniel Wirtz + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +/** + * @license bytebuffer.js (c) 2015 Daniel Wirtz +//? if (DATAVIEW) + * Backing buffer: ArrayBuffer, Accessor: DataView +//? else + * Backing buffer: ArrayBuffer, Accessor: Uint8Array + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/bytebuffer.js for details + */ +(function(global, factory) { + + /* AMD */ if (typeof define === 'function' && define["amd"]) + define(["long"], factory); + /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) + module['exports'] = (function() { + var Long; try { Long = require("long"); } catch (e) {} + return factory(Long); + })(); + /* Global */ else + (global["dcodeIO"] = global["dcodeIO"] || {})["ByteBuffer"] = factory(global["dcodeIO"]["Long"]); + +})(this, function(Long) { + "use strict"; + + //? include("bytebuffer.js"); + return ByteBuffer; +}); diff --git a/tests/bench.js b/tests/bench.js new file mode 100644 index 0000000..06e23cc --- /dev/null +++ b/tests/bench.js @@ -0,0 +1,99 @@ +// a simple benchmark utility comparing performance between the different builds. + +// Uint8Array observations (compared to node Buffers) +// - seems to be pretty much equal for byte ops + +// DataView observations (compared to Uint8Array): +// - allocation is about 2 times slower +// - writing is about 5 times (int32) to 10 times (varint) slower +// - reading is about 3 times slower + +// UTF8 encoding observations (compared to node's string/buffer API) +// - the longer the string, the poorer is read/write performance +// - either utfx doesn't cut it yet, or node's bindings simply outperform everything js here + +var ByteBuffer = require("../index.js"), + prettyHrTime = require("pretty-hrtime"); + +var impls = [ + { name: "ByteBufferNB", impl: ByteBuffer.ByteBufferNB }, + { name: "ByteBufferAB", impl: ByteBuffer.ByteBufferAB }, + { name: "ByteBufferAB_DataView", impl: ByteBuffer.ByteBufferAB_DataView } +]; + +var bench = {}; + +bench["allocate"] = function(ByteBuffer, n) { + n = n || 10000; + for (var i=0; i - */ - -/** - * File to use. - * @type {string} - */ -var FILE = "ByteBuffer.min.js"; - -/** - * ByteBuffer. - * @type {ByteBuffer} - */ -var ByteBuffer = require(__dirname+"/../"+FILE); - -/** - * Long. - * @type {Long} - */ -var Long = ByteBuffer.Long; +var ByteBuffer = require("../dist/bytebuffer-node.js"); +var ByteBufferNode = ByteBuffer; +var ByteBufferBrowser = require("../dist/bytebuffer.min.js"); +var ByteBufferBrowser_DataView = require("../dist/bytebuffer-dataview.min.js"); +var pkg = require("../package.json"); /** * Constructs a new Sandbox for module loaders and shim testing. @@ -51,6 +34,7 @@ var Sandbox = function(properties) { this.Uint32Array = function() {}; this.Float32Array = function() {}; this.Float64Array = function() {}; + this.DataView = function() {}; for (var i in properties) { this[i] = properties[i]; } @@ -61,402 +45,638 @@ var Sandbox = function(properties) { }; }; -/** - * Test suite. - * @type {Object.} - */ -var suite = { - - "init": function(test) { +function makeSuite(ByteBuffer) { + var type = ByteBuffer.type(), // Buffer or ArrayBuffer + accessor = ByteBuffer.accessor(), + Long = ByteBuffer.Long; + var suite = {}; + + suite.init = function(test) { + test.ok(require("../index.js")); + if (ByteBuffer == ByteBufferNode) + test.log("\n\n --- ByteBufferNB ---\n".bold.white), + test.log("[optional] node-memcpy is "+(ByteBuffer.memcpy ? "present" : "not present")); + else if (ByteBuffer == ByteBufferBrowser) + test.log("\n\n --- ByteBufferAB ---\n".bold.white); + else if (ByteBuffer == ByteBufferBrowser_DataView) + test.log("\n\n --- ByteBufferAB_DataView ---\n".bold.white); + test.ok(type === Buffer || type === ArrayBuffer); test.ok(typeof ByteBuffer == "function"); - test.ok(typeof ByteBuffer.encodeUTF8Char == "function"); + test.strictEqual(pkg.version, ByteBuffer.VERSION); test.done(); - }, + }; + + suite.base = {}; + + suite.base.allocate = function(test) { + var bb = new ByteBuffer(); + test.ok(bb.buffer instanceof type); + test.equal(bb.offset, 0); + test.equal(bb.limit, ByteBuffer.DEFAULT_CAPACITY); + test.equal(bb.littleEndian, ByteBuffer.DEFAULT_ENDIAN); + test.equal(bb.noAssert, ByteBuffer.DEFAULT_NOASSERT); + if (type === Buffer) + test.equal(bb.buffer.length, bb.capacity()); + else + test.equal(bb.buffer.byteLength, bb.capacity()); + test.equal(bb.capacity(), ByteBuffer.DEFAULT_CAPACITY); + bb = ByteBuffer.allocate(undefined, !ByteBuffer.DEFAULT_ENDIAN, !ByteBuffer.DEFAULT_NOASSERT); + test.equal(bb.capacity(), ByteBuffer.DEFAULT_CAPACITY); + test.equal(bb.littleEndian, !ByteBuffer.DEFAULT_ENDIAN); + test.equal(bb.noAssert, !ByteBuffer.DEFAULT_NOASSERT); - "construct/allocate": function(test) { + // __isByteBuffer__ + test.strictEqual(bb.__isByteBuffer__, true); + bb.__isByteBuffer__ = false; + test.strictEqual(bb.__isByteBuffer__, true); + test.equal(ByteBuffer.isByteBuffer(bb), true); + + // Fixed set of properties + for (var i in bb) + if (bb.hasOwnProperty(i) && ["offset", "markedOffset", "limit", "littleEndian", "noAssert", "buffer", "view"].indexOf(i) < 0) + test.fail("Illegal enumerable property: "+i); + + test.done(); + }; + + suite.base.clone = function(test) { + var bb = new ByteBuffer(1, true, false); + var bb2 = bb.clone(); + test.strictEqual(bb.buffer, bb2.buffer); + test.equal(bb.offset, bb2.offset); + test.equal(bb.limit, bb2.limit); + test.equal(bb.markedOffset, bb2.markedOffset); + test.equal(bb.littleEndian, bb2.littleEndian); + test.equal(bb.noAssert, bb2.noAssert); + test.notStrictEqual(bb, bb2); + test.done(); + }; + + suite.base.assert = function(test) { var bb = new ByteBuffer(); - test.equal(bb.array.byteLength, ByteBuffer.DEFAULT_CAPACITY); - bb = ByteBuffer.allocate(); - test.equal(bb.array.byteLength, ByteBuffer.DEFAULT_CAPACITY); + test.strictEqual(bb.noAssert, false); + test.strictEqual(bb.assert(false), bb); + test.strictEqual(bb.noAssert, true); + test.strictEqual(bb.assert(true), bb); + test.strictEqual(bb.noAssert, false); test.done(); - }, + }; - "wrap(ArrayBuffer)": function(test) { + suite.wrap = {}; + + if (type === Buffer) { + suite.wrap.Buffer = function(test) { + var buf = new Buffer(1); + buf[0] = 0x01; + var bb = ByteBuffer.wrap(buf); + test.strictEqual(bb.capacity(), 1); + test.deepStrictEqual(bb.buffer, buf); + test.strictEqual(bb.toDebug(), "<01>"); + test.done(); + }; + } + + suite.wrap.ArrayBuffer = function(test) { var buf = new ArrayBuffer(1); var bb = ByteBuffer.wrap(buf); - test.strictEqual(bb.array, buf); + test.strictEqual(bb.capacity(), 1); + if (type === ArrayBuffer) + test.strictEqual(bb.buffer, buf); + else + test.ok(bb.buffer instanceof Buffer); test.equal(bb.offset, 0); - test.equal(bb.length, 1); + test.equal(bb.limit, 1); test.done(); - }, + }; - "wrap(Uint8Array)": function(test) { + suite.wrap.Uint8Array = function(test) { + // Full view var buf = new Uint8Array(1); + buf[0] = 0x01; var bb = ByteBuffer.wrap(buf); - test.strictEqual(bb.array, buf.buffer); + test.strictEqual(bb.capacity(), 1); + if (type === ArrayBuffer) + test.strictEqual(bb.buffer, buf.buffer); + else + test.ok(bb.buffer instanceof Buffer); + test.strictEqual(bb.toDebug(), "<01>"); + + // Partial view (not on node, node copies) + if (type === ArrayBuffer) { + buf = new Uint8Array(3); + buf[0] = 0x01; buf[1] = 0x02; buf[2] = 0x03; + buf = new Uint8Array(buf.buffer, 1, 1); + bb = ByteBuffer.wrap(buf); + test.strictEqual(bb.capacity(), 3); + test.strictEqual(bb.toDebug(), "01<02>03"); + } + test.done(); - }, + }; - "wrap(ByteBuffer)": function(test) { // clones - var bb2 = new ByteBuffer(4).writeInt32(0x12345678).flip(); + suite.wrap.Array = function(test) { + var arr = [1,255,-1]; + var bb = ByteBuffer.wrap(arr); + test.strictEqual(bb.capacity(), 3); + test.strictEqual(bb.toDebug(), "<01 FF FF>"); + test.done(); + }; + + suite.wrap.ByteBuffer = function(test) { + var bb2 = ByteBuffer.wrap("\x12\x34\x56\x78", "binary"); bb2.offset = 1; var bb = ByteBuffer.wrap(bb2); - test.strictEqual(bb2.toHex(), bb.toHex()); + test.strictEqual(bb2.offset, bb.offset); + test.strictEqual(bb2.limit, bb.limit); + test.strictEqual(bb2.capacity(), bb.capacity()); + test.strictEqual(bb2.toString("debug"), bb.toString("debug")); test.done(); - }, + }; - "wrap(String)": function(test) { - var bb = ByteBuffer.wrap("test"); - test.equal(bb.offset, 0); - test.equal(bb.length, 4); - test.equal(bb.readUTF8String(4), "test"); + suite.wrap.string = function(test) { + var bb = ByteBuffer.wrap("\u0061\u0062"); + test.equal(bb.toDebug(), "<61 62>"); test.done(); - }, - - "wrap(Buffer)": function(test) { - var b = new Buffer("abc", "utf8"); - var bb = ByteBuffer.wrap(b); - test.equal(bb.toHex(), "<61 62 63>"); + }; + + suite.encodings = {}; + + suite.encodings.UTF8 = function(test) { + ["aäöü߀b", ""].forEach(function(str) { + var bb = ByteBuffer.wrap(str, "utf8"); // Calls ByteBuffer#fromUTF8 + test.strictEqual(bb.toUTF8(), str); + if (str.length > 2) { + bb.offset = 1; + bb.limit = bb.capacity()-1; + test.strictEqual(bb.toUTF8(), str.substring(1, str.length-1)); + } + }); test.done(); - }, + }; - "resize": function(test) { - var bb = new ByteBuffer(1); - bb.resize(2); - test.equal(bb.array.byteLength, 2); - test.equal(bb.toHex(), "|00 00 "); + suite.encodings.debug = function(test) { + ["60<61 62]63", "<60 61 62 63]", "|", "|61", "<61>", "!12"].forEach(function(str) { + var bb = ByteBuffer.wrap(str, "debug"); // Calls ByteBuffer#fromDebug + test.equal(bb.toDebug(), str); + }); test.done(); - }, + }; - "slice": function(test) { - var bb = new ByteBuffer(3); - bb.writeUint8(0x12).writeUint8(0x34).writeUint8(0x56); - var bb2 = bb.slice(1,2); - test.strictEqual(bb.array, bb2.array); - test.equal(bb.offset, 3); - test.equal(bb.length, 0); - test.equal(bb2.offset, 1); - test.equal(bb2.length, 2); + suite.encodings.binary = function(test) { + ["\x61\x62\x63\x64", "", " "].forEach(function(str) { + var bb = ByteBuffer.wrap(str, "binary"); // Calls ByteBuffer#fromBinary + test.strictEqual(bb.toBinary(), str); + if (str.length > 2) { + bb.offset = 1; + bb.limit = bb.capacity()-1; + test.strictEqual(bb.toBinary(), str.substring(1, str.length-1)); + } + }); test.done(); - }, - - "sliceAndCompact": function(test) { - var bb = new ByteBuffer(3); - bb.writeUint8(0x12).writeUint8(0x34).writeUint8(0x56); - var bb2 = bb.sliceAndCompact(1,2); - test.notStrictEqual(bb, bb2); - test.notStrictEqual(bb.array, bb2.array); - test.equal(bb2.offset, 0); - test.equal(bb2.length, 1); - test.equal(bb2.toHex(), "<34>"); + }; + + suite.encodings.hex = function(test) { + ["61626364", "61", ""].forEach(function(str) { + var bb = ByteBuffer.wrap(str, "hex"); // Calls ByteBuffer#fromHex + test.strictEqual(bb.toHex(), str); + if (str.length > 2) { + bb.offset = 1; + bb.limit = bb.capacity()-1; + test.strictEqual(bb.toHex(), str.substring(2, str.length-2)); + } + }); test.done(); - }, + }; + + suite.encodings.base64 = function(test) { + ["", "YWI=", "YWJjZGVmZw==", "YWJjZGVmZ2g=", "YWJjZGVmZ2hp"].forEach(function(str) { + var bb = ByteBuffer.wrap(str, "base64"); // Calls ByteBuffer#fromBase64 + test.strictEqual(bb.toBase64(), str); + if (str.length > 8) { + bb.offset = 3; + bb.limit = bb.offset + 3; + test.strictEqual(bb.toBase64(), str.substr(4, 4)); + } + }); + test.done(); + }; + + suite.methods = {}; + + suite.methods.concat = function(test) { + var bbs = [ + new ArrayBuffer(1), + ByteBuffer.fromDebug('00<01 02>'), + ByteBuffer.fromDebug('00 01 02<03>00'), + ByteBuffer.fromDebug('00|'), + ByteBuffer.fromDebug('<04>'), + type === Buffer ? new Buffer(0) : new ArrayBuffer(0), + new Uint8Array(0), + '05' + ]; + var bb = ByteBuffer.concat(bbs, 'hex', !ByteBuffer.DEFAULT_ENDIAN, !ByteBuffer.DEFAULT_NOASSERT); + test.strictEqual(bb.littleEndian, !ByteBuffer.DEFAULT_ENDIAN); + test.strictEqual(bb.noAssert, !ByteBuffer.DEFAULT_NOASSERT); + test.equal(bb.toDebug(), '<00 01 02 03 04 05>'); + bb = ByteBuffer.concat([]); + test.strictEqual(bb.buffer, new ByteBuffer(0).buffer); // EMPTY_BUFFER + test.done(); + }; + + suite.methods.resize = function(test) { + var bb = new ByteBuffer(1); + bb.offset = 1; + bb.resize(2); + bb.fill(0, 0, 2); + test.equal(bb.capacity(), 2); + test.equal(bb.toDebug(), "00|00"); + test.done(); + }; - "ensureCapacity": function(test) { + suite.methods.ensureCapacity = function(test) { var bb = new ByteBuffer(5); - test.equal(bb.array.byteLength, 5); - bb.ensureCapacity(6); - test.equal(bb.array.byteLength, 10); - bb.ensureCapacity(21); - test.equal(bb.array.byteLength, 21); + test.equal(bb.capacity(), 5); + bb.ensureCapacity(6); // Doubles + test.equal(bb.capacity(), 10); + bb.ensureCapacity(21); // Uses 21 + test.equal(bb.capacity(), 21); test.done(); - }, - - "flip": function(test) { - var bb = new ByteBuffer(4); - bb.writeUint32(0x12345678); - test.equal(bb.offset, 4); - test.equal(bb.length, 0); - bb.flip(); + }; + + suite.methods.slice = function(test) { + var bb = new ByteBuffer.wrap("\x12\x34\x56"), + bb2 = bb.slice(1,2); + test.strictEqual(bb.buffer, bb2.buffer); test.equal(bb.offset, 0); - test.equal(bb.length, 4); + test.equal(bb.limit, 3); + test.equal(bb2.offset, 1); + test.equal(bb2.limit, 2); test.done(); - }, - - "reset": function(test) { - var bb = new ByteBuffer(4); - bb.writeUint32(0x12345678); - bb.reset(); + }; + + suite.methods.flip = function(test) { + var bb = ByteBuffer.wrap('\x12\x34\x56\x78'); + bb.offset = 4; + test.equal(bb.offset, 4); + test.equal(bb.limit, 4); + bb.flip(); test.equal(bb.offset, 0); - test.equal(bb.length, 0); + test.equal(bb.limit, 4); test.done(); - }, + }; - "mark": function(test) { - var bb = new ByteBuffer(4); - bb.writeUint16(0x1234); - test.equal(bb.offset, 2); - test.equal(bb.length, 0); + suite.methods.mark = function(test) { + var bb = ByteBuffer.wrap('\x12\x34\x56\x78'); + test.equal(bb.offset, 0); + test.equal(bb.limit, 4); test.equal(bb.markedOffset, -1); bb.mark(); - test.equal(bb.markedOffset, 2); - bb.writeUint16(0x5678); - test.equal(bb.offset, 4); - test.equal(bb.markedOffset, 2); - bb.reset(); - test.equal(bb.offset, 2); - test.equal(bb.length, 0); - test.equal(bb.markedOffset, -1); + test.equal(bb.markedOffset, 0); + test.done(); + }; + + suite.methods.reset = function(test) { + var bb = ByteBuffer.wrap('\x12\x34\x56\x78'); bb.reset(); test.equal(bb.offset, 0); - test.equal(bb.length, 0); + test.equal(bb.limit, 4); + bb.offset = 1; + bb.mark(); + test.equal(bb.markedOffset, 1); + bb.reset(); + test.equal(bb.offset, 1); test.equal(bb.markedOffset, -1); - bb.mark(2); - test.equal(bb.markedOffset, 2); test.done(); - }, - - "clone": function(test) { - var bb = new ByteBuffer(1); - var bb2 = bb.clone(); - test.strictEqual(bb.array, bb2.array); - test.equal(bb.offset, bb2.offset); - test.equal(bb.length, bb2.length); - test.notStrictEqual(bb, bb2); - test.done(); - }, + }; - "copy": function(test) { - var bb = new ByteBuffer(1); - bb.writeUint8(0x12); - var bb2 = bb.copy(); + suite.methods.copy = function(test) { + var bb = ByteBuffer.wrap("\x01", !ByteBuffer.DEFAULT_ENDIAN), + bb2 = bb.copy(); + test.equal(bb.offset, 0); test.notStrictEqual(bb, bb2); - test.notStrictEqual(bb.array, bb2.array); + test.notStrictEqual(bb.buffer, bb2.buffer); test.equal(bb2.offset, bb.offset); - test.equal(bb2.length, bb.length); + test.equal(bb2.limit, bb.limit); + test.equal(bb2.markedOffset, bb.markedOffset); + test.equal(bb2.littleEndian, bb.littleEndian); + test.equal(bb2.noAssert, bb.noAssert); test.done(); - }, + }; - "compact": function(test) { - var bb = new ByteBuffer(2); - bb.writeUint8(0x12); - var prevArray = bb.array; - bb.compact(); - test.notStrictEqual(bb.array, prevArray); - test.equal(bb.array.byteLength, 1); - test.equal(bb.offset, 0); - test.equal(bb.length, 1); + suite.methods.copyTo = function(test) { + var bb = ByteBuffer.wrap("\x01"), + bb2 = new ByteBuffer(2).fill(0).flip(); + test.equal(bb.toDebug(), "<01>"); + // Modifies source and target offsets + bb.copyTo(bb2 /* all offsets omitted */); + test.equal(bb.toDebug(), "01|"); // Read 1 byte + test.equal(bb2.toDebug(), "01<00>"); // Written 1 byte + bb.reset(); + test.equal(bb.toDebug(), "<01>"); + // Again, but with bb2.offset=1 + bb.copyTo(bb2 /* all offsets omitted */); + test.equal(bb.toDebug(), "01|"); // Read 1 byte + test.equal(bb2.toDebug(), "01 01|"); // Written 1 byte at 2 + bb.reset(); + bb2.clear().fill(0).flip(); + // Modifies source offsets only + bb.copyTo(bb2, 0 /* source offsets omitted */); + test.equal(bb.toDebug(), "01|"); // Read 1 byte + test.equal(bb2.toDebug(), "<01 00>"); // Written 1 byte (no change) + // Modifies no offsets at all + bb.reset(); + bb2.fill(0).flip(); + bb.copyTo(bb2, 1, 0, bb.capacity() /* no offsets omitted */); + test.equal(bb.toDebug(), "<01>"); // Read 1 byte (no change) + test.equal(bb2.toDebug(), "<00 01>"); // Written 1 byte (no change) test.done(); - }, + }; - "destroy": function(test) { - var bb = new ByteBuffer(1); - bb.writeUint8(0x12); - bb.destroy(); - test.strictEqual(bb.array, null); + suite.methods.compact = function(test) { + var bb = ByteBuffer.wrap("\x01\x02"); + bb.limit = 1; + bb.markedOffset = 2; + var prevBuffer = bb.buffer, + prevView = bb.view; + bb.compact(); + test.notStrictEqual(bb.buffer, prevBuffer); + if (type === ArrayBuffer) { + test.notStrictEqual(bb.buffer, prevView); + } + test.equal(bb.capacity(), 1); + test.equal(bb.offset, 0); + test.equal(bb.limit, 1); + test.equal(bb.markedOffset, 2); // Actually out of bounds + + // Empty region + bb.offset = 1; + prevBuffer = bb.buffer; + bb.compact(); + test.notStrictEqual(bb.buffer, prevBuffer); + test.strictEqual(bb.buffer, new ByteBuffer(0).buffer); // EMPTY_BUFFER + if (type === ArrayBuffer) { + test.strictEqual(bb.view, null); + } + test.equal(bb.capacity(), 0); test.equal(bb.offset, 0); - test.equal(bb.length, 0); - test.equal(bb.toHex(), "DESTROYED"); + test.equal(bb.limit, 0); test.done(); - }, + }; - "reverse": function(test) { - var bb = new ByteBuffer(4); - bb.writeUint32(0x12345678); - bb.flip(); + suite.methods.reverse = function(test) { + var bb = ByteBuffer.wrap("\x12\x34\x56\x78"); + bb.reverse(1, 3); + test.equal(bb.toString("debug"), "<12 56 34 78>"); bb.reverse(); - test.equal(bb.toHex(), "<78 56 34 12>"); - test.done(); - }, - - "append": function(test) { - var bb = new ByteBuffer(2); - bb.writeUint16(0x1234); - var bb2 = new ByteBuffer(2); - bb2.writeUint16(0x5678); - bb2.flip(); - bb.append(bb2); - test.equal(bb.toHex(), ">12 34 56 78<"); - bb.append(bb2, 1); - test.equal(bb.toHex(), ">12 56 78 78<"); - test.done(); - }, - - "prepend": function(test) { - var bb = new ByteBuffer(2); - bb.writeUint16(0x1234); - bb.flip(); - var bb2 = new ByteBuffer(2); - bb2.writeUint16(0x5678); - bb2.flip(); - bb.prepend(bb2); - test.equal(bb.toHex(), "<56 78 12 34>"); - bb.offset = 4; - bb.prepend(bb2, 3); - test.equal(bb.toHex(), " 56 56 78 34|") + test.equal(bb.toString("debug"), "<78 34 56 12>"); + bb.offset = 1; + bb.limit = 3; + bb.reverse(); + test.equal(bb.toString("debug"), "78<56 34>12"); + bb.reverse(0, 4).clear(); + test.equal(bb.toString("debug"), "<12 34 56 78>"); test.done(); - }, + }; - "write/readInt8": function(test) { - var bb = new ByteBuffer(1); - bb.writeInt8(0xFF); - bb.flip(); - test.equal(-1, bb.readInt8()); + suite.methods.append = function(test) { + var bb = ByteBuffer.wrap("\x12\x34"); + var bb2 = ByteBuffer.wrap("\x56\x78"); + bb.offset = 2; + bb.append(bb2); // Modifies offsets of both + test.equal(bb.toString("debug"), "12 34>56 78<"); + test.equal(bb2.toString("debug"), "56 78|"); + bb2.reset(); + bb.append(bb2, 1); // Modifies offsets of bb2 only + test.equal(bb.toString("debug"), "12 56>78 78<"); + test.equal(bb2.toString("debug"), "56 78|"); test.done(); - }, + }; - "write/readByte": function(test) { - var bb = new ByteBuffer(1); - test.strictEqual(bb.readInt8, bb.readByte); - test.strictEqual(bb.writeInt8, bb.writeByte); + suite.methods.writeBytes = function(test) { + var bb = ByteBuffer.wrap("\x12\x34"); + var bb2 = ByteBuffer.wrap("\x56\x78"); + bb.offset = 2; + bb.writeBytes(bb2); // Modifies offsets of both + test.equal(bb.toString("debug"), "12 34>56 78<"); + test.equal(bb2.toString("debug"), "56 78|"); + bb2.reset(); + bb.writeBytes(bb2, 1); // Modifies offsets of bb2 only + test.equal(bb.toString("debug"), "12 56>78 78<"); + test.equal(bb2.toString("debug"), "56 78|"); test.done(); - }, - - "write/readUint8": function(test) { - var bb = new ByteBuffer(1); - bb.writeUint8(0xFF); - bb.flip(); - test.equal(0xFF, bb.readUint8()); - test.done(); - }, - - "write/readInt16": function(test) { - var bb = new ByteBuffer(2); - bb.writeInt16(0xFFFF); - bb.flip(); - test.equal(-1, bb.readInt16()); - test.done(); - }, + }; - "write/readShort": function(test) { - var bb = new ByteBuffer(1); - test.strictEqual(bb.readInt16, bb.readShort); - test.strictEqual(bb.writeInt16, bb.writeShort); - test.done(); - }, - - "write/readUint16": function(test) { - var bb = new ByteBuffer(2); - bb.writeUint16(0xFFFF); - bb.flip(); - test.equal(0xFFFF, bb.readUint16()); + suite.methods.prepend = function(test) { + var bb = ByteBuffer.wrap("\x12\x34"), + bb2 = ByteBuffer.wrap("\x56\x78"); + test.strictEqual(bb.prepend(bb2), bb); // Relative prepend at 0, 2 bytes (2 overflow) + test.equal(bb.toDebug(), "<56 78 12 34>"); + test.equal(bb2.toDebug(), "56 78|"); + bb.offset = 4; + bb2.offset = 1; + bb.prepend(bb2, 3); // Absolute prepend at 3, 1 byte + test.equal(bb.toDebug(), "56 78 78 34|"); + test.equal(bb2.toDebug(), "56 78|"); + bb2.offset = 0; + bb.prepend(bb2); // Relative prepend at 4, 2 bytes + test.equal(bb.toDebug(), "56 78<56 78>"); + test.equal(bb2.toDebug(), "56 78|"); + bb.offset = 3; + bb2.offset = 0; + test.throws(function() { + bb.prepend(bb2, 6); // Absolute out of bounds + }, RangeError); + bb.prepend("abcde", "utf8"); // Relative prepend at 3, 5 bytes (1 overflow) + test.equal(bb.toDebug(), "<61 62 63 64 65 78>"); test.done(); - }, + }; - "write/readInt32": function(test) { - var bb = new ByteBuffer(4); - bb.writeInt32(0xFFFFFFFF); - bb.flip(); - test.equal(-1, bb.readInt32()); + suite.methods.prependTo = function(test) { + var bb = ByteBuffer.wrap("\x12\x34"), + bb2 = ByteBuffer.wrap("\x56\x78"); + test.strictEqual(bb2.prependTo(bb), bb2); + test.equal(bb.toDebug(), "<56 78 12 34>"); + test.equal(bb2.toDebug(), "56 78|"); test.done(); - }, + }; - "write/readInt": function(test) { - var bb = new ByteBuffer(1); - test.strictEqual(bb.readInt32, bb.readInt); - test.strictEqual(bb.writeInt32, bb.writeInt); + suite.methods.remaining = function(test) { + var bb = ByteBuffer.wrap("\x12\x34"); + test.strictEqual(bb.remaining(), 2); + bb.offset = 2; + test.strictEqual(bb.remaining(), 0); + bb.offset = 3; + test.strictEqual(bb.remaining(), -1); test.done(); - }, + }; - "write/readUint32": function(test) { - var bb = new ByteBuffer(4); - bb.writeUint32(0x12345678); - bb.flip(); - test.equal(0x12345678, bb.readUint32()); + suite.methods.skip = function(test) { + var bb = ByteBuffer.wrap("\x12\x34\x56"); + test.strictEqual(bb.offset, 0); + bb.skip(3); + test.strictEqual(bb.offset, 3); + test.strictEqual(bb.noAssert, false); + test.throws(function() { + bb.skip(1); + }); + test.strictEqual(bb.offset, 3); + bb.noAssert = true; + test.doesNotThrow(function() { + bb.skip(1); + }); + test.strictEqual(bb.offset, 4); test.done(); - }, + }; - "write/readFloat32": function(test) { - var bb = new ByteBuffer(4); - bb.writeFloat32(0.5); + suite.methods.order = function(test) { + test.strictEqual(ByteBuffer.LITTLE_ENDIAN, true); + test.strictEqual(ByteBuffer.BIG_ENDIAN, false); + var bb = new ByteBuffer(2); + test.strictEqual(bb.littleEndian, false); + bb.writeInt32(0x12345678); bb.flip(); - test.equal(0.5, bb.readFloat32()); // 0.5 remains 0.5 if Float32 - test.done(); - }, - - "write/readFloat": function(test) { - var bb = new ByteBuffer(1); - test.strictEqual(bb.readFloat32, bb.readFloat); - test.strictEqual(bb.writeFloat32, bb.writeFloat); - test.done(); - }, - - "write/readFloat64": function(test) { - var bb = new ByteBuffer(8); - bb.writeFloat64(0.1); + test.strictEqual(bb.toHex(), "12345678"); + bb.clear(); + test.strictEqual(bb.LE(), bb); + test.strictEqual(bb.littleEndian, true); + bb.writeInt32(0x12345678); bb.flip(); - test.equal(0.1, bb.readFloat64()); // would be 0.10000000149011612 if Float32 + test.strictEqual(bb.toHex(), "78563412"); + test.strictEqual(bb.BE(), bb); + test.strictEqual(bb.littleEndian, false); + test.strictEqual(bb.order(ByteBuffer.LITTLE_ENDIAN), bb); + test.strictEqual(bb.littleEndian, true); + test.strictEqual(bb.order(ByteBuffer.BIG_ENDIAN), bb); + test.strictEqual(bb.littleEndian, false); test.done(); - }, - - "write/readDouble": function(test) { - var bb = new ByteBuffer(1); - test.strictEqual(bb.readFloat64, bb.readDouble); - test.strictEqual(bb.writeFloat64, bb.writeDouble); - test.done(); - }, + }; - "write/readInt64": function(test) { - var bb = new ByteBuffer(8); - - var max = ByteBuffer.Long.MAX_SIGNED_VALUE.toNumber(); - bb.writeInt64(max).flip(); - test.equal(bb.toHex(), "<7F FF FF FF FF FF FF FF>"); - test.equal(bb.readInt64(0), max); - - var min = ByteBuffer.Long.MIN_SIGNED_VALUE.toNumber(); - bb.writeInt64(min).flip(); - test.equal(bb.toHex(), "<80 00 00 00 00 00 00 00>"); - test.equal(bb.readInt64(0), min); - - bb.writeInt64(-1).flip(); - test.equal(bb.toHex(), ""); - test.equal(bb.readInt64(0), -1); - - bb.reset(); - bb.LE().writeInt64(new ByteBuffer.Long(0x89ABCDEF, 0x01234567)).flip(); - test.equal(bb.toHex(), ""); + var types = [ + // name | alias | size | input | output | BE representation + ["Int8" , "Byte" , 1 , 0xFE , -2 , "fe" ], + ["Uint8" , null , 1 , -2 , 0xFE , "fe" ], + ["Int16" , "Short" , 2 , 0xFFFE , -2 , "fffe" ], + ["Uint16" , null , 2 , -2 , 0xFFFE , "fffe" ], + ["Int32" , "Int" , 4 , 0xFFFFFFFE , -2 , "fffffffe" ], + ["Uint32" , null , 4 , -2 , 0xFFFFFFFE , "fffffffe" ], + ["Float32" , "Float" , 4 , 0.5 , 0.5 , "3f000000" ], + ["Float64" , "Double", 8 , 0.1 , 0.1 , "3fb999999999999a" ], + ["Int64" , "Long" , 8 , new Long(0xFFFFFFFE, 0xFFFFFFFF, true) , new Long(0xFFFFFFFE, 0xFFFFFFFF, false) , "fffffffffffffffe" ], + ["Uint64" , null , 8 , new Long(0xFFFFFFFE, 0xFFFFFFFF, false) , new Long(0xFFFFFFFE, 0xFFFFFFFF, true) , "fffffffffffffffe" ], - test.done(); - }, + // name | alias | size | input | output | representation + ["Varint32" , null , 5 , 0xFFFFFFFE , -2 , "feffffff0f" ], + ["Varint32ZigZag", null , 1 , -1 , -1 , "01" ], + ["Varint64" , null , 10 , new Long(0xFFFFFFFE, 0xFFFFFFFF, true) , new Long(0xFFFFFFFE, 0xFFFFFFFF, false) , "feffffffffffffffff01"], + ["Varint64ZigZag", null , 1 , Long.fromNumber(-1) , Long.fromNumber(-1) , "01" ] + ]; + + suite.types = {}; + + types.forEach(function(type) { + var name = type[0], + varint = name.indexOf("Varint") >= 0, + alias = type[1], + size = type[2], + input = type[3], + output = type[4], + be = type[5], + le = ""; + for (var i=be.length; i>0; i-=2) { + le += be.substr(i-2, 2); + } + suite.types[name.toLowerCase()] = function(test) { + var bb = new ByteBuffer(size); + // Relative BE (always LE for varints) + test.strictEqual(bb["write"+name](input), bb); + bb.flip(); + var val = bb["read"+name](); + if (output instanceof Long) { + test.deepEqual(val, output); + } else { + test.strictEqual(val, output); + } + bb.flip(); + test.strictEqual(bb.toHex(), be); + if (!varint) { + // Relative LE + bb.LE(); + bb["write"+name](input); + bb.flip(); + val = bb["read"+name](); + if (output instanceof Long) { + test.deepEqual(val, output); + } else { + test.strictEqual(val, output); + } + bb.flip(); + test.strictEqual(bb.toHex(), le); + } + test.throws(function() { // OOB + bb.offset = bb.capacity() - size + 1; + bb["read"+name](input); + }); + test.doesNotThrow(function() { // OOB, automatic resizing * 2 + bb["write"+name](input); + }); + test.strictEqual(bb.capacity(), size * 2); + // Absolute + bb.clear(); + if (!varint) + test.strictEqual(bb["write"+name](input, 1), bb); + else + test.strictEqual(bb["write"+name](input, 1), size); + val = bb["read"+name](1); + if (output instanceof Long) { + if (!varint) + test.deepEqual(val, output); + else + test.deepEqual(val, {value: output, length: size}); + } else { + if (!varint) + test.strictEqual(val, output); + else + test.deepEqual(val, {value: output, length: size}); + } + // Alias + if (alias) { + test.strictEqual(bb["write"+name], bb["write"+alias]); + test.strictEqual(bb["read"+name], bb["read"+alias]); + } + test.done(); + }; + }); - "write/readUint64": function(test) { - var bb = new ByteBuffer(8); + suite.types.bitset = function(test) { + var bb = new ByteBuffer(2), + arr; - var max = ByteBuffer.Long.MAX_UNSIGNED_VALUE.toNumber(); - bb.writeUint64(max).flip(); - test.equal(bb.toHex(), ""); - test.equal(bb.readUint64(0), max); - - var min = ByteBuffer.Long.MIN_UNSIGNED_VALUE.toNumber(); - bb.writeLong(min).flip(); - test.equal(bb.toHex(), "<00 00 00 00 00 00 00 00>"); - test.equal(bb.readUint64(0), min); + function run(data) { + bb.reset(); + bb.writeBitSet(data); + bb.reset(); + test.deepEqual(bb.readBitSet(),data); + }; - bb.writeUint64(-1).flip(); - test.equal(bb.toHex(), "<00 00 00 00 00 00 00 00>"); - test.equal(bb.readUint64(0), 0); + run([]); + run([true]); + run([false]); + run([false,true]); + run([false,false,false,false,false,false,false,false]); + run([true,false,true,false,true,false,true,false]); + run([true,true,true,true,true,true,true,true]); + run([true,false,true,false,true,false,true,false]); + run([true,false,true,false,true,false,true,false,true]); + + bb.reset(); + bb.writeBitSet([,null,"",0,42,"hello world",new Date(0),{},[]]); + bb.reset(); + test.deepEqual(bb.readBitSet(),[false,false,false,false,true,true,true,true,true]); - bb.reset(); - bb.LE().writeUint64(new ByteBuffer.Long(0x89ABCDEF, 0x01234567, true)).flip(); - test.equal(bb.toHex(), ""); + test.done(); + }; - test.done(); - }, - - "write/readLong": function(test) { - var bb = new ByteBuffer(1); - test.strictEqual(bb.readInt64, bb.readLong); - test.strictEqual(bb.writeInt64, bb.writeLong); - test.done(); - }, - - "writeVarint64/readVarint32": function(test) { - var bb = new ByteBuffer(); - bb.writeVarint64(Long.fromNumber(-1)); - bb.flip(); - var n = bb.readVarint32(); - test.equal(n, -1); - test.done(); - }, - - "LE/BE": function(test) { - var bb = new ByteBuffer(8).LE().writeInt(1).BE().writeInt(2).flip(); - test.equal(bb.toHex(), "<01 00 00 00 00 00 00 02>"); - test.done(); - }, - - "calculateVarint32/64": function(test) { + suite.types.calculateVarint = function(test) { test.equal(ByteBuffer.MAX_VARINT32_BYTES, 5); test.equal(ByteBuffer.MAX_VARINT64_BYTES, 10); var values = [ @@ -487,9 +707,9 @@ var suite = { test.equal(ByteBuffer.calculateVarint64(values[i][0]), values[i][1]); } test.done(); - }, + }; - "zigZagEncode/Decode32/64": function(test) { + suite.types.zigZagVarint = function(test) { var Long = ByteBuffer.Long; var values = [ [ 0, 0], @@ -509,77 +729,36 @@ var suite = { test.equal(ByteBuffer.zigZagDecode64(values[i][1]).toNumber(), values[i][0]); } values = [ - [Long.MAX_SIGNED_VALUE, Long.MAX_UNSIGNED_VALUE.subtract(Long.ONE)], - [Long.MIN_SIGNED_VALUE, Long.MAX_UNSIGNED_VALUE] + [Long.MAX_VALUE, Long.MAX_UNSIGNED_VALUE.subtract(Long.ONE)], + [Long.MIN_VALUE, Long.MAX_UNSIGNED_VALUE] ]; // NOTE: Even 64bit doubles from toNumber() fail for these values so we are using toString() here for (i=0; i 1 ? values[i][1] : values[i][0]).toString(), dec['value'].toString()); - test.equal(encLen, dec['length']); - } - test.done(); - }, - - "write/readZigZagVarint32": function(test) { - var values = [ + + // 32 bit ZZ + values = [ 0, 1, - 300, + 300, -300, - 2147483647, + 2147483647, -2147483648 ]; - var bb = new ByteBuffer(10); - for (var i=0; i00 "); - test.deepEqual({"string": "ab", "length": 3}, bb.readLString(0)); - test.equal(bb.toHex(), "<02 61 62>00 "); - test.equal("ab", bb.readLString()); - test.equal(bb.toHex(), " 02 61 62|00 "); + // bb.printDebug(); + // Reading + str2 = bb.readUTF8String(ByteBuffer.calculateUTF8Chars(str), ByteBuffer.METRICS_CHARS); + // bb.printDebug(); + test.strictEqual(str2.length, str.length); + test.strictEqual(str2, str); + bb.reset(); + str2 = bb.readUTF8String(bb.limit, ByteBuffer.METRICS_BYTES); + test.strictEqual(str2, str); test.done(); - }, + }; - "write/readVString": function(test) { + suite.types.istring = function(test) { var bb = new ByteBuffer(2); - bb.writeVString("ab"); // resizes to 4 - test.equal(bb.array.byteLength, 4); - test.equal(bb.offset, 3); - test.equal(bb.length, 0); + test.strictEqual(bb.writeIString("ab"), bb); // resizes to 4+2=6 + test.strictEqual(bb.capacity(), 6); + test.strictEqual(bb.offset, 6); + test.strictEqual(bb.limit, 2); bb.flip(); - test.equal(bb.toHex(), "<02 61 62>00 "); - test.deepEqual({"string": "ab", "length": 3}, bb.readVString(0)); - test.equal(bb.toHex(), "<02 61 62>00 "); - test.equal("ab", bb.readLString()); - test.equal(bb.toHex(), " 02 61 62|00 "); + test.equal(bb.toString("debug"), "<00 00 00 02 61 62>"); + test.deepEqual(bb.readIString(0), {"string": "ab", "length": 6}); + test.strictEqual(bb.readIString(), "ab"); + bb.reset(); + test.equal(bb.toString("debug"), "<00 00 00 02 61 62>"); + test.strictEqual(bb.readIString(), "ab"); + test.equal(bb.toString("debug"), "00 00 00 02 61 62|"); test.done(); - }, + }; - "write/readCString": function(test) { + suite.types.vstring = function(test) { var bb = new ByteBuffer(2); - bb.writeCString("ab"); // resizes to 4 - test.equal(bb.array.byteLength, 4); - test.equal(bb.offset, 3); - test.equal(bb.length, 0); + bb.writeVString("ab"); // resizes to 2*2=4 + test.strictEqual(bb.capacity(), 4); + test.strictEqual(bb.offset, 3); + test.strictEqual(bb.limit, 2); bb.flip(); - test.equal(bb.toHex(), "<61 62 00>00 "); - test.deepEqual({"string": "ab", "length": 3}, bb.readCString(0)); - test.equal(bb.toHex(), "<61 62 00>00 "); - test.equal("ab", bb.readCString()); - test.equal(bb.toHex(), " 61 62 00|00 "); + test.equal(bb.toString("debug").substr(0, 10), "<02 61 62>"); + test.deepEqual(bb.readVString(0), {"string": "ab", "length": 3}); + test.equal(bb.toString("debug").substr(0, 10), "<02 61 62>"); + test.equal(bb.readVString(), "ab"); + test.equal(bb.toString("debug").substr(0, 9), "02 61 62|"); test.done(); - }, + }; - "write/readJSON": function(test) { - var bb = new ByteBuffer(); - var data = {"x":1}; - bb.writeJSON(data); + suite.types.cstring = function(test) { + var bb = new ByteBuffer(2); + bb.writeCString("a"); + test.equal(bb.capacity(), 2); + test.equal(bb.offset, 2); + test.equal(bb.limit, 2); + bb.offset = 1; + bb.writeCString("b"); // resizes to 4 + test.equal(bb.capacity(), 4); + test.equal(bb.offset, 3); + test.equal(bb.limit, 2); bb.flip(); - test.deepEqual(data, bb.readJSON()); + test.equal(bb.toString("debug").substr(0, 10), "<61 62 00>"); + test.deepEqual(bb.readCString(0), {"string": "ab", "length": 3}); + test.equal(bb.toString("debug").substr(0, 10), "<61 62 00>"); + test.equal(bb.readCString(), "ab"); + test.equal(bb.toString("debug").substr(0, 9), "61 62 00|"); test.done(); - }, + }; - "toHex": function(test) { - var bb = new ByteBuffer(3); + suite.convert = {}; + + suite.convert.toHex = function(test) { + var bb = new ByteBuffer(4); bb.writeUint16(0x1234); - test.equal(bb.toHex(), ">12 34<00 "); + bb.writeUint8(0x56); + bb.flip(); + test.equal(bb.toHex(), "123456"); + test.strictEqual(bb.offset, 0); + test.equal(bb.toHex(1), "3456"); + test.equal(bb.toHex(1,2), "34"); + test.equal(bb.toHex(1,1), ""); + test.throws(function() { + bb.toHex(1,0); + }); test.done(); - }, + }; - "toString": function(test) { - var bb = new ByteBuffer(3); - bb.writeUint16(0x1234); - test.equal(bb.toString(), "ByteBuffer(offset=2,markedOffset=-1,length=0,capacity=3)"); + suite.convert.toBase64 = function(test) { + var bb = new ByteBuffer(8); + bb.writeUTF8String("abcdefg"); // 7 chars + bb.flip(); + test.equal(bb.toBase64(), "YWJjZGVmZw=="); + test.strictEqual(bb.offset, 0); + test.equal(bb.toBase64(3), "ZGVmZw=="); + test.equal(bb.toBase64(3,6), "ZGVm"); + test.equal(bb.toBase64(3,3), ""); + test.throws(function() { + bb.toBase64(1,0); + }); test.done(); - }, + }; - "toArrayBuffer": function(test) { - var bb = new ByteBuffer(3); - bb.writeUint16(0x1234); - var buf = bb.toArrayBuffer(); - test.equal(buf.byteLength, 2); - test.equal(buf[0], 0x12); - test.equal(buf[1], 0x34); - test.equal(bb.offset, 2); - test.equal(bb.length, 0); - test.equal(bb.array.byteLength, 3); + suite.convert.toBinary = function(test) { + var bb = new ByteBuffer(5); + bb.writeUint32(0x001234FF); + bb.flip(); + test.strictEqual(bb.toBinary(), "\x00\x12\x34\xFF"); + test.strictEqual(bb.offset, 0); test.done(); - }, + }; - "toBuffer": function(test) { + suite.convert.toString = function(test) { var bb = new ByteBuffer(3); - bb.writeUint16(0x1234); - var buf; - try { - buf = bb.toBuffer(); - } catch (e) { - console.trace(e); - } - test.equal(buf.length, 2); - test.equal(buf[0], 0x12); - test.equal(buf[1], 0x34); - test.equal(bb.offset, 2); - test.equal(bb.length, 0); - test.equal(bb.array.byteLength, 3); + bb.writeUint16(0x6162).flip(); + test.equal(bb.toString("hex"), "6162"); + test.equal(bb.toString("base64"), "YWI="); + test.equal(bb.toString("utf8"), "ab"); + test.equal(bb.toString("debug").substr(0,7), "<61 62>"); + test.equal(bb.toString(), (type === ArrayBuffer ? (accessor === DataView ? "ByteBufferAB_DataView" : "ByteBufferAB") : "ByteBufferNB")+"(offset=0,markedOffset=-1,limit=2,capacity=3)"); + test.strictEqual(bb.offset, 0); test.done(); - }, + }; - "printDebug": function(test) { - var bb = new ByteBuffer(3); - test.ok(typeof bb.printDebug(true) == 'string'); - function callMe() { callMe.called = true; }; - bb.printDebug(callMe); - test.ok(callMe.called); + suite.convert.toBuffer = function(test) { + var bb = new ByteBuffer(2); + bb.writeUint16(0x1234).flip(); + var buf = bb.toBuffer(); + test.strictEqual(buf, bb.buffer); + if (type === ArrayBuffer) { + test.ok(buf instanceof ArrayBuffer); + test.strictEqual(buf.byteLength, 2); + } else { + test.ok(buf instanceof Buffer); + test.strictEqual(buf.length, 2); + } + bb.limit = 1; + buf = bb.toBuffer(); + test.notStrictEqual(buf, bb.buffer); + if (type === ArrayBuffer) { + test.ok(buf instanceof ArrayBuffer); + test.strictEqual(buf.byteLength, 1); + } else { + test.ok(buf instanceof Buffer); + test.strictEqual(buf.length, 1); + } test.done(); - }, + }; - "encode/decode/calculateUTF8Char": function(test) { - var bb = new ByteBuffer(6) - , chars = [0x00, 0x7F, 0x80, 0x7FF, 0x800, 0xFFFF, 0x10000, 0x1FFFFF, 0x200000, 0x3FFFFFF, 0x4000000, 0x7FFFFFFF] - , dec; - for (var i=0; i10 02 18 00 20 80 B0 D9 B4 E8 27 28 93 99 8E CD 04<00 "); - test.done(); - }, - - "encode/decode64": function(test) { - var values = [ - ["ProtoBuf.js", "UHJvdG9CdWYuanM="], - ["ProtoBuf.j", "UHJvdG9CdWYuag=="], - ["ProtoBuf.", "UHJvdG9CdWYu"], - ["ProtoBuf", "UHJvdG9CdWY="] - ]; - for (var i=0; i"); test.done(); - }, + }; - "commonjs": function(test) { - var fs = require("fs") - , vm = require("vm") - , util = require('util'); - - var code = fs.readFileSync(__dirname+"/../"+FILE); - var Long = ByteBuffer.Long; - var sandbox = new Sandbox({ - require: function(moduleName) { - if (moduleName == 'long') { - return Long; - } - }, - module: { - exports: {} - } - }); - vm.runInNewContext(code, sandbox, "ByteBuffer.js in CommonJS-VM"); - // console.log(util.inspect(sandbox)); - test.ok(typeof sandbox.module.exports == 'function'); - test.ok(sandbox.module.exports.Long && sandbox.module.exports.Long == ByteBuffer.Long); + suite.misc.NaN = function(test) { + var bb = new ByteBuffer(4); + test.ok(isNaN(bb.writeFloat(NaN).flip().readFloat(0))); + test.strictEqual(bb.writeFloat(+Infinity).flip().readFloat(0), +Infinity); + test.strictEqual(bb.writeFloat(-Infinity).flip().readFloat(0), -Infinity); + bb.resize(8); + test.ok(isNaN(bb.writeDouble(NaN).flip().readDouble(0))); + test.strictEqual(bb.writeDouble(+Infinity).flip().readDouble(0), +Infinity); + test.strictEqual(bb.writeDouble(-Infinity).flip().readDouble(0), -Infinity); + + // Varints, however, always need a cast, which results in the following: + test.strictEqual(NaN >>> 0, 0); + test.strictEqual(NaN | 0, 0); + test.strictEqual(Infinity >>> 0, 0); + test.strictEqual(Infinity | 0, 0); + test.strictEqual(-Infinity >>> 0, 0); + test.strictEqual(-Infinity | 0, 0); + test.done(); - }, - - "amd": function(test) { - var fs = require("fs") - , vm = require("vm") - , util = require('util'); + }; - var code = fs.readFileSync(__dirname+"/../"+FILE); - var sandbox = new Sandbox({ - require: function() {}, - define: (function() { - function define(moduleName, dependencies, constructor) { - define.called = [moduleName, dependencies]; - } - define.amd = true; - define.called = null; - return define; - })() - }); - vm.runInNewContext(code, sandbox, "ByteBuffer.js in AMD-VM"); - // console.log(util.inspect(sandbox)); - test.ok(sandbox.define.called && sandbox.define.called[0] == "ByteBuffer" && sandbox.define.called[1][0] == "Math/Long"); + suite.debug = {}; + + suite.debug.printDebug = function(test) { + var bb = new ByteBuffer(3); + function callMe() { callMe.called = true; } + bb.printDebug(callMe); + test.ok(callMe.called); test.done(); - }, + }; + + if (type === ArrayBuffer) { + suite.debug.printDebugVisual = function(test) { + var bb = ByteBuffer.wrap("Hello world! from byteBuffer.js. This is just a last visual test of ByteBuffer#printDebug."); + console.log(""); + bb.printDebug(console.log); + test.done(); + }; + } - "shim": function(test) { - var fs = require("fs") - , vm = require("vm") - , util = require('util'); + return suite; +} - var code = fs.readFileSync(__dirname+"/../"+FILE); - var sandbox = new Sandbox({ - dcodeIO: { - Long: ByteBuffer.Long - } - }); - vm.runInNewContext(code, sandbox, "ByteBuffer.js in shim-VM"); - // console.log(util.inspect(sandbox)); - test.ok(typeof sandbox.dcodeIO != 'undefined' && typeof sandbox.dcodeIO.ByteBuffer != 'undefined'); - test.ok(sandbox.dcodeIO.ByteBuffer.Long && sandbox.dcodeIO.ByteBuffer.Long == ByteBuffer.Long); +module.exports = { + "info": function(test) { + test.log("Version "+ByteBuffer.VERSION+", "+new Date().toISOString()+"\n"); test.done(); }, - - "helloworld": function(test) { - var bb = new ByteBuffer(); - bb.writeUTF8String("Hello world! from ByteBuffer.js. This is just a last visual test of ByteBuffer#printDebug."); - bb.flip(); - console.log(""); - bb.printDebug(console.log); - test.done(); - } + "node": makeSuite(ByteBufferNode), + "browser": makeSuite(ByteBufferBrowser), + "dataview": makeSuite(ByteBufferBrowser_DataView) }; - -module.exports = suite;