The ByteArray Intrinsic Class

Most TADS programs work with the high-level types that TADS provides – integers, strings, lists, objects, and so on.  In some cases, though, it's necessary to manipulate the raw bytes that form the basic units of storage on modern computers.  The ByteArray class provides a structured way of working directly with bytes.

 

A ByteArray looks superficially similar to a Vector object, in that you can access the individual byte elements of a ByteArray using the square bracket indexing operator:

 

  local arr = new ByteArray(100);
  arr[5] = 12;

 

Note, though, that the elements of a ByteArray can only store byte values, which are represented as integers in the range 0 to 255.

Creating a ByteArray

You create a ByteArray object using the new operator.  You must pass to the constructor the number of bytes you want to allocate for the new object; this can be any value from 1 to approximately 2 billion.  For example, to create a byte array with 1,024 elements, you would write this:

 

  local arr = new ByteArray(1024);

 

The size of a ByteArray is fixed at creation; the size cannot change after the object is created.

 

You can also create a ByteArray as a copy of another byte array or a portion of another byte array:

 

  arr = new ByteArray(otherArray, startIndex, len);

 

The startIndex and len parameters are optional; if they're missing, the new byte array will simply be a complete copy of the existing byte array.  If startIndex and len are provided, the new array will be a copy of the region of the other byte array starting at index startIndex and continuing for len bytes.  If startIndex is specified but len is missing, the new array will consist of all of the bytes from the original starting with startIndex and continuing to the end of the original array.

Reference Semantics

Like regular Array objects, a ByteArray has reference semantics: when you change a value in a byte array, any other variables that refer to the same ByteArray will refer to the modified version of the array.

Reading and Writing Raw Files

One of the tasks for which ByteArray objects are uniquely suited is working with files stored in a format defined by another application.  Using ByteArray objects, you can work directly with the exact bytes stored in an external file, allowing you to process data in arbitrary binary formats.

 

To read or write a file using ByteArray objects, you must open the file in "raw" mode.  Once a file is opened in raw mode, you can use the fileRead() and fileWrite() methods to read bytes from the file into a ByteArray and to write bytes from a ByteArray into the file.  Refer to the "tads-io" intrinsic function set for information on the file input/output functions.

ByteArray Methods

copyFrom(sourceArray, sourceStartIndex, destStartIndex, length) – copies bytes from sourceArray, which must be another ByteArray object.  Copies bytes starting with the byte in sourceArray indexed by sourceStartIndex, and continuing for length bytes; stores the bytes in this array starting at the byte indexed by destStartIndex.

 

This routine is safe to use even if sourceArray is the same as the target object, even if the ranges overlap.  When copying bytes between overlapping regions of the same array, this routine is careful to move the bytes without overwriting any source bytes before they've been moved.

 

fillValue(val, startIndex?, length?) – stores the value val in each element of the array, starting at index startIndex and filling the next length bytes.  If startIndex and length are missing, val is stored in every element of the array.  If startIndex is given but length is missing, val is stored in every element from startIndex to the end of the array.  The value val must be an integer in the range 0 to 255.

 

length() – returns the number of bytes in the ByteArray.  This is the same as the size specified when the object was created.

 

mapToString(charset, startIndex?, length?) – maps the bytes in the array to a Unicode string, interpreting the bytes as belonging to the character set given by charset, which must be an object of class CharacterSet.  Returns a string with the result of the character mapping.  Only the bytes starting at index startIndex and running for length bytes are included in the mapping.  If startIndex and length are missing, all of the bytes in the array are mapped.  If startIndex is given but length is missing, the bytes from startIndex to the end of the array are included in the mapping.

 

The character set given by charset must be known.  If the character set is not known, an UnknownCharSetException is thrown.  You can determine if the character set is known using the isMappingKnown() method of charset.

 

subarray(startIndex, length?) – returns a new ByteArray consisting of the region of this array starting with the byte indexed by startingIndex of the number of bytes given by length.  If length is not supplied, the new ByteArray consists of all of the bytes from startingIndex to the last byte of this array.