Skip to content

Cpp OTF User Guide

Todd L. Montgomery edited this page Jan 7, 2014 · 10 revisions

Some applications, such as network sniffers, need to process messages dynamically and thus have to use the Intermediate Representation to decode the messages on-the-fly (OTF). An example of using the OTF API can be found here.

The C++ OTF decoder follows the design principles of the generated codec stubs.

Note: Due to the dynamic nature of OTF decoding, the stubs generated by the SBE compiler will yield greater relative performance.

Introduction

The C++ OTF decoder for SBE is concerned with being able to take a piece of data and a schema and being able to decode it, well, on-the-fly. The decoder uses a reactive, Rx, style API to accomplish this. Applications subclass callback interfaces, such as OnNext, OnError, and OnComplete to be notified of decoding actions. Listener is a decoding engine object. It is configured with the data to decode as well as the schema. The schema is represented in a "compiled" form called Intermediate Representation, or IR.

Listener - Encapsulation of a Decoding Engine

Instances of this class may be reused for different buffers as well as different Ir. The methods use a fluent style for composition.

The basic usage pattern is:

  • Instantiate a Listener
  • Set the Ir to use for the decoding that describes the data format
  • Pass in a pointer to the start of the data along with the length of the data in bytes
  • Subscribe callbacks for Field, Group, Error, and OnCompleted events. When called, Listener::subscribe initiates the decoding of the message. Thus all callbacks come from the calling thread.

This is demonstrated in the example below.

 Listener listener();                   // instantiate a decoder
 Ir ir(irBuffer, irLen);                // create an Ir object for the format based on Ir in buffer
 listener.resetForDecode(buffer, len)   // get ready to decode data located at buffer for len bytes
         .ir(ir)                        // pass in the Ir to use
         .subscribe(...);               // subscribe callbacks and initiate decoding

A more advanced usage pattern is when a header is used to dispatch to a set of different formats for the data. This is accomplished using the Listener::dispatchMessageByHeader method. An example is below.

 Listener listener();
 Ir headerIr(headerIrBuffer, headerIrLen);                   // the Ir for the header
 listener.resetForDecode(buffer, len)                        // get ready to decode data at buffer for len bytes
         .dispatchByMessageHeader(headerIr,                  // the Ir of the header
                                  irCallback)                // the callback called for dispatch choices
         .subscribe(...);

Decoding Multiple Messages in a Buffer