SBE Log Decoder Sample
This sample demonstrates how to convert the
Base64 encoded \*.summary
file into a human-friendly \*.txt
file.
Source code
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using OnixS.SimpleBinaryEncoding;
using OnixS.SimpleBinaryEncoding.Templates;
using OnixS.SimpleBinaryEncoding.CodeGenerator;
namespace SbeLogDecoder
{
internal static class SbeLogDecoder
{
private static readonly string version = "1.0.0";
private static void Main(string[] args)
{
if (args.Length < 2)
{
Console.WriteLine("SBE Log Decoder, version = " + version + "\n");
Console.WriteLine("usage: [SbeMessageSchemaFile] [TargetPath|TargetDir]");
return;
}
string tplPath = args[0];
string targetPath = args[1];
try
{
var decoder = GetDecoder(tplPath);
foreach (var file in GatherFiles(targetPath))
{
Console.WriteLine(Path.GetFileName(file) + ":\n");
Decode(file, decoder);
Console.WriteLine("\n***\n");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private static IDecoder GetDecoder(string tpl)
{
TemplateLibrary.LicenseStore = "../../../../../license|../../../../license|.";
var lib = TemplateLibrary.Parse(File.ReadAllText(tpl));
var assembly = new Generator().GenerateAssembly<CmeILinkHeader>(lib, "OnixS.SimpleBinaryEncoding.Cme");
var decoder = (IDecoder)Activator.CreateInstance(assembly.GetType("OnixS.SimpleBinaryEncoding.Cme.Decoder", true));
return decoder;
}
private static List<string> GatherFiles(string path)
{
if (File.GetAttributes(path).HasFlag(FileAttributes.Directory))
return new List<string>(Directory.GetFiles(path, "*.summary"));
else
return new List<string>([path]);
}
private static void Decode(string filePtah, IDecoder decoder)
{
using var fileStream = File.OpenRead(filePtah);
using var streamReader = new StreamReader(fileStream, Encoding.UTF8, true);
{
string line;
while((line = streamReader.ReadLine()) != null)
{
const int LogLinePrefixSize = 32;
string prefix = line[0..LogLinePrefixSize];
line = line[LogLinePrefixSize..];
byte[] rawData = Convert.FromBase64String(line);
// See https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/46113078/iLink+3+Message+Header.
bool sofhDetected = rawData[3] == 0xCA && rawData[2] == 0xFE;
byte[] iLinkMessage = null;
if (sofhDetected)
{
iLinkMessage = rawData;
}
else
{
// The log record does not contain a Simple Open Framing Header(SOFH), so we need to add it before we can decode the message.
const int SofhLength = 4;
iLinkMessage = new byte[rawData.Length + SofhLength];
Array.Copy(rawData, 0, iLinkMessage, SofhLength, rawData.Length);
byte[] messageSizeBytes = BitConverter.GetBytes((ushort)iLinkMessage.Length);
// Set the `MessageSize` SOFH field.
iLinkMessage[0] = messageSizeBytes[0];
iLinkMessage[1] = messageSizeBytes[1];
}
var memPtr = new MemoryPointer(new Memory<byte>(iLinkMessage));
Console.WriteLine(prefix + decoder.Wrap(memPtr).ToString());
}
}
}
}
}