Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize ArrayBuffer

If I want to create an arraybuffer, I write: var buff = new ArrayBuffer(size)

But how is it possible to resize an existing buffer? I mean, adding some more bytes at the end of the buffer.

like image 310
don kaka Avatar asked Sep 03 '13 20:09

don kaka


People also ask

Is ArrayBuffer a binary?

The ArrayBuffer is a data type that is used to represent a generic, fixed-length binary data buffer.

What is ArrayBuffer in JavaScript?

The ArrayBuffer object is used to represent a generic, fixed-length raw binary data buffer. It is an array of bytes, often referred to in other languages as a "byte array".

What is ArrayBuffer in typescript?

Interface ArrayBufferRepresents a raw buffer of binary data, which is used to store data for the different typed arrays. ArrayBuffers cannot be read from or written to directly, but can be passed to a typed array or DataView Object to interpret the raw buffer as needed.

What is ArrayBuffer and blob?

An ArrayBuffer is in the memory, available for manipulation. A Blob can be on disk, in cache memory, and other places not readily available. But the data from a Blob can be copied into an ArrayBuffer.


2 Answers

No set on the ArrayBuffer itself. There is set on the TypedArray though. Use like this:

var oldBuffer = new ArrayBuffer(20);

var newBuffer = new ArrayBuffer(40);
new Uint8Array(newBuffer).set(oldBuffer);
like image 126
user7090288 Avatar answered Sep 26 '22 05:09

user7090288


The way to do that would be ArrayBuffer.transfer(oldBuffer, newByteLength), like so:

var buffA = new ArrayBuffer(30);
var buffB = ArrayBuffer.transfer(buffA, 40);

// buffA is now an empty array buffer (`buffA.byteLength === 0`)
// whereas buffB is a new buffer that starts with a's contents
// and ends with 10 bytes that are 0s.

// Much faster than manually copying. You could even just do:

var buffA = new ArrayBuffer(30);
buffA = ArrayBuffer.transfer(buffA, 40);

// Or as a prototype method

ArrayBuffer.prototype.resize = function(newByteLength) {
    return ArrayBuffer.transfer(this, newByteLength);
}

var buffA = new ArrayBuffer(30);
buffA = buffA.resize(40);

However (as of October 2017) there is 0% browser support (not even Node.js support) and is not even drafted yet.


Until this is available, you can use the polyfill given on the page, which copies 8 bytes at a time, so is relatively quick for large arrays (Though it does not empty the given array, which is impossible to do).

Here is a modified version using TypeArray.prototype.set instead of for loops:

if (!ArrayBuffer.transfer) {
  ArrayBuffer.transfer = function(oldBuffer, newByteLength) {
    var srcBuffer = Object(oldBuffer);
    var destBuffer = new ArrayBuffer(newByteLength);
    if (!(srcBuffer instanceof ArrayBuffer) || !(destBuffer instanceof ArrayBuffer)) {
      throw new TypeError('Source and destination must be ArrayBuffer instances');
    }
    var copylen = Math.min(srcBuffer.byteLength, destBuffer.byteLength);

    /* Copy 8 bytes at a time */
    var length = Math.trunc(copylen / 64);
    (new Float64Array(destBuffer, 0, length))
      .set(new Float64Array(srcBuffer, 0, length));

    /* Copy the remaining 0 to 7 bytes, 1 byte at a time */
    var offset = length * 64;
    length = copylen - offset;
    (new Uint8Array(srcBuffer, offset, length))
      .set(new Uint8Array(destBuffer, offset, length));

    return destBuffer;
  };
}

[EDIT]

alternate version of the above that doesn't use ArrayBuffer namespace, and takes a slightly different approach

          function arrayBufferTransfer(oldBuffer, newByteLength) {
             const 
             srcArray  = new Uint8Array(oldBuffer),
             destArray = new Uint8Array(newByteLength),
             copylen = Math.min(srcArray.buffer.byteLength, destArray.buffer.byteLength),
             floatArrayLength   = Math.trunc(copylen / 8),
             floatArraySource   = new Float64Array(srcArray.buffer,0,floatArrayLength),
             floarArrayDest     = new Float64Array(destArray.buffer,0,floatArrayLength);
             
             floarArrayDest.set(floatArraySource);
                 
             let bytesCopied = floatArrayLength * 8;
             
         
             // slowpoke copy up to 7 bytes.
             while (bytesCopied < copylen ) {
                 destArray[bytesCopied]=srcArray[bytesCopied];
                 bytesCopied++;
             }
             
           
             return destArray.buffer;
         }
like image 14
Artyer Avatar answered Sep 28 '22 05:09

Artyer