229 lines
No EOL
11 KiB
C#
229 lines
No EOL
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using Bloomberg.Message.Entities;
|
|
using Bloomberg.Message.Utils;
|
|
|
|
namespace Bloomberg.Message.Reader
|
|
{
|
|
public class DataInfoReader
|
|
{
|
|
private readonly DataReader _dataReader = new DataReader();
|
|
private static log4net.ILog _log = log4net.LogManager.GetLogger(typeof(DataInfoReader));
|
|
|
|
public List<DataElement> Read(Stream currentStream, string savePath, ref bool errorDetected)
|
|
{
|
|
var dataList = new List<DataElement>();
|
|
|
|
uint lastReadMarker = ReadingForDataInfoStartMarker(dataList, currentStream, ref errorDetected);
|
|
|
|
if(lastReadMarker != MessageConstants.DataInfoStartMarker)
|
|
{
|
|
return dataList;
|
|
}
|
|
|
|
bool endOfDataList = false;
|
|
do
|
|
{
|
|
if(lastReadMarker != MessageConstants.DataStartMarker && lastReadMarker != MessageConstants.DataInfoEndMarker)
|
|
{
|
|
lastReadMarker = ReadUpToDataStartMarkerOrDataInfoEndMarker(dataList, currentStream, ref errorDetected);
|
|
}
|
|
|
|
switch (lastReadMarker)
|
|
{
|
|
case MessageConstants.DataStartMarker:
|
|
|
|
DataElement newDataElement = new DataElement();
|
|
|
|
try
|
|
{
|
|
_dataReader.Read(currentStream, savePath, ref newDataElement, ref errorDetected);
|
|
|
|
lastReadMarker = ReadUpToDataEndMarker(dataList, currentStream, ref errorDetected);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
errorDetected = true;
|
|
|
|
newDataElement.Error = $"DataInfoReader - Caught the following exception while reading: \r\n{e.Message}";
|
|
|
|
if (string.IsNullOrEmpty(newDataElement.Name))
|
|
{
|
|
newDataElement.Name = "n/a";
|
|
}
|
|
|
|
_log.Error("Error in DataInfoReader", e);
|
|
|
|
lastReadMarker = 0;
|
|
}
|
|
|
|
dataList.Add(newDataElement);
|
|
|
|
break;
|
|
|
|
case MessageConstants.DataInfoEndMarker:
|
|
//just continue
|
|
endOfDataList = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
//no marker found. end parsing
|
|
_log.Warn("DataInfoReader - Bad marker found " + MessageConstants.GetMarkerName(lastReadMarker));
|
|
endOfDataList = true;
|
|
|
|
break;
|
|
}
|
|
}
|
|
while (!endOfDataList);
|
|
|
|
return dataList;
|
|
}
|
|
|
|
private uint ReadingForDataInfoStartMarker(List<DataElement> dataList, Stream currentStream, ref bool errorDetected)
|
|
{
|
|
while (true)
|
|
{
|
|
uint foundMarker;
|
|
|
|
if (ReaderHelper.ScanForSpecificMarkerNoSeek(currentStream, out foundMarker, MessageConstants.DataInfoStartMarker))
|
|
{
|
|
return foundMarker;
|
|
}
|
|
|
|
string foundMarkerName = MessageConstants.GetMarkerName(foundMarker);
|
|
|
|
switch (foundMarker)
|
|
{
|
|
case MessageConstants.DataInfoStartMarker:
|
|
//what we wanted, just keep going but log this and add error dataelement because it wasn't the first read that returned this constant
|
|
MessageReader.LogErrorDataElement(ref errorDetected, $"Unrecognized data before marker {foundMarkerName}", dataList);
|
|
return foundMarker;
|
|
|
|
case MessageConstants.MessageEndMarker:
|
|
//just end streaming
|
|
return foundMarker;
|
|
|
|
case MessageConstants.ReportStartMarker:
|
|
case MessageConstants.ReportEndMarker:
|
|
case MessageConstants.DataInfoEndMarker:
|
|
case MessageConstants.VariableLengthStartMarker:
|
|
case MessageConstants.VariableLengthEndMarker:
|
|
case MessageConstants.DataEndMarker:
|
|
case MessageConstants.AttributeStartMarker:
|
|
case MessageConstants.AttributeEndMarker:
|
|
case MessageConstants.MessageStartMarker:
|
|
MessageReader.LogErrorDataElement(ref errorDetected, $"Unexpected marker found before DataInfoStartMarker: {foundMarkerName}", dataList);
|
|
break;
|
|
|
|
case MessageConstants.DataStartMarker:
|
|
//next best thing, we can start a data element with this just rewind the stream a bit
|
|
MessageReader.LogErrorDataElement(ref errorDetected,
|
|
$"Unexpected marker found before DataInfoStartMarker: {foundMarkerName}. Continuing with parsing the message.", dataList);
|
|
return foundMarker;
|
|
default:
|
|
MessageReader.LogErrorDataElement(ref errorDetected, "No recognizeable marker found and end of stream reached while looking for DataInfoStartMarker", dataList);
|
|
return foundMarker;
|
|
}
|
|
}
|
|
}
|
|
|
|
private uint ReadUpToDataStartMarkerOrDataInfoEndMarker(List<DataElement> dataList, Stream currentStream, ref bool errorDetected)
|
|
{
|
|
while (true)
|
|
{
|
|
uint foundMarker;
|
|
|
|
if (ReaderHelper.ScanForSpecificMarkersNoSeek(currentStream, out foundMarker, MessageConstants.DataStartMarker, MessageConstants.DataInfoEndMarker))
|
|
{
|
|
return foundMarker;
|
|
}
|
|
|
|
string foundMarkerName = MessageConstants.GetMarkerName(foundMarker);
|
|
|
|
switch (foundMarker)
|
|
{
|
|
case MessageConstants.DataStartMarker:
|
|
//what we wanted, just keep going but log this and add error dataelement because it wasn't the first read that returned this constant
|
|
MessageReader.LogErrorDataElement(ref errorDetected, $"Unrecognized data before marker {foundMarkerName}", dataList);
|
|
return foundMarker;
|
|
|
|
case MessageConstants.DataInfoEndMarker:
|
|
//the end of data info marker is found
|
|
MessageReader.LogErrorDataElement(ref errorDetected, $"Unrecognized data before marker {foundMarkerName}", dataList);
|
|
|
|
return MessageConstants.DataInfoEndMarker;
|
|
|
|
case MessageConstants.MessageEndMarker:
|
|
//stop reading
|
|
MessageReader.LogErrorDataElement(ref errorDetected, $"Unrecognized data before marker {foundMarkerName}", dataList);
|
|
return MessageConstants.MessageEndMarker;
|
|
case MessageConstants.DataInfoStartMarker:
|
|
case MessageConstants.ReportStartMarker:
|
|
case MessageConstants.ReportEndMarker:
|
|
case MessageConstants.VariableLengthStartMarker:
|
|
case MessageConstants.VariableLengthEndMarker:
|
|
case MessageConstants.DataEndMarker:
|
|
case MessageConstants.AttributeStartMarker:
|
|
case MessageConstants.AttributeEndMarker:
|
|
case MessageConstants.MessageStartMarker:
|
|
MessageReader.LogErrorDataElement(ref errorDetected,
|
|
$"Unexpected marker found before DataInfoStartMarker or DataInfoEndMarker: {foundMarkerName}", dataList);
|
|
break;
|
|
|
|
default:
|
|
MessageReader.LogErrorDataElement(ref errorDetected, "No recognizeable marker found and end of stream reached while looking for DataInfoStartMarker or DataInfoEndMarker", dataList);
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private uint ReadUpToDataEndMarker(List<DataElement> dataList, Stream currentStream, ref bool errorDetected)
|
|
{
|
|
while (true)
|
|
{
|
|
uint foundMarker;
|
|
|
|
if (ReaderHelper.ScanForSpecificMarkerNoSeek(currentStream, out foundMarker, MessageConstants.DataEndMarker))
|
|
{
|
|
return foundMarker;
|
|
}
|
|
|
|
string foundMarkerName = MessageConstants.GetMarkerName(foundMarker);
|
|
|
|
switch (foundMarker)
|
|
{
|
|
case MessageConstants.DataStartMarker:
|
|
//the DataEndMarker is missing but keep reading to parse the new DataElement. Just rewind a little so the next scan for DataStartMarker works
|
|
MessageReader.LogErrorDataElement(ref errorDetected, $"Unexpected marker found before marker DataEndMarker: {foundMarkerName}", dataList);
|
|
|
|
return foundMarker;
|
|
|
|
case MessageConstants.DataEndMarker:
|
|
//there was some data before the end of the expected DataElement serialization
|
|
MessageReader.LogErrorDataElement(ref errorDetected, $"Unexpected data before marker DataEndMarker: {foundMarkerName}", dataList);
|
|
return foundMarker;
|
|
|
|
case MessageConstants.DataInfoStartMarker:
|
|
case MessageConstants.MessageEndMarker:
|
|
case MessageConstants.ReportStartMarker:
|
|
case MessageConstants.ReportEndMarker:
|
|
case MessageConstants.VariableLengthStartMarker:
|
|
case MessageConstants.VariableLengthEndMarker:
|
|
case MessageConstants.DataInfoEndMarker:
|
|
case MessageConstants.AttributeStartMarker:
|
|
case MessageConstants.AttributeEndMarker:
|
|
case MessageConstants.MessageStartMarker:
|
|
MessageReader.LogErrorDataElement(ref errorDetected, $"Unexpected marker found before DataEndMarker: {foundMarkerName}", dataList);
|
|
break;
|
|
|
|
default:
|
|
MessageReader.LogErrorDataElement(ref errorDetected, "No recognizeable marker found or end of stream reached while looking for DataEndMarker", dataList);
|
|
return foundMarker;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |