You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			2321 lines
		
	
	
		
			99 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			2321 lines
		
	
	
		
			99 KiB
		
	
	
	
		
			JavaScript
		
	
| /*
 | |
|  Copyright 2013 Daniel Wirtz <dcode@dcode.io>
 | |
| 
 | |
|  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 <dcode@dcode.io>
 | |
|  * 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.
 | |
| 
 | |
|     /**
 | |
|      * @param {Function=} Long
 | |
|      * @returns {Function}
 | |
|      * @inner
 | |
|      */
 | |
|     function loadByteBuffer(Long) {
 | |
| 
 | |
|         // Support node's Buffer if available, see 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.
 | |
|          * @class A full-featured ByteBuffer implementation in JavaScript using typed arrays.
 | |
|          * @exports ByteBuffer
 | |
|          * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
 | |
|          * @param {boolean=} littleEndian `true` to use little endian multi byte values, defaults to `false` for big
 | |
|          *  endian.
 | |
|          * @param {boolean=} sparse If set to `true`, a ByteBuffer with array=view=null will be created which have to be
 | |
|          *  set manually afterwards. Defaults to `false`.
 | |
|          * @expose
 | |
|          */
 | |
|         var ByteBuffer = function(capacity, littleEndian, sparse) {
 | |
|             capacity = typeof capacity !== 'undefined' ? parseInt(capacity, 10) : ByteBuffer.DEFAULT_CAPACITY;
 | |
|             if (capacity < 1) capacity = ByteBuffer.DEFAULT_CAPACITY;
 | |
| 
 | |
|             /**
 | |
|              * Backing ArrayBuffer.
 | |
|              * @type {?ArrayBuffer}
 | |
|              * @expose
 | |
|              */
 | |
|             this.array = sparse ? null : new ArrayBuffer(capacity);
 | |
| 
 | |
|             /**
 | |
|              * DataView to mess with the ArrayBuffer.
 | |
|              * @type {?DataView}
 | |
|              * @expose
 | |
|              */
 | |
|             this.view = sparse ? null : new DataView(this.array);
 | |
| 
 | |
|             /**
 | |
|              * 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}. Defaults to `-1` (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, defaults to `false` for big endian.
 | |
|              * @type {boolean}
 | |
|              * @expose
 | |
|              */
 | |
|             this.littleEndian = typeof littleEndian != 'undefined' ? !!littleEndian : false;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Version string.
 | |
|          * @type {string}
 | |
|          * @const
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.VERSION = "2.3.1";
 | |
| 
 | |
|         /**
 | |
|          * Default buffer capacity of `16`. 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 `null` if the Long class has not been loaded and int64 support is
 | |
|          *  not available.
 | |
|          * @type {?Long}
 | |
|          * @const
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.Long = Long || null;
 | |
| 
 | |
|         /**
 | |
|          * Tests if the specified type is a ByteBuffer or ByteBuffer-like.
 | |
|          * @param {*} bb ByteBuffer to test
 | |
|          * @returns {boolean} true if it is a ByteBuffer or ByteBuffer-like, otherwise false
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.isByteBuffer = function(bb) {
 | |
|             return bb && (
 | |
|                 (bb instanceof ByteBuffer) || (
 | |
|                     typeof bb === 'object' &&
 | |
|                     (bb.array === null || bb.array instanceof ArrayBuffer) &&
 | |
|                     (bb.view === null || bb.view instanceof DataView) &&
 | |
|                     typeof bb.offset === 'number' &&
 | |
|                     typeof bb.markedOffset === 'number' &&
 | |
|                     typeof bb.length === 'number' &&
 | |
|                     typeof bb.littleEndian === 'boolean'
 | |
|                 )
 | |
|             );
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * 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, defaults to `false` for big
 | |
|          *  endian.
 | |
|          * @returns {!ByteBuffer}
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.allocate = function(capacity, littleEndian) {
 | |
|             return new ByteBuffer(capacity, littleEndian);
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Converts a node.js <= 0.8 Buffer to an ArrayBuffer.
 | |
|          * @param {!Buffer} b Buffer to convert
 | |
|          * @returns {?ArrayBuffer} Converted buffer
 | |
|          * @inner
 | |
|          */
 | |
|         function b2ab(b) {
 | |
|             var ab = new ArrayBuffer(b.length),
 | |
|                 view = new Uint8Array(ab);
 | |
|             for (var i=0, k=b.length; i < k; ++i) view[i] = b[i];
 | |
|             return ab;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Wraps an ArrayBuffer, any object containing an ArrayBuffer, a node buffer or a string. Sets the created
 | |
|          *  ByteBuffer's offset to 0 and its length to the wrapped object's byte length.
 | |
|          * @param {!ArrayBuffer|!Buffer|!{array: !ArrayBuffer}|!{buffer: !ArrayBuffer}|string} buffer Anything that can
 | |
|          *  be wrapped
 | |
|          * @param {(string|boolean)=} enc String encoding if a string is provided (hex, utf8, binary, defaults to base64)
 | |
|          * @param {boolean=} littleEndian `true` to use little endian multi byte values, defaults to `false` for big
 | |
|          *  endian.
 | |
|          * @returns {!ByteBuffer}
 | |
|          * @throws {Error} If the specified object cannot be wrapped
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.wrap = function(buffer, enc, littleEndian) {
 | |
|             if (typeof enc === 'boolean') {
 | |
|                 littleEndian = enc;
 | |
|                 enc = "utf8";
 | |
|             }
 | |
|             // Wrap a string
 | |
|             if (typeof buffer === 'string') {
 | |
|                 switch (enc) {
 | |
|                     case "base64":
 | |
|                         return ByteBuffer.decode64(buffer, littleEndian);
 | |
|                     case "hex":
 | |
|                         return ByteBuffer.decodeHex(buffer, littleEndian);
 | |
|                     case "binary":
 | |
|                         return ByteBuffer.decodeBinary(buffer, littleEndian);
 | |
|                     default:
 | |
|                         return new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, littleEndian).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) ? b2ab(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 (ByteBuffer.isByteBuffer(buffer)) {
 | |
|                 return ByteBuffer.prototype.clone.call(buffer); // Also makes ByteBuffer-like a ByteBuffer
 | |
|             }
 | |
|             // 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, true);
 | |
|             b.array = buffer;
 | |
|             b.view = b.array.byteLength > 0 ? new DataView(b.array) : null;
 | |
|             b.offset = 0;
 | |
|             b.length = buffer.byteLength;
 | |
|             return b;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Switches little endian byte order.
 | |
|          * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian
 | |
|          * @returns {!ByteBuffer} this
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.LE = function(littleEndian) {
 | |
|             this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true;
 | |
|             return this;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Switches big endian byte order.
 | |
|          * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian
 | |
|          * @returns {!ByteBuffer} this
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.BE = function(bigEndian) {
 | |
|             this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false;
 | |
|             return this;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Resizes the ByteBuffer to the given capacity. Will do nothing if already that large or larger.
 | |
|          * @param {number} capacity New capacity
 | |
|          * @returns {!ByteBuffer} this
 | |
|          * @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 this;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Slices the ByteBuffer. This is independent of the ByteBuffer's actual offsets. Does not compact the underlying
 | |
|          *  ArrayBuffer (use {@link ByteBuffer#compact} or {@link ByteBuffer.wrap} instead).
 | |
|          * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
 | |
|          * @param {number=} end End offset, defaults to {@link ByteBuffer#length}.
 | |
|          * @returns {!ByteBuffer} Clone of this ByteBuffer with 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 (typeof begin === 'undefined') begin = this.offset;
 | |
|             if (typeof end === 'undefined') end = this.length;
 | |
|             if (end <= begin) {
 | |
|                 var t = end; end = begin; begin = t;
 | |
|             }
 | |
|             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;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * 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
 | |
|          * @returns {!ByteBuffer} this
 | |
|          * @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 this;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Makes the buffer ready for a new sequence of write or relative read operations. Sets `length=offset` and
 | |
|          *  `offset=0`. Always make sure to flip a buffer when all relative writing operations are complete.
 | |
|          * @returns {!ByteBuffer} this
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.flip = function() {
 | |
|             this.length = this.array == null ? 0 : this.offset;
 | |
|             this.offset = 0;
 | |
|             return this;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Marks an offset to be used with {@link ByteBuffer#reset}.
 | |
|          * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}.
 | |
|          * @returns {!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`.
 | |
|          * @returns {!ByteBuffer} this
 | |
|          * @see ByteBuffer#mark
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.reset = function() {
 | |
|             if (this.array === null) {
 | |
|                 throw(new Error(this+" cannot be reset: Already destroyed"));
 | |
|             }
 | |
|             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 backing array but will have its own
 | |
|          *  offsets.
 | |
|          * @returns {!ByteBuffer} Clone
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.clone = function() {
 | |
|             var b = new ByteBuffer(-1, this.littleEndian, /* no init, undocumented */ true);
 | |
|             b.array = this.array;
 | |
|             b.view = this.view;
 | |
|             b.offset = this.offset;
 | |
|             b.markedOffset = this.markedOffset;
 | |
|             b.length = this.length;
 | |
|             return b;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Copies this ByteBuffer. The copy has its own backing array and uses the same offsets as this one.
 | |
|          * @returns {!ByteBuffer} Copy
 | |
|          * @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.markedOffset = this.markedOffset;
 | |
|             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`.
 | |
|          * @returns {number} Remaining readable bytes. May be negative if `offset>length`.
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.remaining = function() {
 | |
|             if (this.array === null) return 0;
 | |
|             return this.length - this.offset;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Gets the capacity of the backing buffer. This is independent from {@link ByteBuffer#length} and returns the
 | |
|          *  size of the entire backing array.
 | |
|          * @returns {number} Capacity of the backing array 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 set `offset=0` and
 | |
|          *  `length=capacity`.
 | |
|          * @returns {!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) {
 | |
|                 this.array = new ArrayBuffer(0);
 | |
|                 this.view = null; // A DataView on a zero-length AB would throw
 | |
|                 return this;
 | |
|             }
 | |
|             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;
 | |
|             if (this.markedOffset >= this.offset) {
 | |
|                 this.markedOffset -= this.offset;
 | |
|             } else {
 | |
|                 this.markedOffset = -1;
 | |
|             }
 | |
|             this.offset = 0;
 | |
|             this.length = this.array.byteLength;
 | |
|             return this;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Manually destroys the ByteBuffer, releasing references to the backing array. Manually destroying a ByteBuffer
 | |
|          *  is usually not required but may be useful in limited memory environments. Most successive operations will
 | |
|          *  rise an error until {@link ByteBuffer#resize} or {@link ByteBuffer#ensureCapacity} is called to reinitialize
 | |
|          *  the backing array.
 | |
|          * @returns {!ByteBuffer} this
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.destroy = function() {
 | |
|             if (this.array !== null) {
 | |
|                 this.array = null;
 | |
|                 this.view = null;
 | |
|                 this.offset = 0;
 | |
|                 this.markedOffset = -1;
 | |
|                 this.length = 0;
 | |
|             }
 | |
|             return this;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Reverses the backing array 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". Also clears the marked
 | |
|          *  offset.
 | |
|          * @returns {!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"));
 | |
|             }
 | |
|             Array.prototype.reverse.call(new Uint8Array(this.array));
 | |
|             var o = this.offset;
 | |
|             this.offset = this.array.byteLength - this.length;
 | |
|             this.markedOffset = -1;
 | |
|             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 contained in
 | |
|          *  the specified ByteBuffer. Offset and length of the specified ByteBuffer will remain the same.
 | |
|          * @param {!*} src ByteBuffer or any object that can be wrapped to append
 | |
|          * @param {number=} offset Offset to append at. Defaults to {@link ByteBuffer#offset}.
 | |
|          * @returns {!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); // Reinitializes if required
 | |
|             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 contained in
 | |
|          *  the specified ByteBuffer. Offset and length of the specified ByteBuffer will remain the same.
 | |
|          * @param {!*} src ByteBuffer or any object that can be wrapped to prepend
 | |
|          * @param {number=} offset Offset to prepend at. Defaults to {@link ByteBuffer#offset}.
 | |
|          * @returns {!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 signed integer.
 | |
|          * @param {number} value Value
 | |
|          * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} if
 | |
|          *  omitted.
 | |
|          * @returns {!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 signed integer.
 | |
|          * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.readByte = ByteBuffer.prototype.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} if omitted.
 | |
|          * @returns {!ByteBuffer} this
 | |
|          * @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 unsigned integer.
 | |
|          * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.readFloat = ByteBuffer.prototype.readFloat32;
 | |
| 
 | |
|         /**
 | |
|          * Writes a 64bit float.
 | |
|          * @param {number} value Value to write
 | |
|          * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {number}
 | |
|          * @throws {Error} If offset is out of bounds
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.readDouble = ByteBuffer.prototype.readFloat64;
 | |
| 
 | |
|         // Available with Long.js only
 | |
|         if (Long) {
 | |
| 
 | |
|             /**
 | |
|              * Writes a 64bit integer. Requires Long.js.
 | |
|              * @function
 | |
|              * @param {number|!Long} value Value to write
 | |
|              * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|              * @returns {!ByteBuffer} this
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.prototype.writeInt64 = function(value, offset) {
 | |
|                 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. Requires Long.js.
 | |
|              * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|              * @returns {!Long}
 | |
|              * @throws {Error} If offset is out of bounds
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.prototype.readInt64 = function(offset) {
 | |
|                 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. Requires Long.js.
 | |
|              * @function
 | |
|              * @param {number|!Long} value Value to write
 | |
|              * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|              * @returns {!ByteBuffer} this
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.prototype.writeUint64 = function(value, offset) {
 | |
|                 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. Requires Long.js.
 | |
|              * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|              * @returns {!Long}
 | |
|              * @throws {Error} If offset is out of bounds
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.prototype.readUint64 = function(offset) {
 | |
|                 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|!Long} value Value to write
 | |
|              * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|              * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|              * @returns {!Long}
 | |
|              * @throws {Error} If offset is out of bounds
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.prototype.readLong = ByteBuffer.prototype.readInt64;
 | |
| 
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Maximum number of bytes used by 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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} 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
 | |
|          */
 | |
|         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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} 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
 | |
|          */
 | |
|         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 used by a 64bit base 128 variable-length integer.
 | |
|          * @type {number}
 | |
|          * @const
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.MAX_VARINT64_BYTES = 10;
 | |
| 
 | |
|         /**
 | |
|          * @type {number}
 | |
|          * @const
 | |
|          * @inner
 | |
|          */
 | |
|         var TWO_PWR_7_DBL = 1 << 7;
 | |
| 
 | |
|         /**
 | |
|          * @type {number}
 | |
|          * @const
 | |
|          * @inner
 | |
|          */
 | |
|         var TWO_PWR_14_DBL = TWO_PWR_7_DBL * TWO_PWR_7_DBL;
 | |
| 
 | |
|         /**
 | |
|          * @type {number}
 | |
|          * @const
 | |
|          * @inner
 | |
|          */
 | |
|         var TWO_PWR_21_DBL = TWO_PWR_7_DBL * TWO_PWR_14_DBL;
 | |
| 
 | |
|         /**
 | |
|          * @type {number}
 | |
|          * @const
 | |
|          * @inner
 | |
|          */
 | |
|         var TWO_PWR_28_DBL = TWO_PWR_14_DBL * TWO_PWR_14_DBL;
 | |
| 
 | |
|         // Available with Long.js only
 | |
|         if (Long) {
 | |
| 
 | |
|             /**
 | |
|              * 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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|              * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.prototype.writeVarint64 = function(value, offset) {
 | |
|                 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. Requires Long.js.
 | |
|              * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} 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
 | |
|              */
 | |
|             ByteBuffer.prototype.readVarint64 = function(offset) {
 | |
|                 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.
 | |
|              * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
 | |
|              * @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.
 | |
|              * @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
 | |
|              */
 | |
|             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.
 | |
|          * @returns {!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.
 | |
|          * @returns {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.
 | |
|          * @returns {!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.
 | |
|          * @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
 | |
|          */
 | |
|         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
 | |
|          * @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 < 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;
 | |
|             }
 | |
|         };
 | |
|         
 | |
|         // Available with Long.js only
 | |
|         if (Long) {
 | |
|     
 | |
|             /**
 | |
|              * Calculates the actual number of bytes required to encode 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) {
 | |
|                 // 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
 | |
|          * @returns {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
 | |
|          * @returns {number} Signed 32bit integer
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.zigZagDecode32 = function(n) {
 | |
|             // ref: src/google/protobuf/wire_format_lite.h
 | |
|             return ((n >>> 1) ^ -(n & 1)) | 0;
 | |
|         };
 | |
|         
 | |
|         // Available with Long.js only
 | |
|         if (Long) {
 | |
|     
 | |
|             /**
 | |
|              * Encodes a signed 64bit integer so that it can be effectively used with varint encoding.
 | |
|              * @param {number|!Long} n Signed long
 | |
|              * @returns {!Long} Unsigned zigzag encoded long
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.zigZagEncode64 = function(n) {
 | |
|                 // 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|number} n Unsigned zigzag encoded long or JavaScript number
 | |
|              * @returns {!Long} Signed long
 | |
|              * @throws {Error} If long support is not available
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.zigZagDecode64 = function(n) {
 | |
|                 // 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
 | |
|          * @returns {!{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
 | |
|          * @returns {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
 | |
|          * @returns {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
 | |
|          * @returns {number} Number of bytes required
 | |
|          */
 | |
|         ByteBuffer.calculateUTF8String = function(str) {
 | |
|             str = ""+str;
 | |
|             var bytes = 0;
 | |
|             for (var i=0, k=str.length; i<k; ++i) {
 | |
|                 // Does not throw since JS strings are already UTF8 encoded
 | |
|                 bytes += ByteBuffer.calculateUTF8Char(str.charCodeAt(i));
 | |
|             }
 | |
|             return bytes;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Base64 alphabet.
 | |
|          * @type {string}
 | |
|          * @inner
 | |
|          */
 | |
|         var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 | |
|         B64 = B64+""; // Prevent CC from inlining this for less code size
 | |
| 
 | |
|         /**
 | |
|          * Encodes a ByteBuffer's contents to a base64 string.
 | |
|          * @param {!ByteBuffer} bb ByteBuffer to encode. Will be cloned and flipped if length < offset.
 | |
|          * @returns {string} Base64 encoded string
 | |
|          * @throws {Error} If the argument is not a valid ByteBuffer
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.encode64 = function(bb) {
 | |
|             // ref: http://phpjs.org/functions/base64_encode/
 | |
|              if (!(bb instanceof ByteBuffer)) {
 | |
|                 bb = ByteBuffer.wrap(bb);
 | |
|             } else if (bb.length < bb.offset) {
 | |
|                  bb = bb.clone().flip();
 | |
|              }
 | |
|             var o1, o2, o3, h1, h2, h3, h4, bits, i = bb.offset,
 | |
|                 oi = 0,
 | |
|                 out = [];
 | |
|             do {
 | |
|                 o1 = bb.readUint8(i++);
 | |
|                 o2 = bb.length > 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 base64 encoded string to a ByteBuffer.
 | |
|          * @param {string} str Base64 encoded string
 | |
|          * @param {boolean=} littleEndian `true` to use little endian byte order, defaults to `false` for big endian.
 | |
|          * @returns {!ByteBuffer} ByteBuffer
 | |
|          * @throws {Error} If the argument is not a valid base64 encoded string
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.decode64 = function(str, littleEndian) {
 | |
|             // 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), littleEndian);
 | |
|             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();
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Encodes a ByteBuffer to a hex encoded string.
 | |
|          * @param {!ByteBuffer} bb ByteBuffer to encode. Will be cloned and flipped if length < offset.
 | |
|          * @returns {string} Hex encoded string
 | |
|          * @throws {Error} If the argument is not a valid ByteBuffer
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.encodeHex = function(bb) {
 | |
|             if (!(bb instanceof ByteBuffer)) {
 | |
|                 bb = ByteBuffer.wrap(bb);
 | |
|             } else if (bb.length < bb.offset) {
 | |
|                 bb = bb.clone().flip();
 | |
|             }
 | |
|             if (bb.array === null) return "";
 | |
|             var val, out = [];
 | |
|             for (var i=bb.offset, k=bb.length; i<k; ++i) {
 | |
|                 val = bb.view.getUint8(i).toString(16).toUpperCase();
 | |
|                 if (val.length < 2) val = "0"+val;
 | |
|                 out.push(val);
 | |
|             }
 | |
|             return out.join('');
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Decodes a hex encoded string to a ByteBuffer.
 | |
|          * @param {string} str Hex encoded string
 | |
|          * @param {boolean=} littleEndian `true` to use little endian byte order, defaults to `false` for big endian.
 | |
|          * @returns {!ByteBuffer} ByteBuffer
 | |
|          * @throws {Error} If the argument is not a valid hex encoded string
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.decodeHex = function(str, littleEndian) {
 | |
|             if (typeof str !== 'string') {
 | |
|                 throw(new Error("Illegal argument: Not a string"));
 | |
|             }
 | |
|             if (str.length % 2 !== 0) {
 | |
|                 throw(new Error("Illegal argument: Not a hex encoded string"));
 | |
|             }
 | |
|             var o,
 | |
|                 out = new ByteBuffer(str.length/2, littleEndian);
 | |
|             for (var i=0, k=str.length; i<k; i+=2) {
 | |
|                 out.writeUint8(parseInt(str.substring(i, i+2), 16));
 | |
|             }
 | |
|             return out.flip();
 | |
|         };
 | |
| 
 | |
|         // NOTE on binary strings: Binary strings as used here have nothing to do with frequently asked questions about
 | |
|         // conversion between ArrayBuffer and String. What we do here is what libraries like node-forge do to simulate a
 | |
|         // byte buffer: Conversion between 8 bit unsigned integers and the low 8 bit UTF8/UCS2 characters. This is not
 | |
|         // perfect as it effectively uses 16 bit per character in memory to store the 8 bit values, but that's not our
 | |
|         // concern as we just want it to be compatible. It's always better to use ArrayBuffer/Buffer (!) while base64
 | |
|         // and hex should be slightly worse regarding memory consumption and encoding speed.
 | |
| 
 | |
|         /**
 | |
|          * Encodes a ByteBuffer to a binary string. A binary string in this case is a string composed of 8bit values
 | |
|          *  as characters with a char code between 0 and 255 inclusive.
 | |
|          * @param {!ByteBuffer} bb ByteBuffer to encode. Will be cloned and flipped if length < offset.
 | |
|          * @returns {string} Binary string
 | |
|          * @throws {Error} If the argument is not a valid ByteBuffer
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.encodeBinary = function(bb) {
 | |
|             if (!(bb instanceof ByteBuffer)) {
 | |
|                 bb = ByteBuffer.wrap(bb);
 | |
|             } else if (bb.length < bb.offset) {
 | |
|                 bb = bb.clone().flip();
 | |
|             }
 | |
|             var out = [], view = bb.view;
 | |
|             for (var i=bb.offset, k=bb.length; i<k; ++i) {
 | |
|                 out.push(String.fromCharCode(view.getUint8(i)));
 | |
|             }
 | |
|             return out.join('');
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Decodes a binary string to a ByteBuffer. A binary string in this case is a string composed of 8bit values
 | |
|          *  as characters with a char code between 0 and 255 inclusive.
 | |
|          * @param {string} str Binary string
 | |
|          * @param {boolean=} littleEndian `true` to use little endian byte order, defaults to `false` for big endian.
 | |
|          * @returns {!ByteBuffer} ByteBuffer
 | |
|          * @throws {Error} If the argument is not a valid binary string
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.decodeBinary = function(str, littleEndian) {
 | |
|             if (typeof str !== 'string') {
 | |
|                 throw(new Error("Illegal argument: Not a string"));
 | |
|             }
 | |
|             var k=str.length,
 | |
|                 dst = new ArrayBuffer(k),
 | |
|                 view = new DataView(dst),
 | |
|                 val;
 | |
|             for (var i=0; i<k; ++i) {
 | |
|                 if ((val = str.charCodeAt(i)) > 255) throw(new Error("Illegal argument: Not a binary string (char code "+val+")"));
 | |
|                 view.setUint8(i, val);
 | |
|             }
 | |
|             var bb = new ByteBuffer(k, littleEndian, true);
 | |
|             bb.array = dst;
 | |
|             bb.view = view;
 | |
|             bb.length = k;
 | |
|             return bb;
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Writes an UTF8 string.
 | |
|          * @param {string} str String to write
 | |
|          * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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); // See [1]
 | |
|             this.ensureCapacity(offset+encLen);
 | |
|             for (var i=0, j=str.length; i<j; ++i) {
 | |
|                 // [1] Does not throw since JS strings are already UTF8 encoded
 | |
|                 offset += ByteBuffer.encodeUTF8Char(str.charCodeAt(i), this, offset);
 | |
|             }
 | |
|             if (advance) {
 | |
|                 this.offset = offset;
 | |
|                 return this;
 | |
|             } else {
 | |
|                 return offset-start;
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Reads an UTF8 string.
 | |
|          * @param {number} chars Number of characters to read
 | |
|          * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} 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.
 | |
|          * @throws {Error} If the string cannot be decoded
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.readUTF8String = function(chars, offset) {
 | |
|             var advance = typeof offset === 'undefined';
 | |
|             offset = typeof offset !== 'undefined' ? offset : this.offset;
 | |
|             var dec, result = "", start = offset;
 | |
|             for (var i=0; i<chars; ++i) {
 | |
|                 dec = ByteBuffer.decodeUTF8Char(this, offset);
 | |
|                 offset += dec["length"];
 | |
|                 result += String.fromCharCode(dec["char"]);
 | |
|             }
 | |
|             if (advance) {
 | |
|                 this.offset = offset;
 | |
|                 return result;
 | |
|             } else {
 | |
|                 return {
 | |
|                     "string": result,
 | |
|                     "length": offset-start
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Reads an UTF8 string with the specified byte length.
 | |
|          * @param {number} length Byte length
 | |
|          * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} 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
 | |
|          * @throws {Error} If the length did not match or the string cannot be decoded
 | |
|          */
 | |
|         ByteBuffer.prototype.readUTF8StringBytes = function(length, offset) {
 | |
|             var advance = typeof offset === 'undefined';
 | |
|             offset = typeof offset !== 'undefined' ? offset : this.offset;
 | |
|             var dec, result = "", start = offset;
 | |
|             length = offset + length; // Limit
 | |
|             while (offset < length) {
 | |
|                 dec = ByteBuffer.decodeUTF8Char(this, offset);
 | |
|                 offset += dec["length"];
 | |
|                 result += String.fromCharCode(dec["char"]);
 | |
|             }
 | |
|             if (offset != length) {
 | |
|                 throw(new Error("Actual string length differs from the specified: "+((offset>length ? "+" : "")+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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} 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.
 | |
|          * @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),
 | |
|                 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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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 prepended number of characters, which is encoded as a 32bit base 128 variable-length 
 | |
|          *  integer.
 | |
|          * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} 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.
 | |
|          * @throws {Error} If the string cannot be decoded or if it is not preceeded by 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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} 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.
 | |
|          * @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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @param {function(*)=} stringify Stringify implementation to use. Defaults to {@link JSON.stringify}.
 | |
|          * @returns {!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. Will use and advance {@link ByteBuffer#offset} if omitted.
 | |
|          * @param {function(string)=} parse Parse implementation to use. Defaults to {@link JSON.parse}.
 | |
|          * @returns {!*|!{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"]
 | |
|                 };
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Returns a textual two columns (hex, ascii) representation of this ByteBuffer's backing array.
 | |
|          * @param {number=} wrap Wrap length. Defaults to 16.
 | |
|          * @returns {string} Hex representation as of " 00<01 02>03... ASCII DATA" with marked offsets
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.toColumns = function(wrap) {
 | |
|             if (this.array === null) return "DESTROYED";
 | |
|             wrap = typeof wrap !== 'undefined' ? parseInt(wrap, 10) : 16;
 | |
|             if (wrap < 1) wrap = 16;
 | |
| 
 | |
|             // Left colum: hex with offsets
 | |
|             var out = "",
 | |
|                 lines = [],
 | |
|                 val,
 | |
|                 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, k=this.array.byteLength; i<k; ++i) {
 | |
|                 if (i>0 && i%wrap == 0) {
 | |
|                     while (out.length < 3*wrap+1) out += "   "; // Make it equal to maybe show something on the right
 | |
|                     lines.push(out);
 | |
|                     out = " ";
 | |
|                 }
 | |
|                 val =  view.getUint8(i).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 (out != " ") {
 | |
|                 lines.push(out);
 | |
|             }
 | |
|             // Make it equal
 | |
|             for (i=0, k=lines.length; i<k; ++i) {
 | |
|                 while (lines[i].length < 3*wrap+1) lines[i] += "   "; // Make it equal to maybe show something on the right
 | |
|             }
 | |
| 
 | |
|             // Right column: ASCII, using dots for (usually) non-printable characters
 | |
|             var n = 0;
 | |
|             out = "";
 | |
|             for (i=0, k=this.array.byteLength; i<k; ++i) {
 | |
|                 if (i>0 && i%wrap == 0) {
 | |
|                     lines[n] += " "+out;
 | |
|                     out = ""; n++;
 | |
|                 }
 | |
|                 val = view.getUint8(i);
 | |
|                 out += val > 32 && val < 127 ? String.fromCharCode(val) : ".";
 | |
|             }
 | |
|             if (out != "") {
 | |
|                 lines[n] += " "+out;
 | |
|             }
 | |
|             return lines.join("\n");
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Prints debug information about this ByteBuffer's contents.
 | |
|          * @param {function(string)=} out Output function to call, defaults to console.log
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.printDebug = function(out) {
 | |
|             if (typeof out !== 'function') out = console.log.bind(console);
 | |
|             out(
 | |
|                 (this.array != null ? "ByteBuffer(offset="+this.offset+",markedOffset="+this.markedOffset+",length="+this.length+",capacity="+this.array.byteLength+")" : "ByteBuffer(DESTROYED)")+"\n"+
 | |
|                     "-------------------------------------------------------------------\n"+
 | |
|                     this.toColumns()+"\n"
 | |
|             );
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Returns the ByteBuffer's contents between offset and length as a hex string.
 | |
|          * @param {boolean=} debug `true` to return the entire backing array with marked offsets, defaults to `false`
 | |
|          * @returns {string} Hex string or debug string
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.toHex = function(debug) {
 | |
|             var out = "",
 | |
|                 val,
 | |
|                 view = this.view,
 | |
|                 i, k;
 | |
|             if (!debug) {
 | |
|                 return ByteBuffer.encodeHex(this);
 | |
|             } else {
 | |
|                 if (this.array === null) return "DESTROYED";
 | |
|                 if (this.offset == 0 && this.length == 0) {
 | |
|                     out += "|";
 | |
|                 } else if (this.length == 0) {
 | |
|                     out += ">";
 | |
|                 } else if (this.offset == 0) {
 | |
|                     out += "<";
 | |
|                 } else {
 | |
|                     out += " ";
 | |
|                 }
 | |
|                 for (i=0, k=this.array.byteLength; i<k; ++i) {
 | |
|                     val =  view.getUint8(i).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 += " ";
 | |
|                     }
 | |
|                 }
 | |
|                 return out;
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Returns the ByteBuffer's contents between offset and length as a binary string. A binary string in this case
 | |
|          *  is a string composed of 8bit values as characters with a char code between 0 and 255 inclusive.
 | |
|          * @returns {string} Binary string
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.toBinary = function() {
 | |
|             return ByteBuffer.encodeBinary(this);
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Returns the base64 encoded representation of the ByteBuffer'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 ByteBuffer's contents 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"];
 | |
|         };
 | |
| 
 | |
|         /**
 | |
|          * Converts the ByteBuffer to a string.
 | |
|          * @param {string=} enc Output encoding. Returns an informative string representation by default but also allows
 | |
|          *  direct conversion to "utf8", "hex", "base64" and "binary" encoding. "debug" returns a hex representation with
 | |
|          *  marked offsets.
 | |
|          * @returns {string} String representation
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.toString = function(enc) {
 | |
|             enc = enc || "";
 | |
|             switch (enc) {
 | |
|                 case "utf8":
 | |
|                     return this.toUTF8();
 | |
|                 case "base64":
 | |
|                     return this.toBase64();
 | |
|                 case "hex":
 | |
|                     return this.toHex();
 | |
|                 case "binary":
 | |
|                     return this.toBinary();
 | |
|                 case "debug":
 | |
|                     return this.toHex(true);
 | |
|                 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 transparently
 | |
|          *  {@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 `true` forces the creation of a copy, defaults to `false`
 | |
|          * @returns {?ArrayBuffer} Compacted ArrayBuffer or null if already destroyed
 | |
|          * @expose
 | |
|          */
 | |
|         ByteBuffer.prototype.toArrayBuffer = function(forceCopy) {
 | |
|             if (this.array === null) return null;
 | |
|             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;
 | |
|         };
 | |
|         
 | |
|         // Available with node.js only
 | |
|         if (Buffer) {
 | |
|     
 | |
|             /**
 | |
|              * Returns a node Buffer compacted to contain this ByteBuffer's actual contents. Will transparently
 | |
|              *  {@link ByteBuffer#flip} the ByteBuffer if its offset is larger than its length. Will also copy all data (not
 | |
|              *  a reference).
 | |
|              * @returns {?Buffer} Compacted node Buffer or null if already destroyed
 | |
|              * @expose
 | |
|              */
 | |
|             ByteBuffer.prototype.toBuffer = function() {
 | |
|                 if (this.array === null) return null;
 | |
|                 var offset = this.offset, length = this.length;
 | |
|                 if (offset > length) {
 | |
|                     var temp = offset;
 | |
|                     offset = length;
 | |
|                     length = temp;
 | |
|                 }
 | |
|                 return new Buffer(new Uint8Array(this.array).subarray(offset, length));
 | |
|             };
 | |
|             
 | |
|         }
 | |
| 
 | |
|         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(global["dcodeIO"]["Long"]);
 | |
|     }
 | |
| 
 | |
| })(this);
 |