Comparing version 2.1.0 to 3.0.0
307
IOBuffer.js
@@ -6,5 +6,23 @@ 'use strict'; | ||
/** | ||
* IOBuffer | ||
* @constructor | ||
* @param {undefined|number|ArrayBuffer|TypedArray|IOBuffer|Buffer} data - The data to construct the IOBuffer with. | ||
* | ||
* If it's a number, it will initialize the buffer with the number as the buffer's length<br> | ||
* If it's undefined, it will initialize the buffer with a default length of 8 Kb<br> | ||
* If its an ArrayBuffer, a TypedArray, an IOBuffer instance, | ||
* or a Node.js Buffer, it will create a view over the underlying ArrayBuffer. | ||
* @param {object} [options] | ||
* @param {number} [options.offset=0] - Ignore the first n bytes of the ArrayBuffer | ||
* @property {ArrayBuffer} buffer - Reference to the internal ArrayBuffer object | ||
* @property {number} length - Byte length of the internal ArrayBuffer | ||
* @property {number} offset - The current offset of the buffer's pointer | ||
* @property {number} byteLength - Byte length of the internal ArrayBuffer | ||
* @property {number} byteOffset - Byte offset of the internal ArrayBuffer | ||
*/ | ||
class IOBuffer { | ||
constructor(data, options) { | ||
options = options || {}; | ||
var dataIsGiven = false; | ||
if (data === undefined) { | ||
@@ -15,26 +33,37 @@ data = defaultByteLength; | ||
data = new ArrayBuffer(data); | ||
} else { | ||
dataIsGiven = true; | ||
this._lastWrittenByte = data.byteLength; | ||
} | ||
let length = data.byteLength; | ||
const offset = options.offset ? options.offset>>>0 : 0; | ||
const offset = options.offset ? options.offset >>> 0 : 0; | ||
let byteLength = data.byteLength - offset; | ||
let dvOffset = offset; | ||
if (data.buffer) { | ||
length = data.byteLength - offset; | ||
if (data.byteLength !== data.buffer.byteLength) { // Node.js buffer from pool | ||
data = data.buffer.slice(data.byteOffset + offset, data.byteOffset + data.byteLength); | ||
} else if (offset) { | ||
data = data.buffer.slice(offset); | ||
} else { | ||
data = data.buffer; | ||
if (data.byteLength !== data.buffer.byteLength) { | ||
dvOffset = data.byteOffset + offset; | ||
} | ||
data = data.buffer; | ||
} | ||
if (dataIsGiven) { | ||
this._lastWrittenByte = byteLength; | ||
} else { | ||
this._lastWrittenByte = 0; | ||
} | ||
this.buffer = data; | ||
this.length = length; | ||
this.byteLength = length; | ||
this.byteOffset = 0; | ||
this.length = byteLength; | ||
this.byteLength = byteLength; | ||
this.byteOffset = dvOffset; | ||
this.offset = 0; | ||
this.littleEndian = true; | ||
this._data = new DataView(this.buffer); | ||
this._increment = length || defaultByteLength; | ||
this._data = new DataView(this.buffer, dvOffset, byteLength); | ||
this._mark = 0; | ||
this._marks = []; | ||
} | ||
/** | ||
* Checks if the memory allocated to the buffer is sufficient to store more bytes after the offset | ||
* @param {number} [byteLength=1] The needed memory in bytes | ||
* @return {boolean} Returns true if there is sufficient space and false otherwise | ||
*/ | ||
available(byteLength) { | ||
@@ -45,2 +74,6 @@ if (byteLength === undefined) byteLength = 1; | ||
/** | ||
* Check if little-endian mode is used for reading and writing multi-byte values | ||
* @return {boolean} Returns true if little-endian mode is used, false otherwise | ||
*/ | ||
isLittleEndian() { | ||
@@ -50,6 +83,15 @@ return this.littleEndian; | ||
/** | ||
* Set little-endian mode for reading and writing multi-byte values | ||
* @return {IOBuffer} | ||
*/ | ||
setLittleEndian() { | ||
this.littleEndian = true; | ||
return this; | ||
} | ||
/** | ||
* Check if big-endian mode is used for reading and writing multi-byte values | ||
* @return {boolean} Returns true if big-endian mode is used, false otherwise | ||
*/ | ||
isBigEndian() { | ||
@@ -59,41 +101,109 @@ return !this.littleEndian; | ||
/** | ||
* Switches to big-endian mode for reading and writing multi-byte values | ||
* @return {IOBuffer} | ||
*/ | ||
setBigEndian() { | ||
this.littleEndian = false; | ||
return this; | ||
} | ||
/** | ||
* Move the pointer n bytes forward | ||
* @param {number} n | ||
* @return {IOBuffer} | ||
*/ | ||
skip(n) { | ||
if (n === undefined) n = 1; | ||
this.offset += n; | ||
return this; | ||
} | ||
/** | ||
* Move the pointer to the given offset | ||
* @param {number} offset | ||
* @return {IOBuffer} | ||
*/ | ||
seek(offset) { | ||
this.offset = offset; | ||
return this; | ||
} | ||
/** | ||
* Store the current pointer offset. | ||
* @see {@link IOBuffer#reset} | ||
* @return {IOBuffer} | ||
*/ | ||
mark() { | ||
this._mark = this.offset; | ||
return this; | ||
} | ||
/** | ||
* Move the pointer back to the last pointer offset set by mark | ||
* @see {@link IOBuffer#mark} | ||
* @return {IOBuffer} | ||
*/ | ||
reset() { | ||
this.offset = this._mark; | ||
return this; | ||
} | ||
/** | ||
* Push the current pointer offset to the mark stack | ||
* @see {@link IOBuffer#popMark} | ||
* @return {IOBuffer} | ||
*/ | ||
pushMark() { | ||
this._marks.push(this.offset); | ||
return this; | ||
} | ||
/** | ||
* Pop the last pointer offset from the mark stack, and set the current pointer offset to the popped value | ||
* @see {@link IOBuffer#pushMark} | ||
* @return {IOBuffer} | ||
*/ | ||
popMark() { | ||
const offset = this._marks.pop(); | ||
if (offset === undefined) throw new Error('Mark stack empty'); | ||
this.seek(offset); | ||
return this; | ||
} | ||
/** | ||
* Move the pointer offset back to 0 | ||
* @return {IOBuffer} | ||
*/ | ||
rewind() { | ||
this.offset = 0; | ||
return this; | ||
} | ||
/** | ||
* Make sure the buffer has sufficient memory to write a given byteLength at the current pointer offset | ||
* If the buffer's memory is insufficient, this method will create a new buffer (a copy) with a length | ||
* that is twice (byteLength + current offset) | ||
* @param {number} [byteLength = 1] | ||
* @return {IOBuffer} | ||
*/ | ||
ensureAvailable(byteLength) { | ||
if (byteLength === undefined) byteLength = 1; | ||
if (!this.available(byteLength)) { | ||
const newIncrement = this._increment + this._increment; | ||
this._increment = newIncrement; | ||
const newLength = this.length + newIncrement; | ||
const lengthNeeded = this.offset + byteLength; | ||
const newLength = lengthNeeded * 2; | ||
const newArray = new Uint8Array(newLength); | ||
newArray.set(new Uint8Array(this.buffer)); | ||
this.buffer = newArray.buffer; | ||
this.length = newLength; | ||
this.length = this.byteLength = newLength; | ||
this._data = new DataView(this.buffer); | ||
} | ||
return this; | ||
} | ||
/** | ||
* Read a byte and return false if the byte's value is 0, or true otherwise | ||
* Moves pointer forward | ||
* @return {boolean} | ||
*/ | ||
readBoolean() { | ||
@@ -103,2 +213,6 @@ return this.readUint8() !== 0; | ||
/** | ||
* Read a signed 8-bit integer and move pointer forward | ||
* @return {number} | ||
*/ | ||
readInt8() { | ||
@@ -108,2 +222,6 @@ return this._data.getInt8(this.offset++); | ||
/** | ||
* Read an unsigned 8-bit integer and move pointer forward | ||
* @return {number} | ||
*/ | ||
readUint8() { | ||
@@ -113,2 +231,6 @@ return this._data.getUint8(this.offset++); | ||
/** | ||
* Alias for {@link IOBuffer#readUint8} | ||
* @return {number} | ||
*/ | ||
readByte() { | ||
@@ -118,2 +240,7 @@ return this.readUint8(); | ||
/** | ||
* Read n bytes and move pointer forward. | ||
* @param {number} n | ||
* @return {Uint8Array} | ||
*/ | ||
readBytes(n) { | ||
@@ -128,2 +255,6 @@ if (n === undefined) n = 1; | ||
/** | ||
* Read a 16-bit signed integer and move pointer forward | ||
* @return {number} | ||
*/ | ||
readInt16() { | ||
@@ -135,2 +266,6 @@ var value = this._data.getInt16(this.offset, this.littleEndian); | ||
/** | ||
* Read a 16-bit unsigned integer and move pointer forward | ||
* @return {number} | ||
*/ | ||
readUint16() { | ||
@@ -142,2 +277,6 @@ var value = this._data.getUint16(this.offset, this.littleEndian); | ||
/** | ||
* Read a 32-bit signed integer and move pointer forward | ||
* @return {number} | ||
*/ | ||
readInt32() { | ||
@@ -149,2 +288,6 @@ var value = this._data.getInt32(this.offset, this.littleEndian); | ||
/** | ||
* Read a 32-bit unsigned integer and move pointer forward | ||
* @return {number} | ||
*/ | ||
readUint32() { | ||
@@ -156,2 +299,6 @@ var value = this._data.getUint32(this.offset, this.littleEndian); | ||
/** | ||
* Read a 32-bit floating number and move pointer forward | ||
* @return {number} | ||
*/ | ||
readFloat32() { | ||
@@ -163,2 +310,6 @@ var value = this._data.getFloat32(this.offset, this.littleEndian); | ||
/** | ||
* Read a 64-bit floating number and move pointer forward | ||
* @return {number} | ||
*/ | ||
readFloat64() { | ||
@@ -170,2 +321,6 @@ var value = this._data.getFloat64(this.offset, this.littleEndian); | ||
/** | ||
* Read 1-byte ascii character and move pointer forward | ||
* @return {string} | ||
*/ | ||
readChar() { | ||
@@ -175,2 +330,7 @@ return String.fromCharCode(this.readInt8()); | ||
/** | ||
* Read n 1-byte ascii characters and move pointer forward | ||
* @param {number} n | ||
* @return {string} | ||
*/ | ||
readChars(n) { | ||
@@ -185,20 +345,50 @@ if (n === undefined) n = 1; | ||
writeBoolean(bool) { | ||
this.writeUint8(bool ? 0xff : 0x00); | ||
/** | ||
* Write 0xff if the passed value is truthy, 0x00 otherwise | ||
* @param {any} value | ||
* @return {IOBuffer} | ||
*/ | ||
writeBoolean(value) { | ||
this.writeUint8(value ? 0xff : 0x00); | ||
return this; | ||
} | ||
/** | ||
* Write value as an 8-bit signed integer | ||
* @param {number} value | ||
* @return {IOBuffer} | ||
*/ | ||
writeInt8(value) { | ||
this.ensureAvailable(1); | ||
this._data.setInt8(this.offset++, value); | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* Write value as a 8-bit unsigned integer | ||
* @param {number} value | ||
* @return {IOBuffer} | ||
*/ | ||
writeUint8(value) { | ||
this.ensureAvailable(1); | ||
this._data.setUint8(this.offset++, value); | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* An alias for {@link IOBuffer#writeUint8} | ||
* @param {number} value | ||
* @return {IOBuffer} | ||
*/ | ||
writeByte(value) { | ||
this.writeUint8(value); | ||
return this.writeUint8(value); | ||
} | ||
/** | ||
* Write bytes | ||
* @param {Array|Uint8Array} bytes | ||
* @return {IOBuffer} | ||
*/ | ||
writeBytes(bytes) { | ||
@@ -209,4 +399,11 @@ this.ensureAvailable(bytes.length); | ||
} | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* Write value as an 16-bit signed integer | ||
* @param {number} value | ||
* @return {IOBuffer} | ||
*/ | ||
writeInt16(value) { | ||
@@ -216,4 +413,11 @@ this.ensureAvailable(2); | ||
this.offset += 2; | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* Write value as a 16-bit unsigned integer | ||
* @param {number} value | ||
* @return {IOBuffer} | ||
*/ | ||
writeUint16(value) { | ||
@@ -223,4 +427,11 @@ this.ensureAvailable(2); | ||
this.offset += 2; | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* Write a 32-bit signed integer at the current pointer offset | ||
* @param {number} value | ||
* @return {IOBuffer} | ||
*/ | ||
writeInt32(value) { | ||
@@ -230,4 +441,11 @@ this.ensureAvailable(4); | ||
this.offset += 4; | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* Write a 32-bit unsigned integer at the current pointer offset | ||
* @param {number} value - The value to set | ||
* @return {IOBuffer} | ||
*/ | ||
writeUint32(value) { | ||
@@ -237,4 +455,11 @@ this.ensureAvailable(4); | ||
this.offset += 4; | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* Write a 32-bit floating number at the current pointer offset | ||
* @param {number} value - The value to set | ||
* @return {IOBuffer} | ||
*/ | ||
writeFloat32(value) { | ||
@@ -244,4 +469,11 @@ this.ensureAvailable(4); | ||
this.offset += 4; | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* Write a 64-bit floating number at the current pointer offset | ||
* @param {number} value | ||
* @return {IOBuffer} | ||
*/ | ||
writeFloat64(value) { | ||
@@ -251,8 +483,20 @@ this.ensureAvailable(8); | ||
this.offset += 8; | ||
this._updateLastWrittenByte(); | ||
return this; | ||
} | ||
/** | ||
* Write the charCode of the passed string's first character to the current pointer offset | ||
* @param {string} str - The character to set | ||
* @return {IOBuffer} | ||
*/ | ||
writeChar(str) { | ||
this.writeUint8(str.charCodeAt(0)); | ||
return this.writeUint8(str.charCodeAt(0)); | ||
} | ||
/** | ||
* Write the charCodes of the passed string's characters to the current pointer offset | ||
* @param {string} str | ||
* @return {IOBuffer} | ||
*/ | ||
writeChars(str) { | ||
@@ -262,9 +506,26 @@ for (var i = 0; i < str.length; i++) { | ||
} | ||
return this; | ||
} | ||
/** | ||
* Export a Uint8Array view of the internal buffer. | ||
* The view starts at the byte offset and its length | ||
* is calculated to stop at the last written byte or the original length. | ||
* @return {Uint8Array} | ||
*/ | ||
toArray() { | ||
return new Uint8Array(this.buffer, 0, this.offset); | ||
return new Uint8Array(this.buffer, this.byteOffset, this._lastWrittenByte); | ||
} | ||
/** | ||
* Update the last written byte offset | ||
* @private | ||
*/ | ||
_updateLastWrittenByte() { | ||
if (this.offset > this._lastWrittenByte) { | ||
this._lastWrittenByte = this.offset; | ||
} | ||
} | ||
} | ||
module.exports = IOBuffer; |
{ | ||
"name": "iobuffer", | ||
"version": "2.1.0", | ||
"version": "3.0.0", | ||
"description": "Read and write binary data on ArrayBuffers", | ||
@@ -10,5 +10,7 @@ "main": "./IOBuffer.js", | ||
"scripts": { | ||
"test": "mocha --require should --reporter mocha-better-spec-reporter --recursive", | ||
"test-cov": "istanbul cover node_modules/.bin/_mocha -- --require should --reporter dot --recursive", | ||
"test-travis": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- --require should --reporter mocha-better-spec-reporter --recursive" | ||
"eslint": "eslint IOBuffer.js test", | ||
"eslint-fix": "npm run eslint -- --fix", | ||
"test": "mocha --require should --reporter mocha-better-spec-reporter --recursive; npm run eslint", | ||
"test-cov": "istanbul cover _mocha -- --require should --reporter dot --recursive", | ||
"test-travis": "istanbul cover _mocha --report lcovonly -- --require should --reporter mocha-better-spec-reporter --recursive; npm run eslint" | ||
}, | ||
@@ -26,2 +28,5 @@ "repository": { | ||
"devDependencies": { | ||
"eslint": "^3.12.1", | ||
"eslint-config-cheminfo": "^1.6.0", | ||
"eslint-plugin-no-only-tests": "^1.1.0", | ||
"istanbul": "^0.4.5", | ||
@@ -28,0 +33,0 @@ "mocha": "^3.0.2", |
@@ -5,3 +5,3 @@ # iobuffer | ||
[![build status][travis-image]][travis-url] | ||
[![Test coverage][coveralls-image]][coveralls-url] | ||
[![Test coverage][codecov-image]][codecov-url] | ||
[![npm download][download-image]][download-url] | ||
@@ -18,72 +18,25 @@ | ||
## API | ||
Complete [API documentation](http://image-js.github.io/iobuffer/) | ||
### IOBuffer | ||
## Usage exemple | ||
```js | ||
const io = new IOBuffer(); | ||
// Pointer offset is 0 | ||
io | ||
.writeChars('Hello world') // Written 11 chars, pointer offset now 11 | ||
.writeUint32(42) // Written 32-bit int (default is little-endian), pointer offset now 15 | ||
.setBigEndian() // Switch to big-endian mode | ||
.writeUint32(24) // Written another 32-bit int, but big-endian, pointer offset now 19 | ||
.mark() // bookmark current pointer offset | ||
.skip(2) // Pointer offset now 21 | ||
.writeBoolean(true) // Write 0xff, pointer offset now 22 | ||
.reset() // Go to bookmared pointer offset, pointer now 19 | ||
.setLittleEndian() // Go back to little endian mode | ||
.writeUint16(18) // Write 16-bit unsigned integer in the previously skipped 2 bytes, pointer offset now 21 | ||
.rewind() // Pointer offset now 0 | ||
.toArray() // Create a DataView of the internal Buffer that ranges over the written buffer [0-21] | ||
``` | ||
#### new IOBuffer(data) | ||
`data` can be an ArrayBuffer or any Typed Array (including Node.js' Buffer from v4). | ||
#### buffer | ||
Reference to the internal `ArrayBuffer` object. | ||
#### length | ||
Byte length of the internal `ArrayBuffer` object. | ||
#### available(byteLength = 1) | ||
Returns `true` if there are enough bytes between the current offset and the buffer's end, false otherwise. | ||
#### setBigEndian() / setLittleEndian() | ||
Set the endianess for multi-byte values (default is little endian). | ||
#### isBigEndian() / isLittleEndian() | ||
Returns a boolean indicating if current endianess matches. | ||
#### littleEndian | ||
`true` if current endianess is little endian, `false` if it is big endian. | ||
#### offset | ||
Value of the current pointer offset. | ||
#### skip(n = 1) | ||
Move the pointer forward by `n` bytes. | ||
#### seek(offset) | ||
Move the pointer at the given offset. | ||
#### mark() | ||
Store the current pointer offset. | ||
#### reset() | ||
Move the pointer back to the last offset stored by `mark`. | ||
#### rewind() | ||
Move the pointer back to offset `0`. | ||
#### Read methods | ||
Each method returns the value and moves the pointer forward by the number of read bytes. | ||
* readBoolean | ||
* readInt8 | ||
* readUint8 / readByte / readBytes(n) | ||
* readInt16 | ||
* readUint16 | ||
* readInt32 | ||
* readUint32 | ||
* readFloat32 | ||
* readFloat64 | ||
* readChar / readChars(n) | ||
## License | ||
@@ -97,5 +50,5 @@ | ||
[travis-url]: https://travis-ci.org/image-js/iobuffer | ||
[coveralls-image]: https://img.shields.io/coveralls/image-js/iobuffer.svg?style=flat-square | ||
[coveralls-url]: https://coveralls.io/github/image-js/iobuffer | ||
[codecov-image]: https://img.shields.io/codecov/c/image-js/iobuffer.svg?style=flat-square | ||
[codecov-url]: https://codecov.io/gh/image-js/iobuffer | ||
[download-image]: https://img.shields.io/npm/dm/iobuffer.svg?style=flat-square | ||
[download-url]: https://www.npmjs.com/package/iobuffer |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19683
5
460
7
52