You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
4.8 KiB

// Light implementation of binary buffer with helpers for easy access.
//
'use strict';
var TYPED_OK = (typeof Uint8Array !== 'undefined');
function createArray(size) {
return TYPED_OK ? new Uint8Array(size) : Array(size);
}
function MicroBuffer(buffer, start, length) {
var isInherited = buffer instanceof MicroBuffer;
this.buffer = isInherited ?
buffer.buffer
:
(typeof buffer === 'number' ? createArray(buffer) : buffer);
this.start = (start || 0) + (isInherited ? buffer.start : 0);
this.length = length || (this.buffer.length - this.start);
this.offset = 0;
this.isTyped = !Array.isArray(this.buffer);
}
MicroBuffer.prototype.getUint8 = function (pos) {
return this.buffer[pos + this.start];
};
MicroBuffer.prototype.getUint16 = function (pos, littleEndian) {
var val;
if (littleEndian) {
throw new Error('not implemented');
} else {
val = this.buffer[pos + 1 + this.start];
val += this.buffer[pos + this.start] << 8 >>> 0;
}
return val;
};
MicroBuffer.prototype.getUint32 = function (pos, littleEndian) {
var val;
if (littleEndian) {
throw new Error('not implemented');
} else {
val = this.buffer[pos + 1 + this.start] << 16;
val |= this.buffer[pos + 2 + this.start] << 8;
val |= this.buffer[pos + 3 + this.start];
val += this.buffer[pos + this.start] << 24 >>> 0;
}
return val;
};
MicroBuffer.prototype.setUint8 = function (pos, value) {
this.buffer[pos + this.start] = value & 0xFF;
};
MicroBuffer.prototype.setUint16 = function (pos, value, littleEndian) {
var offset = pos + this.start;
var buf = this.buffer;
if (littleEndian) {
buf[offset] = value & 0xFF;
buf[offset + 1] = (value >>> 8) & 0xFF;
} else {
buf[offset] = (value >>> 8) & 0xFF;
buf[offset + 1] = value & 0xFF;
}
};
MicroBuffer.prototype.setUint32 = function (pos, value, littleEndian) {
var offset = pos + this.start;
var buf = this.buffer;
if (littleEndian) {
buf[offset] = value & 0xFF;
buf[offset + 1] = (value >>> 8) & 0xFF;
buf[offset + 2] = (value >>> 16) & 0xFF;
buf[offset + 3] = (value >>> 24) & 0xFF;
} else {
buf[offset] = (value >>> 24) & 0xFF;
buf[offset + 1] = (value >>> 16) & 0xFF;
buf[offset + 2] = (value >>> 8) & 0xFF;
buf[offset + 3] = value & 0xFF;
}
};
MicroBuffer.prototype.writeUint8 = function (value) {
this.buffer[this.offset + this.start] = value & 0xFF;
this.offset++;
};
MicroBuffer.prototype.writeInt8 = function (value) {
this.setUint8(this.offset, (value < 0) ? 0xFF + value + 1 : value);
this.offset++;
};
MicroBuffer.prototype.writeUint16 = function (value, littleEndian) {
this.setUint16(this.offset, value, littleEndian);
this.offset += 2;
};
MicroBuffer.prototype.writeInt16 = function (value, littleEndian) {
this.setUint16(this.offset, (value < 0) ? 0xFFFF + value + 1 : value, littleEndian);
this.offset += 2;
};
MicroBuffer.prototype.writeUint32 = function (value, littleEndian) {
this.setUint32(this.offset, value, littleEndian);
this.offset += 4;
};
MicroBuffer.prototype.writeInt32 = function (value, littleEndian) {
this.setUint32(this.offset, (value < 0) ? 0xFFFFFFFF + value + 1 : value, littleEndian);
this.offset += 4;
};
// get current position
//
MicroBuffer.prototype.tell = function () {
return this.offset;
};
// set current position
//
MicroBuffer.prototype.seek = function (pos) {
this.offset = pos;
};
MicroBuffer.prototype.fill = function (value) {
var index = this.length - 1;
while (index >= 0) {
this.buffer[index + this.start] = value;
index--;
}
};
MicroBuffer.prototype.writeUint64 = function (value) {
// we canot use bitwise operations for 64bit values because of JavaScript limitations,
// instead we should divide it to 2 Int32 numbers
// 2^32 = 4294967296
var hi = Math.floor(value / 4294967296);
var lo = value - hi * 4294967296;
this.writeUint32(hi);
this.writeUint32(lo);
};
MicroBuffer.prototype.writeBytes = function (data) {
var buffer = this.buffer;
var offset = this.offset + this.start;
if (this.isTyped) {
buffer.set(data, offset);
} else {
for (var i = 0; i < data.length; i++) {
buffer[i + offset] = data[i];
}
}
this.offset += data.length;
};
MicroBuffer.prototype.toString = function (offset, length) {
// default values if not set
offset = (offset || 0);
length = length || (this.length - offset);
// add buffer shift
var start = offset + this.start;
var end = start + length;
var string = '';
for (var i = start; i < end; i++) {
string += String.fromCharCode(this.buffer[i]);
}
return string;
};
MicroBuffer.prototype.toArray = function () {
if (this.isTyped) {
return this.buffer.subarray(this.start, this.start + this.length);
}
return this.buffer.slice(this.start, this.start + this.length);
};
module.exports = MicroBuffer;