/// \brief Implementation of a high performance DDL decoder for the muon tracking stations.
///
/// This file implementes the AliMUONTrackerDDLDecoder class, which contains
-/// the core logic for decoding the payload in DDL streams comming from the muon
+/// the core logic for decoding the payload in DDL streams coming from the muon
/// spectrometer's tracking chambers in a very efficient manner.
///
/// This implementation is derived from work done by Christian Finck for the
#include "AliMUONTrackerDDLDecoderEventHandler.h"
-#include <cassert>
-#include <ostream>
-#include <Rtypes.h>
-
-
/// \ingroup raw
/// \class AliMUONTrackerDDLDecoder
/// \brief A high performance decoder class for MUON tracking DDL data.
///
/// This class implements a high performance decoder for decoding DDL payload
/// data coming from the muon spectrometers tracking chambers.
-/// It has been implemented using the event driven paradigm, which allows us
-/// to minimise the number of method calls made in the inner loops of the algorithm
-/// and minimise the memory footprint.
+/// It has been implemented using the event driven paradigm with templates,
+/// which allows us to minimise the number of method calls made in the inner
+/// loops of the algorithm and minimise the memory footprint. At least for
+/// optimised production compilations.
/// The decoder class only contains the basic decoding and error checking logic.
/// It calls methods such as OnNewBlock, OnNewBusPatch, OnData etc in
/// the event handler during the decoding to return the decoded data.
/// The event handler class is nothing more than a callback interface to deliver
/// the next chunks of decoded data.
-/// To actually do something with the data one needs to implement a custom
+/// To actually do something with the data, one needs to implement a custom
/// event handler (callback) class by inheriting from AliMUONTrackerDDLDecoderEventHandler
/// and overriding the callback methods like so:
/// \code
/// class MyCustomHandler : public AliMUONTrackerDDLDecoderEventHandler
/// {
/// public:
-/// void OnData(UInt_t data)
+/// void OnData(UInt_t data, bool parityError)
/// {
-/// // I can do something with 'data' here.
+/// // I can do something with 'data' here and check if there was
+/// // a parity error with 'parityError'.
/// }
/// };
/// \endcode
///
-/// Once the custom handler is written then the decoder is in instantiated as
-/// shown below, to use your new custom handler. And to start decoding one needs
+/// Once the custom handler is written then the decoder is instantiated as
+/// shown below, to use your new custom handler. Also to start decoding one needs
/// to call the Decode() method of the decoder.
/// \code
/// AliMUONTrackerDDLDecoder<MyCustomHandler> myDecoder;
/// \endcode
///
/// Note that this class was written as a template on purpose. To maximise the
-/// compilers chance to make optimisations and inlining code must use a template.
-/// Depending on exactly what you do inside your handler the decoder will be
-/// significantly slower if run time polymorphism was used i.e. making the class
+/// compilers chance to make optimisations and inline the code we must use a template.
+/// Depending on exactly what you do inside your handler, the decoder could be
+/// significantly slower if run time polymorphism was used, i.e. making the class
/// AliMUONTrackerDDLDecoderEventHandler abstract and using virtual methods.
///
+/// There has been a change to the data format that the real detector generates.
+/// Two trailer words are added to the end of the DDL payload which indicated
+/// the end of data. The decoder is initialised by default to automatically
+/// check for these and deal with it correctly, if they exist or not.
+/// However, if you want to override this behaviour then set the flag
+/// fAutoDetectTrailer to false with AutoDetectTrailer(false). Then if you have
+/// data with the old data format you should set fCheckForTrailer to false with
+/// CheckForTrailer(false), otherwise for real data it should be
+/// fCheckForTrailer = true. Only when fAutoDetectTrailer is true will the
+/// fCheckForTrailer flag be ignored and no warnings will be generated for an
+/// incorrect data format.
+///
/// \author Artur Szostak <artursz@iafrica.com>
template <class EventHandler>
AliMUONTrackerDDLDecoder() :
fExitOnError(true), fTryRecover(false),
fSendDataOnParityError(false), fHadError(false),
+ fAutoDetectTrailer(true), fCheckForTrailer(true),
fMaxBlocks(2), fMaxDSPs(5), fMaxBusPatches(5), fHandler()
{}
/// Returns the "try to recover from errors" flag.
/// i.e. should the decoder try to recover from errors found in the
- /// payload headers.
+ /// payload headers or trailers.
bool TryRecover() const { return fTryRecover; }
/// Sets the "try to recover from errors" flag.
/// i.e. should the decoder try to recover from errors found in the
- /// payload headers.
+ /// payload headers or trailers.
void TryRecover(bool value) { fTryRecover = value; }
/// Returns the flag indicating if the raw data words in the bus patches
/// structure within the DDL payload.
void MaxBusPatches(UInt_t n) { fMaxBusPatches = n; }
+ /// Returns the value of the auto-detect trailer flag.
+ bool AutoDetectTrailer() const { return fAutoDetectTrailer; }
+
+ /// Sets the value of the auto-detect trailer flag.
+ void AutoDetectTrailer(bool value) { fAutoDetectTrailer = value; }
+
+ /// Returns the value of the flag to check for the end of DDL trailer.
+ bool CheckForTrailer() const { return fCheckForTrailer; }
+
+ /// Sets the value of the flag to check for the end of DDL trailer.
+ void CheckForTrailer(bool value) { fCheckForTrailer = value; }
+
/// This method decodes the DDL payload contained in the buffer.
bool Decode(const void* buffer, UInt_t bufferSize);
+ /// Returns the block marker key.
+ static UInt_t BlockDataKeyWord() { return fgkBlockDataKey; }
+
+ /// Returns the DSP marker key.
+ static UInt_t DspDataKeyWord() { return fgkDSPDataKey; }
+
+ /// Returns the bus patch marker key.
+ static UInt_t BusPatchDataKeyWord() { return fgkBusPatchDataKey; }
+
+ /// Returns the expected padding word value.
+ static UInt_t PaddingWord() { return fgkPaddingWord; }
+
+ /// Returns the expected end of DDL marker.
+ static UInt_t EndOfDDLWord() { return fgkEndOfDDL; }
+
private:
bool fExitOnError; ///< Indicates if we should exit on the very first error.
- bool fTryRecover; ///< Indicates if we should try recover from a corrupt structure header.
+ bool fTryRecover; ///< Indicates if we should try recover from a corrupt structure header or DDL trailer.
bool fSendDataOnParityError; ///< If set to true then we issue a OnData() event even if the data word had a parity error.
bool fHadError; ///< Indicates if we had an error decoding the data.
+ bool fAutoDetectTrailer; ///< Indicates if we should automatically check for the end of DDL trailer (Default = true).
+ bool fCheckForTrailer; ///< Indicates if we should check for the end of DDL trailer (Default = true). This flag is ignored if fAutoDetectTrailer is true.
UInt_t fMaxBlocks; ///< Maximum number of block structures allowed in a DDL stream.
UInt_t fMaxDSPs; ///< Maximum number of DSP structures allowed in a DDL stream.
UInt_t fMaxBusPatches; ///< Maximum number of bus patch structures allowed in a DDL stream.
EventHandler fHandler; ///< The event handler which deals with parsing events.
+ void DecodeBuffer(const UChar_t* start, const UChar_t* end);
+
bool DecodeBlockData(
const AliMUONBlockHeaderStruct* blockHeader,
const UChar_t* start, const UChar_t* end
static const UInt_t fgkDSPDataKey; ///< The key word expected to identify DSP structure headers.
static const UInt_t fgkBusPatchDataKey; ///< The key word expected to identify bus patch headers.
static const UInt_t fgkPaddingWord; ///< The expected format of the padding word in the DDL payload.
+ static const UInt_t fgkEndOfDDL; ///< The end of DDL trailer word.
};
//_____________________________________________________________________________
const UInt_t AliMUONTrackerDDLDecoder<EventHandler>::fgkBusPatchDataKey = 0xB000000B;
template <class EventHandler>
const UInt_t AliMUONTrackerDDLDecoder<EventHandler>::fgkPaddingWord = 0xBEEFFACE;
-
-
-inline const char* AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToString(ErrorCode code)
-{
- /// This is a utility method which converts an error code to a string
- /// representation for printing purposes.
- /// \param code The error code as received in OnError for example.
- /// \return An ANSI string containing the name of the error code symbol.
-
- switch (code)
- {
- case kNoError: return "kNoError";
- case kBufferTooBig: return "kBufferTooBig";
- case kTooManyBlocks: return "kTooManyBlocks";
- case kTooManyDSPs: return "kTooManyDSPs";
- case kTooManyBusPatches: return "kTooManyBusPatches";
- case kNoBlockHeader: return "kNoBlockHeader";
- case kBadBlockKey: return "kBadBlockKey";
- case kBadBlockLength: return "kBadBlockLength";
- case kBadBlockTotalLength: return "kBadBlockTotalLength";
- case kBlockLengthMismatch: return "kBlockLengthMismatch";
- case kNoDSPHeader: return "kNoDSPHeader";
- case kBadDSPKey: return "kBadDSPKey";
- case kBadDSPLength: return "kBadDSPLength";
- case kBadDSPTotalLength: return "kBadDSPTotalLength";
- case kDSPLengthMismatch: return "kDSPLengthMismatch";
- case kNoBusPatchHeader: return "kNoBusPatchHeader";
- case kBadBusPatchKey: return "kBadBusPatchKey";
- case kBadBusPatchLength: return "kBadBusPatchLength";
- case kBadBusPatchTotalLength: return "kBadBusPatchTotalLength";
- case kBusPatchLengthMismatch: return "kBusPatchLengthMismatch";
- case kGlitchFound: return "kGlitchFound";
- case kBadPaddingWord: return "kBadPaddingWord";
- case kParityError: return "kParityError";
- default: return "INVALID";
- }
-}
-
-
-inline const char* AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToMessage(ErrorCode code)
-{
- /// This is a utility method which converts an error code to user friendly
- /// descriptive message useful for printing to the screen.
- /// \param code The error code as received in OnError for example.
- /// \return An ANSI string containing a descriptive message of the error.
-
- switch (code)
- {
- case kNoError:
- return "Decoding was successful.";
- case kBufferTooBig:
- return "The DDL raw data is larger than indicated by the headers;"
- " extra bytes are probably just garbage.";
- case kTooManyBlocks:
- return "Too many block structures found.";
- case kTooManyDSPs:
- return "Too many DSP structures found in the block.";
- case kTooManyBusPatches:
- return "Too many bus patch structures found in the DSP structure.";
- case kNoBlockHeader:
- return "Missing a block header.";
- case kBadBlockKey:
- return "The block header key word does not contain the correct value.";
- case kBadBlockLength:
- return "The block length field points past the end of the raw data size.";
- case kBadBlockTotalLength:
- return "The total block length field points past the end of the"
- " raw data size.";
- case kBlockLengthMismatch:
- return "The block length and total length fields do not correspond."
- " One or both of these values is incorrect.";
- case kNoDSPHeader:
- return "Missing a DSP header.";
- case kBadDSPKey:
- return "The DSP header key word does not contain the correct value.";
- case kBadDSPLength:
- return "The DSP structure length field points past the end of the"
- " block structure.";
- case kBadDSPTotalLength:
- return "The total DSP structure length field points past the end of"
- " the block structure.";
- case kDSPLengthMismatch:
- return "The DSP structure length and total length fields do not"
- " correspond. One or both of these values is incorrect.";
- case kNoBusPatchHeader:
- return "Missing a bus patch header.";
- case kBadBusPatchKey:
- return "The bus patch header key word does not contain the correct value.";
- case kBadBusPatchLength:
- return "The bus patch length field points past the end of the"
- " DSP structure.";
- case kBadBusPatchTotalLength:
- return "The total bus patch length field points past the end of"
- " the DSP structure.";
- case kBusPatchLengthMismatch:
- return "The bus patch length and total length fields do not correspond."
- " One or both of these values is incorrect.";
- case kGlitchFound:
- return "Found a glitch. This means a 1 byte word has been randomly"
- " inserted into the raw data by mistake.";
- case kBadPaddingWord:
- return "The padding word does not contain the correct value.";
- case kParityError:
- return "Found a parity error in the data word.";
- default:
- return "Unknown error code!";
- }
-}
-
-
-inline std::ostream& operator << (std::ostream& os, AliMUONTrackerDDLDecoderEventHandler::ErrorCode code)
-{
- /// This is the stream operator for std::ostream classes to be able to
- /// easily write the error messages associated with the error codes generated
- /// by the decoder to 'cout' or 'cerr' for example.
-
- os << AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToMessage(code);
- return os;
-}
+template <class EventHandler>
+const UInt_t AliMUONTrackerDDLDecoder<EventHandler>::fgkEndOfDDL = 0xD000000D;
template <class EventHandler>
/// flag is set to true. There is also an optional flag fTryRecover which
/// can enable logic which will attempt to recover the header structures found
/// in the DDL payload if they are found to be inconsistent (assumed corrupt).
+ /// fTryRecover set to true will also enable recovery from a corrupt
+ /// DDL trailer marking the end of DDL payload.
///
/// \param buffer This is the pointer to the start of the memory buffer
/// containing the DDL payload. Remember that this must be the start of
fHadError = false;
// We are basically implementing something like a recursive decent parser.
- // So start by marking the current buffer position and end of buffer.
- const UChar_t* current = reinterpret_cast<const UChar_t*>(buffer);
- const UChar_t* end = current + bufferSize;
+ // So start by marking the start of buffer position and end of buffer.
+ const UChar_t* start = reinterpret_cast<const UChar_t*>(buffer);
+ const UChar_t* end = start + bufferSize;
- // Signal a new buffer event.
fHandler.OnNewBuffer(buffer, bufferSize);
+ DecodeBuffer(start, end);
+ fHandler.OnEndOfBuffer(buffer, bufferSize);
+ return not fHadError;
+}
+
+
+template <class EventHandler>
+void AliMUONTrackerDDLDecoder<EventHandler>::DecodeBuffer(
+ const UChar_t* start, const UChar_t* end
+ )
+{
+ /// This method decodes the buffer's payload data. It unpacks the block
+ /// structures contained inside and then for each block it calls the
+ /// OnNewBlock method for the event handler to signal the start of each new
+ /// block structure. OnEndOfBlock is called once each block is processed.
+ /// \param start This is the pointer to the start of the buffer.
+ /// \param end This is the pointer to the first byte just past the
+ /// end of the buffer.
+ /// fHadError is set to true if there were any errors decoding the buffer
+ /// and the OnError method of the callback event handler is called for
+ /// each error.
+
+ const UChar_t* current = start;
+ const UInt_t* bufferStart = reinterpret_cast<const UInt_t*>(start);
+ const UInt_t* bufferEnd = reinterpret_cast<const UInt_t*>(end);
+ bool problemWithTrailer = false;
+
+ // The DDL payload normally has a 2 word trailer which contains the end of
+ // DDL markers 0xD000000D. But this is not the case for older simulated
+ // data so if we are auto-detecting the trailer then we need to carefully
+ // check if these words are there or not.
+ const UChar_t* endOfBlocks = end;
+ const UInt_t* trailerWords = reinterpret_cast<const UInt_t*>(end) - 2;
+ if (fAutoDetectTrailer)
+ {
+ if (trailerWords >= bufferStart and *trailerWords == fgkEndOfDDL
+ and *(trailerWords+1) == fgkEndOfDDL
+ )
+ {
+ // Found the trailer so reposition the end of blocks marker.
+ endOfBlocks = reinterpret_cast<const UChar_t*>(trailerWords);
+ }
+ // else assume we are dealing with the older data format.
+ }
+ else if (fCheckForTrailer)
+ {
+ if (trailerWords >= bufferStart and *trailerWords == fgkEndOfDDL
+ and *(trailerWords+1) == fgkEndOfDDL
+ )
+ {
+ // Found the trailer so reposition the end of blocks marker.
+ endOfBlocks = reinterpret_cast<const UChar_t*>(trailerWords);
+ }
+ else
+ {
+ if (trailerWords+1 >= bufferStart and *(trailerWords+1) == fgkEndOfDDL)
+ fHandler.OnError(EventHandler::kTooFewDDLTrailerWords, trailerWords+1);
+ else if (trailerWords >= bufferStart and *(trailerWords) == fgkEndOfDDL)
+ fHandler.OnError(EventHandler::kTooFewDDLTrailerWords, trailerWords);
+ else
+ fHandler.OnError(EventHandler::kNoDDLTrailerWords, end);
+
+ // Stop the decoding if so requested by the user, otherwise
+ // remember about the error so that we return false from the
+ // Decode() method and continue decoding.
+ fHadError = true;
+ if (fExitOnError) return;
+
+ // Mark that there was a problem with the trailer so that
+ // for subsequent errors we try to deal with this better.
+ problemWithTrailer = true;
+
+ // We can also try figure out how many trailer words there
+ // actually are and move the end of blocks marker back.
+
+ if (fTryRecover)
+ {
+ trailerWords = bufferEnd;
+ // There should only be a max of 2 trailer words.
+ if (*(trailerWords-1) == fgkEndOfDDL)
+ trailerWords--;
+ else if (*(trailerWords-1) == fgkEndOfDDL)
+ trailerWords--;
+ endOfBlocks = reinterpret_cast<const UChar_t*>(trailerWords);
+ }
+ }
+ }
UInt_t blockCount = 0; // Indicates the number of blocks decoded.
- while (current < end)
+ while (current < endOfBlocks)
{
// Mark the start of the block structure.
const UChar_t* blockStart = current;
const AliMUONBlockHeaderStruct* blockHeader
= reinterpret_cast<const AliMUONBlockHeaderStruct*>(blockStart);
current += sizeof(AliMUONBlockHeaderStruct);
- if (current > end)
+ if (current > endOfBlocks)
{
+ // We first check if we actually hit the end of DDL markers
+ // If we did then either we did not/could not recover from
+ // a corrupt trailer or we did not detect a correct trailer
+ // in auto-detect mode.
+ trailerWords = reinterpret_cast<const UInt_t*>(blockHeader);
+ // The "trailerWords+1 <= bufferEnd" checks that we are
+ // not reading beyond the end of the buffer.
+ if (trailerWords+1 <= bufferEnd and *trailerWords == fgkEndOfDDL)
+ {
+ // If we aready knew the trailer was corrupt then just
+ // return because the error was already announced.
+ if (problemWithTrailer) return;
+
+ if (fAutoDetectTrailer)
+ {
+ // If we got here then there is at least one correct trailer
+ // word, but since we did not detect a correct trailer then
+ // there must be only one. Announce the error and exit.
+ fHandler.OnError(EventHandler::kTooFewDDLTrailerWords, trailerWords);
+ fHadError = true;
+ return;
+ }
+ }
+
// So we only got part of a block header at the very end
// of the buffer. Nothing to do but report the error and exit.
if (blockCount == fMaxBlocks)
fHandler.OnError(EventHandler::kBufferTooBig, blockHeader);
else
fHandler.OnError(EventHandler::kNoBlockHeader, blockHeader);
- return false;
+ fHadError = true;
+ return;
}
// The header fits the buffer so we can mark the data start and
// If any of the above fail then we know there is a problem with
// the block header. It must be corrupted somehow.
if (blockHeader->fDataKey != fgkBlockDataKey
- or dataEnd > end or blockEnd > end or dataEnd != blockEnd)
+ or dataEnd > endOfBlocks or blockEnd > endOfBlocks or dataEnd != blockEnd)
{
// So let us see what exactly is wrong and report this.
if (blockCount == fMaxBlocks)
// expected, so the remaining data must be rubbish.
// Don't even bother trying to recover the data.
fHandler.OnError(EventHandler::kBufferTooBig, blockHeader);
- return false;
+ fHadError = true;
+ return;
}
if (blockHeader->fDataKey != fgkBlockDataKey)
fHandler.OnError(EventHandler::kBadBlockKey, &blockHeader->fDataKey);
- if (blockEnd > end)
+ if (blockEnd > endOfBlocks)
fHandler.OnError(EventHandler::kBadBlockLength, &blockHeader->fLength);
- if (dataEnd > end)
+ if (dataEnd > endOfBlocks)
fHandler.OnError(EventHandler::kBadBlockTotalLength, &blockHeader->fTotalLength);
if (dataEnd != blockEnd)
fHandler.OnError(EventHandler::kBlockLengthMismatch, blockHeader);
// Stop the decoding if so requested by the user, otherwise
- // remember about the error so that we return false from this
- // routine and continue decoding.
- if (fExitOnError)
- return false;
- else
- fHadError = true;
+ // remember about the error so that we return false from the
+ // Decode() method and continue decoding.
+ fHadError = true;
+ if (fExitOnError) return;
// Try to recover from the corrupt header.
RecoverResult result = TryRecoverStruct(
fgkBlockDataKey, sizeof(AliMUONBlockHeaderStruct),
blockHeader->fTotalLength, blockHeader->fLength,
- blockStart, end, dataEnd, blockEnd, current
+ blockStart, endOfBlocks, dataEnd, blockEnd, current
);
if (result == kContinueToNextStruct)
continue; // Try the next block at 'current'.
- if (result == kRecoverFailed) return false;
+ if (result == kRecoverFailed) return;
}
// At this point we certainly have a valid block header, so we
// In this case we stop the decoding because clearly
// something is seriously wrong with the data if we are
// getting more blocks than expected.
- return false;
+ fHadError = true;
+ return;
}
fHandler.OnNewBlock(blockHeader, dataStart);
- if (DecodeBlockData(blockHeader, dataStart, dataEnd)) continue;
-
- // At this point we had a problem decoding the block structure's
- // data. Thus we should stop further decoding if so requested by
- // the user. Note the fHadError flag is already marked inside
- // DecodeBlockData.
- if (fExitOnError) return false;
+ if (not DecodeBlockData(blockHeader, dataStart, dataEnd))
+ {
+ // At this point we had a problem decoding the block structure's
+ // data. Thus we should stop further decoding if so requested by
+ // the user. Note the fHadError flag is already marked inside
+ // DecodeBlockData.
+ if (fExitOnError)
+ {
+ fHandler.OnEndOfBlock(blockHeader, dataStart);
+ return;
+ }
+ }
+ fHandler.OnEndOfBlock(blockHeader, dataStart);
}
-
- return not fHadError;
}
// the next event.
fHandler.OnError(EventHandler::kGlitchFound, &dspHeader->fErrorWord);
fHadError = true;
- if (fExitOnError) return false;
+ if (fExitOnError)
+ {
+ fHandler.OnEndOfDSP(dspHeader, dataStart);
+ return false;
+ }
// Try recover by finding the very next DSP and continue
// decoding from there. Note: to achieve all we have to do
{
fHandler.OnError(EventHandler::kBadPaddingWord, padWord);
fHadError = true;
- if (fExitOnError) return false;
+ if (fExitOnError)
+ {
+ fHandler.OnEndOfDSP(dspHeader, dataStart);
+ return false;
+ }
}
}
- if (DecodeDSPData(dataStart, dataEnd)) continue;
-
- // At this point we had a problem decoding the DSP structure's
- // data, thus we should stop further decoding if so requested by
- // the user. Note the fHadError flag is already marked inside
- // DecodeDSPData.
- if (fExitOnError) return false;
+ if (not DecodeDSPData(dataStart, dataEnd))
+ {
+ // At this point we had a problem decoding the DSP structure's
+ // data, thus we should stop further decoding if so requested by
+ // the user. Note the fHadError flag is already marked inside
+ // DecodeDSPData.
+ if (fExitOnError)
+ {
+ fHandler.OnEndOfDSP(dspHeader, dataStart);
+ return false;
+ }
+ }
+ fHandler.OnEndOfDSP(dspHeader, dataStart);
}
return true;
}
fHandler.OnNewBusPatch(busPatchHeader, dataStart);
- if (DecodeBusPatchData(dataStart, dataEnd)) continue;
-
- // At this point we had a problem decoding the bus patch data,
- // thus we should stop further decoding if so requested by the
- // user. Note the fHadError flag is already marked inside
- // DecodeBusPatchData.
- if (fExitOnError) return false;
+ if (not DecodeBusPatchData(dataStart, dataEnd))
+ {
+ // At this point we had a problem decoding the bus patch data,
+ // thus we should stop further decoding if so requested by the
+ // user. Note the fHadError flag is already marked inside
+ // DecodeBusPatchData.
+ if (fExitOnError)
+ {
+ fHandler.OnEndOfBusPatch(busPatchHeader, dataStart);
+ return false;
+ }
+ }
+ fHandler.OnEndOfBusPatch(busPatchHeader, dataStart);
}
return true;
{
if (ParityIsOk(*data))
{
- fHandler.OnData(*data);
+ fHandler.OnData(*data, false);
}
else
{
if (fExitOnError) return false;
if (fSendDataOnParityError)
- fHandler.OnData(*data);
+ fHandler.OnData(*data, true);
}
}
const UInt_t* headerKey = reinterpret_cast<const UInt_t*>(structStart);
bool headerKeyOk = (expectedKey == *headerKey);
- bool lengthsMatch = (totalLength == length + headerSize);
+ bool lengthsMatch = (totalLength*4 == length*4 + headerSize);
bool lengthIsCorrect = false;
bool totalLengthIsCorrect = false;
const UInt_t* keyAtDataEnd = reinterpret_cast<const UInt_t*>(dataEnd);
const UInt_t* keyAtStructEnd = reinterpret_cast<const UInt_t*>(structEnd);
- switch (expectedKey)
- {
- case fgkBlockDataKey:
+
+ if ( expectedKey == fgkBlockDataKey )
+ {
if (dataEnd == bufferEnd)
{
// Are we at the end of the buffer?
totalLengthIsCorrect = true;
}
}
+ }
- break;
-
- case fgkDSPDataKey:
+ else if ( expectedKey == fgkDSPDataKey )
+ {
if (dataEnd == bufferEnd)
{
// Are we at the end of the buffer?
totalLengthIsCorrect = true;
}
}
-
- break;
-
- case fgkBusPatchDataKey:
+ }
+ else if ( expectedKey == fgkBusPatchDataKey )
+ {
if (dataEnd == bufferEnd)
{
// Are we at the end of the buffer?
totalLengthIsCorrect = true;
}
}
-
- break;
-
- default:
- // lengthIsCorrect and totalLengthIsCorrect already set to false.
- break;
- }
+ }
if (headerKeyOk and lengthIsCorrect)
{