The decoder object is the first argument passed to all on_new_decoder and on_data, on_missing_data, and on_exit callbacks as shown:

  • function on_new_decoder(dec) {}

    • This is called whenever a decoder is initialised

  • function on_data(dec) {}

    • This is called whenver data is received from a lower layer in the stack - try to spend as little time in this callback as possible as it will hold onto data in the capture device until released.

  • function on_missing_data(dec) {}

    • This is called to inform the application that dataloss has happened. In some situations, the decoder may choose to flush all cache and start as if it was just initialised again.

  • function on_exit(dec) {}

    • This is called whenever the decoder is shutting down. Useful for calculating summary roll-up statistics when using SDK in retro-analysis.

The decoder object should only be accessed from these callbacks.

dec.buffer attribute (of type decoder.BufferChain)

Objects of this type cannot be instantiated by the user but may be accessed as a member of the decoder object as shown:

function on_data(dec) {
  console.log(dec.buffer.size()) // log the number of bytes contained in the buffer
}

The buffer object provides access to the underlying UDP or TCP/IP data stream as discussed here.

There are two versions of the script decoder, "script_v8_cut" which does not provide access to the underling data stream and "script_v8" which makes the buffer object available. "script_v8_cut" is designed to be used in scenarios where only algorithmic Datafield translations are needed.

BufferChain.advance(offset : Number) : Void

The buffer object stores a pointer to the current byte of interest. In the documents, it is called the "current pointer". Nearly all operations that act on a part of the Buffer use this pointer as their data location (or as a basis of calculating the data location via offsets). The "advance" method is used to increment the current pointer by offset. Note that this method does not alter memory directly but deallocates it in chunks, therefore it is efficient to call this method as much as desired.

BufferChain.size() : Number

Returns a JavaScript number indicating how much data is left beyond the "current pointer" in the BufferChain.

function on_data(dec) {
  var initialSize = dec.buffer.size()
  if (initialSize > 2) {
    dec.buffer.advance(2)
    var isTrue = (initialSize == dec.buffer.size() + 2)
  }
}

BufferChain.isEmpty() : Number

Returns true if and only if the buffer is empty. This is equivalent to but slightly more efficient to call than "dec.buffer.size() == 0".

BufferChain.sizeGreaterThan(value : Number) : Boolean

Equivalent to "dec.buffer.size() > value" but slightly more efficient.

BufferChain.sizeGreaterThanOrEqualTo(value : Number) : Boolean

Equivalent to "dec.buffer.size() >= value" but slightly more efficient.

BufferChain.sizeLessThan(value : Number) : Boolean

Equivalent to "dec.buffer.size() < value" but slightly more efficient.

BufferChain.sizeLessThanOrEqualTo(value : Number) : Boolean

Equivalent to "dec.buffer.size() <= value" but slightly more efficient.

BufferChain.substring(offset : Number, lastOffset : Number) : String

This method creates a JavaScript string from a portion of the buffer denoted by offset and lastOffset. The first byte from the buffer that is placed in the string comes from the current pointer with the offset added and every byte up to but not including lastOffset are returned.

JavaScript strings store each character as unicode-16 so not all data representable by a decoder.BufferChain can be stored in a JavaScript string. Please be aware of your data when calling this method.

function on_data(dec) {
  // dec.buffer currently stores [ 'm', 'e', 'h', 'e', 'l', 'l', 'o', 'm', 'e' ]
  var str = dec.buffer.substring(2, 7)
  var isTrue = (str == "hello")
}

BufferChain.toString() : String

This method is equivalent to buffer.substring(0, buffer.size()) but slightly more efficient.

BufferChain.skipToAndConsumeByte(byte : Number) : Boolean

This method searches for the byte represented by the number byte in the buffer. If the byte is found then the current pointer is set to point 1 byte past it otherwise the entire Buffer is emptied.

