I convert data from JavaScript variables to ArrayBuffer
and back. Think of this function:
function numberToArrayBuffer(number) {
return new Float64Array([number]).buffer;
}
And other way around:
function numberFromArrayBuffer(buffer) {
// Assuming implicitly, that the buffer is long enough
return new Float64Array(buffer, 0, 1)[0];
}
That works, but imagine you stuff more of these numbers in Blob:
var numbers = new Blob([numberToArrayBuffer(66), numberToArrayBuffer(666), numberToArrayBuffer(NaN)], {type:"binary/Float64Array"});
If you read that using file reader, you can get ArrayBuffer
again:
var fl = new FileReader();
fl.onload = function() {
console.log(Float64Array(this.result));
}
fl.readAsArrayBuffer(numbers);
And you get something like this:
Float64Array { 0=66, 1=666, 2=NaN}
But of course, there could be sequences od different types, like 2 unrestricted double
s and 4 uint32_t
. So I would like do something like this (but there is no .offset
metod):
var num1 = numberFromArrayBuffer(buffer);
// Shift by 8 bytes - if only `offset(8)` was defined
var num2 = byteFromArrayBuffer(buffer.offset(8));
Of course, I can make a "overloaded function":
function numberToArrayBuffer(number, offset) {
return new Float64Array([number], offset||0).buffer;
}
and use it like this:
var num2 = byteFromArrayBuffer(buffer, 8);
But I'd prefer an equivalent of this C++ code:
void main()
{
uint8_t* bytes = loadBytesFromSomewhere();
// Read 4 bytes and make an int
uint32_t integer = intFromBytes(bytes);
// Read 2 bytes and make a short
uint16_t short_integer = shortFromBytes(bytes+4);
delete bytes;
}
I want this because it's really annoying to put offset aspect to decoding algorithms. At the same time, I really want to be consistent and use ArrayBuffer
, which can be turned to any data type array at will.
Is there a trick? I tried this:
//Make 20 bytes
var buffer = new Uint8Array(20);
console.log("Original buffer: ",buffer.byteLength);
//Try to offset the buffer off cnt
var shiftedArray = new Uint8Array(buffer, 10, 10);
var shiftedBuffer = shiftedArray.buffer;
console.log("Shifted buffer? Length:",shiftedBuffer.byteLength);
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
Not only that it doesn't work, but also exhibits possible dangerous and confusing behavior of typed arrays created with an offset - their length can be significantly smaller than their ArrayBuffer
length.
The following may or may not exactly meet your needs, I believe it's the equivalent of what you desired in c++ (minus the delete bytes). Though, this is an old post and you may have your answer already!
As you already know, ArrayBuffers
in javascript can be accessed through a handful of different viewpoints/objects, called TypedArrays. These are objects such as Float64Array, Uint32Array, etc. There is a TypedArray object that allows you to grab data back dynamically to whatever type you would like at target byte offsets called a DataView
.
So to achieve the desired functionality you could do something like the following:
var buffer = loadByteBufferFromSomewhere();
//DataView would be the same way
var dv = new DataView(buffer);
//uint32 at index 0;
dv.getUint32(0);
//uint16 starting at byte 4
dv.getUint16(4);
//get a target byte at given indexes
dv.getUint8(0);
dv.getUint8(1);
DataView is a wrapper around the ArrayBuffer like Float64Array, Uint32Array, etc. You can also set target types at given indexes as well. I've found JavaScripture's references really helpful TypedArrays