Although OnixS::FIX::Message class is designed for high-performance duty, each concept has its bounds and bottlenecks. The serialization/deserialization operations, that are done by the OnixS::FIX::Session each time when an instance of OnixS::FIX::Message is sent/received to/from counterparty, is quite a heavy-weight operation, thus it has negative influence on a general performance.
To satisfy the needs of ultra-low latency trading, OnixS FIX Engine offers a new concept of an editable flat FIX message, exposed as the OnixS::FIX::FlatMessage class. This class provides functionality that is similar to the OnixS::FIX::Message. However, being pre-serialized, it eliminates the necessity of converting between structured memory presentation and a 'tag=value' form when the message is actually sent or received.
OnixS::FIX::FlatMessage instance can be constructed either from a 'tag=value' form or a regular OnixS::FIX::Message class instance. The following code shows the creation of a flat order (MsgType=D) from a 'tag=value' form:
Also, OnixS::FIX::FlatMessage instance can be constructed from a 'tag=value' form without session-level fields, in this case, the required session-level fields will be added during the construction:
The following code shows the creation of a flat order (MsgType=D) from the previously filled OnixS::FIX::Message instance:
Also, the OnixS::FIX::FlatMessage instance can be constructed as a blank instance or with required message header fields only. In this case, one can add all additional fields by OnixS::FIX::FlatMessage::add methods:
Once the instance of OnixS::FIX::FlatMessage class is constructed, its fields can be manipulated in a similar way, as in the case of OnixS::FIX::Message.
OnixS::FIX::FlatMessage class interface exposes two ways of accessing fields: using temporary references and using permanent keys. Temporary references are represented by OnixS::FIX::FlatFieldRef class and permanent keys are of the OnixS::FIX::FlatFieldKey type.
Whatever way is used to access a field, a temporary reference to the field must be obtained first. The OnixS::FIX::FlatMessage class exposes the OnixS::FIX::FlatMessage::find method for that purposes. If the lookup succeeds, it returns a valid reference instance for further use:
Once a reference is obtained, it can be used to update the field value:
For a continuous and non-destructive modification of a message field value, the concept of a flat field key is exposed. In contrast to a temporary field references, keys remain constant for the entire life of the particular OnixS::FIX::FlatMessage instance. Changing field values does not invalidate keys and, thus multiple fields can be updated without affecting keys. Keys are unique in bounds of a single flat message.
The following code demonstrates how a key can be obtained from a temporary reference:
Once a key is obtained, the field value can be accessed and modified, using the same way as using temporary references:
To iterate over all fields of a OnixS::FIX::FlatMessage you can use the OnixS::FIX::FlatMessage::ConstIterator class:
To simplify access to FIX groups, the OnixS::FIX::FlatGroup class is implemented. One can use the OnixS::FIX::FlatMessage::getGroup() method to get the OnixS::FIX::FlatGroup instance. After that, one can use the OnixS::FIX::FlatGroup::ConstIterator class to iterate over all group instances in the repeating group. Each group instance iterator returns the OnixS::FIX::FlatGroupInstance object, which one can use to get access to group instance fields. To access a nested repeating group, one can use the OnixS::FIX::FlatGroupInstance::getGroup() method. The following code demonstrates the access to fields of FIX group instances by iterators:
Also, the OnixS::FIX::FlatMessage class provides an additional ability to access fields with the same tag from different entries of a flat repeating group. It can be performed with the overloaded OnixS::FIX::FlatMessage::find(OnixS::FIX::Tag, const OnixS::FIX::FlatFieldRef&) const method. The second parameter indicates the OnixS::FIX::FlatFieldRef value after which the search will be performed. Accordingly, you can find all field values with the same tag and allocate keys for further access. The following code demonstrates the access to fields with the same tag:
To add a field, you can use OnixS::FIX::FlatMessage::add methods. These methods add the given tag/value pair at the end of the message instance:
To insert a field, you can use OnixS::FIX::FlatMessage::insert methods. These methods insert the given tag/value pair to the message instance. The position is specified by the posTag parameter. The OnixS::FIX::InsertMode::Enum is used to specify where the new field will be inserted - before or after the position tag:
To remove a field, use the OnixS::FIX::FlatMessage::remove(OnixS::FIX::Tag) method.
The OnixS::FIX::FlatMessage::userData() method can attach a user data pointer to the message object. This way can be used to associate some data with the given message object or pass user data with a message object through sending or receiving call stack. The user data is available in OnixS::FIX::ISessionListener, and OnixS::FIX::ISessionStorage callbacks are called for this particular message object.