Note: BufferChains take numbers instead of JavaScript characters to represent a byte as:

  • JavaScript string characters may only store bytes representable in unicode 16.

  • There is no "char" type in JavaScript so it is much more efficient to pass a number rather than a string of size 1.

The following example demonstrates how to convert a JavaScript character into a byte which can make this method much easier to use:

var byteCodeOfE = 'e'.charCodeAt(0)
 
function on_data(dec) {
  // dec.buffer currently stores [ 'm', 'e', 'h', 'e', 'l', 'l', 'o', 'm', 'e' ]
  dec.buffer.skipToAndConsumeByte(byteCodeOfE)
  var str = dec.buffer.substring(0, 5)
  var isTrue = (str == "hello")
}

BufferChain.indexOfByte(byte : Number) : Number

Return the next occurrence of byte in the BufferChain starting from the current pointer. If the byte is not found then "buffer.length()" is returned.

function on_data(dec) {
  // dec.buffer currently stores [ 'm', 'e', 'h', 'e', 'l', 'l', 'o', 'm', 'e' ]
  var offset = dec.buffer.indexOfByte('e')
  if (dec.buffer.sizeGreaterThan(offset)) {
    console.log("found 'e' at " + offset)
    var isTrue = (offset == 1)
  }
}

BufferChain.indexOfByteFrom(byte : Number, offset : Number) : Number

This method operates the same as BufferChain.indexOfByte but looks for the first occurrence of byte from offset bytes after the current pointer.

function on_data(dec) {
  // dec.buffer currently stores [ 'm', 'e', 'h', 'e', 'l', 'l', 'o', 'm', 'e' ]
  var offset = dec.buffer.indexOfByteFrom('e', 2)
  if (dec.buffer.sizeGreaterThan(offset)) {
    console.log("found 'e' at " + offset)
    var isTrue = (offset == 3)
  }
}

BufferChain.indexOfString(value : String) : Number

Returns the offset that the string value next appears in the buffer, or the size of the buffer if the string is not found.

function on_data(dec) {
  var idx = dec.buffer.indexOfString("hello")
  if (idx !== dec.buffer.size()) {
    // ...
  }
}

BufferChain.reset() : Void

This methods completely empties the buffer and reclaims all dynamically allocated memory associated with it.

function on_data(dec) {
  dec.buffer.reset()
  var isTrue = dec.buffer.isEmpty()
}

BufferChain.consumeUInt8() : Number

Return the byte at the head of the BufferChain and advance the current pointer by a single byte.

BufferChain.consumeInt8() : Number

Return the byte at the head of the BufferChain but consider it as a signed byte represented by two's compliment encoding; then advance the current pointer by a single byte

BufferChain.consumeUInt16() : Number

Convert the two bytes at the current buffer pointer into unsigned 16-bit integer using network byte order and advance the current pointer by 2 bytes.

function on_data(dec) {
  // dec.buffer currently stores [ 0, 6 ]
  var isTrue   = (dec.buffer.consumeUInt16() == 6)
  var alsoTrue = dec.buffer.isEmpty()
}

BufferChain.consumeUInt16LE() : Number

This method is identical to BufferChain.consumeUInt16 but decoders the 16-bit integer using little-endian byte order.

function on_data(dec) {
  // dec.buffer currently stores [  6, 0 ]
  var isTrue   = (dec.buffer.consumeUInt16() == 6)
  var alsoTrue = dec.buffer.isEmpty()
}

BufferChain.consumeInt16() : Number

Identical to BufferChain.consumeUInt16 but consume a signed 16-bit (2 byte) integer.

BufferChain.consumeInt16LE() : Number

Identical to BufferChain.consumeUInt16LE but consume a signed 16-bit (2 byte) integer.

BufferChain.consumeUInt32() : Number

Identical to BufferChain.consumeUInt16 but consume an unsigned 32-bit (4 byte) integer.

BufferChain.consumeUInt32LE() : Number

Identical to BufferChain.consumeUInt16LE but consume an unsigned 32-bit (4 byte) integer.

