Encoding FIX Messages
To encode a FIX message into a SBE stream, the OnixS::FIX::SBE::Encoder class is used.
std::string xmlSbeTemplate = readTextFile("SbeTemplate.xml");
const int SbeTemplateID = 10;
const int SbeSchemaVersion = encoder.schemaVersion();
const size_t BufferSize = 1024;
unsigned char sbeStreamChunk[BufferSize];
size_t rootBlockLength = 0;
size_t chunkSize = encoder.encode(sourceFixMessage, SbeTemplateID, SbeSchemaVersion, sbeStreamChunk, BufferSize, &rootBlockLength);
Decoding SBE binary chunks
To decode a part of a SBE stream back into a FIX message, the OnixS::FIX::SBE::Decoder class is used.
Please note, that it is needed to obtain three separate values for:
- SBE schema version;
- SBE template identifier;
- Size of the root block of the message to decode.
Usually, the data arranged in the message header. Decoding of the header is not covered by the SBE decoder, and the header has to be decoded by separate user code.
void sbeDecoding()
{
std::ifstream templatesStream("templates/SbeTemplates.xml");
assert(templatesStream);
const std::string XmlSbeTemplates((std::istreambuf_iterator<char>(templatesStream)), std::istreambuf_iterator<char>());
assert(!XmlSbeTemplates.empty());
std::ifstream dataStream("data/sbeChunk.bin", std::ios_base::in | std::ios_base::binary);
assert(dataStream);
const std::string binaryChunk((std::istreambuf_iterator<char>(dataStream)), std::istreambuf_iterator<char>());
assert(!binaryChunk.empty());
const int TemplateId = 10;
const int Version = schemaVersion();
const size_t RootBlockLength = 28;
const Message& message = decoder.decode(TemplateId, Version, RootBlockLength, reinterpret_cast<const unsigned char*>(binaryChunk.data()), binaryChunk.size());
std::clog << "Decoded: " << message << std::endl;
}
Decoding multiple FIX Messages from the same binary chunk.
To decode multiple FIX Messages from the same binary chunk the OnixS::FIX::SBE::Decoder::tryDecode method is used.
- Note
- Exact code of header decoding can vary in dependency on the specification of the protocol used.
struct SbeMessageHeader
{
int templateId;
int schemaVersion;
unsigned rootBlockSize;
};
void sbeDecodeMultipleMessagesFromSameBinaryChunk()
{
std::ifstream templatesStream("templates/SbeTemplates.xml");
assert(templatesStream);
const std::string XmlSbeTemplates((std::istreambuf_iterator<char>(templatesStream)), std::istreambuf_iterator<char>());
assert(!XmlSbeTemplates.empty());
std::ifstream dataStream("data/sbeChunk.bin", std::ios_base::in | std::ios_base::binary);
assert(dataStream);
const std::string BinaryChunk((std::istreambuf_iterator<char>(dataStream)), std::istreambuf_iterator<char>());
assert(!BinaryChunk.empty());
const SbeMessageHeader *header = reinterpret_cast<const SbeMessageHeader *>(&BinaryChunk[0]);
size_t offset = sizeof(SbeMessageHeader);
size_t count = BinaryChunk.length() - sizeof(SbeMessageHeader);
size_t numberOfDecodedBytes = 0;
while (decoder.tryDecode(header->templateId, header->schemaVersion, header->rootBlockSize, reinterpret_cast<const unsigned char*>(BinaryChunk.data()), offset, count, &message, &numberOfDecodedBytes))
{
std::clog << "Decoded " << numberOfDecodedBytes << " bytes: " << message << std::endl;
offset += numberOfDecodedBytes;
count -= numberOfDecodedBytes;
if (count <= sizeof(SbeMessageHeader))
break;
count -= sizeof(SbeMessageHeader);
header = reinterpret_cast<const SbeMessageHeader *>(&BinaryChunk[offset]);
offset += sizeof(SbeMessageHeader);
}
}