]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - MUON/AliMUONTrackerDDLDecoder.h
Protection against index out of range
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerDDLDecoder.h
index d7305f0397d6145cc3793ca27692880907df6b74..c64c272cee23bd21237246ae010970cbc596b018 100644 (file)
 
 #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.
@@ -170,6 +165,8 @@ private:
        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
@@ -225,125 +222,6 @@ 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>
 bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t bufferSize)
 {
@@ -380,12 +258,34 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
        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.
+       /// \return If the blocks in the buffer were decoded without errors
+       ///      or we could recover from the errors, then true is returned.
+       ///      False is returned otherwise.
+       
+       const UChar_t* current = start;
 
        UInt_t blockCount = 0; // Indicates the number of blocks decoded.
        while (current < end)
@@ -408,7 +308,8 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                                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
@@ -436,7 +337,8 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                                // 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);
@@ -448,12 +350,10 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                                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(
@@ -463,7 +363,7 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                                );
                        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
@@ -476,20 +376,25 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::Decode(const void* buffer, UInt_t b
                        // 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;
 }
 
 
@@ -607,7 +512,11 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBlockData(
                        // 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
@@ -629,17 +538,27 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBlockData(
                        {
                                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;
@@ -749,13 +668,19 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeDSPData(
                }
                
                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;
@@ -793,7 +718,7 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBusPatchData(
        {
                if (ParityIsOk(*data))
                {
-                       fHandler.OnData(*data);
+                       fHandler.OnData(*data, false);
                }
                else
                {
@@ -804,7 +729,7 @@ bool AliMUONTrackerDDLDecoder<EventHandler>::DecodeBusPatchData(
                        if (fExitOnError) return false;
                        
                        if (fSendDataOnParityError)
-                               fHandler.OnData(*data);
+                               fHandler.OnData(*data, true);
                }
        }
        
@@ -915,9 +840,9 @@ AliMUONTrackerDDLDecoder<EventHandler>::TryRecoverStruct(
        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?
@@ -949,10 +874,10 @@ AliMUONTrackerDDLDecoder<EventHandler>::TryRecoverStruct(
                                        totalLengthIsCorrect = true;
                        }
                }
+        }        
                        
-               break;
-       
-       case fgkDSPDataKey:
+        else if ( expectedKey == fgkDSPDataKey )
+        {
                if (dataEnd == bufferEnd)
                {
                        // Are we at the end of the buffer?
@@ -986,10 +911,9 @@ AliMUONTrackerDDLDecoder<EventHandler>::TryRecoverStruct(
                                        totalLengthIsCorrect = true;
                        }
                }
-                       
-               break;
-       
-       case fgkBusPatchDataKey:
+        }        
+        else if ( expectedKey == fgkBusPatchDataKey )
+        {
                if (dataEnd == bufferEnd)
                {
                        // Are we at the end of the buffer?
@@ -1023,13 +947,7 @@ AliMUONTrackerDDLDecoder<EventHandler>::TryRecoverStruct(
                                        totalLengthIsCorrect = true;
                        }
                }
-                       
-               break;
-               
-       default:
-               // lengthIsCorrect and totalLengthIsCorrect already set to false.
-               break;
-       }
+        }
        
        if (headerKeyOk and lengthIsCorrect)
        {