BufferChain.consumeInt32() : Number

Identical to BufferChain.consumeInt16 but consume a signed 32-bit (4 byte) integer.

BufferChain.consumeInt32LE() : Number

Identical to BufferChain.consumeUInt16LE but decode a signed 32-bit (4 byte) integer.

BufferChain.decodeUInt8(offset : Number) : Number

Return the byte at the given offset from the current pointer of the BufferChain.

BufferChain.decodeInt8(offset : Number) : Number

Return the byte at the given offset from the current pointer of the BufferChain considering it as a signed byte encoded with two's compliment representation.

BufferChain.decodeUInt16(offset : Number) : Number

Identical to BufferChain.consumeUInt16 but:

  • Do not advance the buffer pointer.

  • Decode the integer starting at offset bytes past the current pointer.

BufferChain.decodeUInt16LE(offset : Number) : Number

Identical to BufferChain.decodeUInt16 but decode the number using little-endian byte order:

BufferChain.decodeInt16(offset : Number) : Number

Identical to BufferChain.decodeUInt16 but decode a signed 16-bit (2 byte) integer.

BufferChain.decodeInt16LE(offset : Number) : Number

Identical to BufferChain.decodeUInt16LE but decode a signed 16-bit (2 byte) integer.

BufferChain.decodeUInt32(offset : Number) : Number

Identical to BufferChain.decodeUInt16 but decode an unsigned 32-bit (4 byte) integer.

BufferChain.decodeUInt32LE(offset : Number) : Number

Identical to BufferChain.decodeUInt16LE but decode an unsigned 32-bit (4 byte) integer.

BufferChain.decodeInt32(offset : Number) : Number

Identical to BufferChain.decodeInt16 but decode a signed 32-bit (4 byte) integer.

BufferChain.decodeInt32LE(offset : Number) : Number

Identical to BufferChain.decodeUInt16LE but decode a signed 32-bit (4 byte) integer.

dec.nextDecoder() : Void

This method can result in one of two outcomes:

  • If there is another protocol after the script decoder Protocol in the train, then the next decoder layer is called.

  • If there is no Protocol in the stack following the current script decoder, then the Datafields and Statistics are made available to Collectors which are then triggered.

When the Collectors are triggered:

  • All Datafields created by the script are reset to their default values.

  • All "resettable" datafields are reset to their initials values passed via the constructors.

This method may only be called from the on_data callback.

var dfMarketId  = new decoder.DatafieldUInt("script_v8.market_id")
 
function on_data(dec) {
  dfMarketId.set(123)
  dec.nextDecoder()
  // dfMarketId is now available to the next layer or collector with a value of 123
}

dec.nextDecoder(value : String) : Void

As above but pass the data in the given JavaScript string as the input stream of the next decoder.

function on_data(dec) {
  dec.nextDecoder("important")
  // pass "important" to the input stream of the next decoder layer.
  // i.e. if the next layer is also a script decoder than it's dec.buffer
  // object would hold the string "important".
}

dec.nextDecoder(df : decoder.Datafield) : Void

As above but pass the binary data in the given datafield as the input stream of the next decoder (most useful for decoder.DatafieldBinary or decoder.DatafieldString)

var dfForward = decoder.protocol.getDatafield('df.binary_datafield')
 
function on_data(dec) {
  if (dfForward.isSet()) {
    dec.nextDecoder(dfForward)
  }
  dec.buffer.reset()
}

dec.nextDecoder(offset: Number, length : Number) : Void

This method is not available from script_v8_cut.

Pass the length bytes from offset bytes passed the current buffer pointer to the next protocol layer.

function on_data(dec) {
  // dec.buffer contains the string "ilovetsa"
  dec.nextDecoder(1, 4) // passes "love" to the next decoder
}

dec.nextDecoder(length : Number) : Void

This method is not available from script_v8_cut.

Equivalent to dec.nextDecoder(0, length).