JavaScript Data Structures - Typed Arrays II
Written by Ian Elliot   
Thursday, 23 January 2020
Article Index
JavaScript Data Structures - Typed Arrays II
Byte Order - The Endian Problem

JavaScript has typed arrays that let you work easily with arrays of data stored an ArrayBuffer. What do you do if the data isn't in the form of an array but a patchwork of data types, i.e. a structure? The answer is the DataView, but what about endianism? For the complete answer, read on.  

 


JavaScript Data Structures 

Cover

Contents

  1. The Associative Array
  2. The String Object
  3. The Array object
  4. Speed dating - the art of the JavaScript Date object
  5. Doing JavaScript Date Calculations
  6. A Time Interval Object
  7. Collection Object
  8. Stacks, Queue & Deque
  9. The Linked List
  10. A Lisp-like list
  11. The Binary Tree
  12. Bit manipulation
  13. Typed Arrays I
  14. Typed Arrays II
  15. Master JavaScript Regular Expressions
    * First Draft

In the first part of Typed Arrays we looked at the basics of creating and using typed arrays. In this part we are examining some slightly more advanced ideas, in particular the idea of converting binary data into structures or records and how to deal with the irritating problem of byte order. You are expected to know how ArrayBuffer and typed arrays work so check out Part 1 if you are in any doubt. 

Structures and Arrays

First some data basics. The array and the structure, also called a struct or a record are the most basic of all data structures but the differences between a structure and an array are subtle.

In an array every element is of the same type but in a structure each element can be a different type.

This is a basic definition but it isn't always sufficient because, for example, a JavaScript Array can store different data types in each of its elements but this is more because JavaScript is weakly typed. In weakly typed languages saying that elements of a structure are of different types isn't telling very much. 

Typed arrays are a much better example of a traditional array - every element is of a specified type - byte or unsigned integer or whatever.  In this sense the JavaScript typed array is much more like a traditional array than the Array object. 

The key idea is that an array consists of elements that can be treated in the same way i.e. if you can do something to a[23] you can do it to a[13] or any element of the array - they are functionally the same. In a structure the elements can be different and you certainly can't rely on the idea of processing them in the same way. 

This is the reason that arrays are accessed using an index e.g. a[10], a[11] and so on and a structure is accessed using a field or property e.g. s.address, s.telephone etc. The index means you can write a loop that steps though each element and performs the same action. A loop should have no value for a structure but of course JavaScript and many other languages do allow you to write a for each loop which can process a structure sequentially.

Binary Representations

In many cases binary data is just the representation of an array with the same data type repeating over and over again. For example an image file could be just an array of pixel data with color value following color value. This case is handled well by the typed array. 

However even data that is mainly in this format often has a header which contains a variety of different data types providing different information - i.e. it starts with a structure.

For example most, if not all, graphics files have a header that tells you the size of the image, the resolution, the color space and so on. By the very varied nature of the data that you find in headers different data types are generally used. This makes the header a structure rather than an array. 

The problem that we are trying to solve is:

suppose you have a binary buffer, i.e. an ArrayBuffer, of bytes and the first two bytes gives you the number of elements in total and the next byte gives the number of rows in an image. At the moment you would have to set up two views to read the data in a simple and natural manner - one Int16 array to read the first element and one int8 array to read the third byte. 

If this was repeated with lots of arbitrary data types packed one after another then things are going to get out of hand very quickly - we need another solution. Typed arrays are for situations when all of the data in the binary buffer is of the same type. 

Banner

DataView

The solution to accessing different data types in the same ArrayBuffer is the DataView object.  

The DataView object is just another view that can be associated with an ArrayBuffer. You can associate it either with the complete buffer or any portion.  

For example:

var datav=new DataView(buffer);

associates the DataView with the complete buffer. You can use the optional offset and length parameters to pick out a sub-buffer if you want to.

For example:

var datav=new DataView(buffer,99,10)

associates the view with the buffer starting at byte 99 and finishing 10 bytes further on. Notice that the units are bytes because no single data type is associate with a DataView. 

Ok once you have the DataView object how do you use it to get the various parts of the buffer? 

The answer is that there are a set of get and set methods that will retrieve or store data of various types.

The location in the buffer is specified by an offset.  

There is a get/set method for each of

  • Int8 (1 byte),
  • Uint8 (1 byte),
  • Int16 (2 bytes),  
  • Uint16 (2 bytes),
  • Int32 (4 bytes),
  • Uint32 (4 bytes),
  • Float32 (4 bytes)
    and
  • Float64 (8 byes).

Each of the methods works in roughly the same way. For example:

var ubyte=datav.getUint8(9);

retrieves an unsigned byte from the buffer at the 10th byte (remember numbering starts from zero).  Similarly to put a single unsigned byte back in the array you would use

datav.setUint8(0xFF,9);

which stores 255 in the tenth byte of the ArrayBuffer.

You can see that by using different gets and sets you can read the byte as a patchwork quilt of different data types from the same ArrayBuffer.



Last Updated ( Thursday, 23 January 2020 )