Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:20:06

0001 // @file PayLoadCont.h
0002 // @brief Declaration of class for continuos buffer of ALPIDE data
0003 // @author ruben.shahoyan@cern.ch
0004 // @sa
0005 // <O2/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PayLoadCont.h>
0006 //     <03608ff89>
0007 
0008 #ifndef MVTXDECODER_PAYLOADCONT_H
0009 #define MVTXDECODER_PAYLOADCONT_H
0010 
0011 #include <cstdint>
0012 #include <cstring>
0013 #include <functional>
0014 #include <vector>
0015 
0016 namespace mvtx
0017 {
0018 
0019   class PayLoadCont
0020   {
0021     /// continous buffer for the payload, just a preallocated vector with current
0022     /// position and end pointer. Big endian is used.
0023 
0024    public:
0025     static constexpr size_t MinCapacity = 16;
0026 
0027     ///< allocate buffer
0028     PayLoadCont() = default;
0029     PayLoadCont(size_t sz) { expand(sz); }
0030     ~PayLoadCont() = default;
0031 
0032     PayLoadCont(const PayLoadCont &src);
0033 
0034     PayLoadCont &operator=(const PayLoadCont &src);
0035 
0036     const uint8_t *data() const { return mBuffer.data(); }
0037 
0038     ///< increase the buffer size
0039     void expand(size_t sz);
0040 
0041     bool isEmpty() const { return mPtr >= mEnd; }
0042 
0043     ///< make buffer empty w/o deallocating it
0044     void clear(uint32_t maxCapacity = 0)
0045     {
0046       mPtr = mBuffer.data();
0047       mEnd = mPtr;
0048       if (maxCapacity && mBuffer.capacity() > (5 * maxCapacity))
0049       {
0050         std::vector<uint8_t>().swap(mBuffer);
0051         expand(maxCapacity);
0052       }
0053     }
0054 
0055     ///< get unused size
0056     size_t getUnusedSize() const { return mEnd > mPtr ? mEnd - mPtr : 0; }
0057 
0058     ///< get filled size
0059     size_t getSize() const { return mEnd - mBuffer.data(); }
0060 
0061     ///< get offset of the current ptr from the head
0062     size_t getOffset() const { return mPtr - mBuffer.data(); }
0063 
0064     ///< booked capacity
0065     size_t getCapacity() const { return mBuffer.size(); }
0066 
0067     ///< number of bytes still can accept w/o expanding the buffer
0068     size_t getFreeCapacity() const { return mBuffer.size() - getSize(); }
0069 
0070     ///< make sure buffer may accept at least n bytes
0071     void ensureFreeCapacity(size_t n)
0072     {
0073       if (getFreeCapacity() < n)
0074       {
0075         expand(getCapacity() + 2 * n);
0076       }
0077     }
0078 
0079     ///< fill n bytes with given symbol w/o checking for the size
0080     void fillFast(const uint8_t c, size_t n)
0081     {
0082       std::memset(mEnd, c, n);
0083       mEnd += n;
0084     }
0085 
0086     ///< add n bytes to the buffer w/o checking for the size
0087     void addFast(const uint8_t *ptr, size_t n)
0088     {
0089       std::memcpy(mEnd, ptr, n);
0090       mEnd += n;
0091     }
0092 
0093     ///< add new byte to the buffer w/o checking for the size
0094     void addFast(uint8_t val) { *mEnd++ = val; }
0095 
0096     ///< add new short to the buffer w/o checking for the size
0097     void addFast(uint16_t val)
0098     {
0099       *mEnd++ = val >> 8;
0100       *mEnd++ = 0xff & val;
0101     }
0102 
0103     ///< erase n bytes w/o checking for the underflow
0104     void eraseFast(size_t n) { mEnd -= n; }
0105 
0106     ///< erase n bytes
0107     void erase(size_t n)
0108     {
0109       if (n > getSize())
0110       {
0111         clear();
0112       }
0113       else
0114       {
0115         eraseFast(n);
0116       }
0117     }
0118 
0119     ///< fill n bytes with given symbol
0120     void fill(const uint8_t c, size_t n)
0121     {
0122       ensureFreeCapacity(n);
0123       fillFast(c, n);
0124     }
0125 
0126     ///< add n bytes to the buffer, expand if needed. no check for overlap
0127     void add(const uint8_t *ptr, size_t n)
0128     {
0129       ensureFreeCapacity(n);
0130       addFast(ptr, n);
0131     }
0132 
0133     ///< add new byte to the buffer
0134     void add(uint8_t val)
0135     {
0136       ensureFreeCapacity(sizeof(val));
0137       addFast(val);
0138     }
0139 
0140     ///< add new short to the buffer
0141     void add(uint16_t val)
0142     {
0143       ensureFreeCapacity(sizeof(val));
0144       addFast(val);
0145     }
0146 
0147     ///< shrink buffer to requested size, no check on over/under flow
0148     void shrinkToSize(size_t sz) { mEnd = mPtr + sz; }
0149 
0150     ///< direct const access to value at a given slot, w/o checking for overflow
0151     uint8_t operator[](size_t i) const { return mBuffer[i]; }
0152 
0153     ///< direct access to value at a given slot, w/o checking for overflow
0154     uint8_t &operator[](size_t i) { return mBuffer[i]; }
0155 
0156     ///< read current character value from buffer w/o stepping forward
0157     bool current(uint8_t &v) const
0158     {
0159       if (mPtr < mEnd)
0160       {
0161         v = *mPtr;
0162         return true;
0163       }
0164       return false;
0165     }
0166 
0167     ///< read character value from buffer
0168     bool next(uint8_t &v)
0169     {
0170       if (mPtr < mEnd)
0171       {
0172         v = *mPtr++;
0173         return true;
0174       }
0175       return false;
0176     }
0177 
0178     ///< read short value from buffer
0179     bool next(uint16_t &v)
0180     {
0181       if (mPtr < mEnd - (sizeof(uint16_t) - 1))
0182       {
0183         v = (*mPtr++) << 8;
0184         v |= (*mPtr++);
0185         return true;
0186       }
0187       return false;
0188     }
0189 
0190     ///< move current pointer to the head
0191     void rewind() { mPtr = mBuffer.data(); }
0192 
0193     ///< move all data between the mPtr and mEnd to the head of the buffer
0194     void moveUnusedToHead()
0195     {
0196       auto left = getUnusedSize();
0197       if (left < getOffset())
0198       {
0199         std::memcpy(mBuffer.data(), mPtr, left);  // there is no overlap
0200       }
0201       else
0202       {
0203         std::memmove(mBuffer.data(), mPtr, left);  // there is an overlap
0204       }
0205       mPtr = mBuffer.data();
0206       mEnd = mPtr + left;
0207     }
0208 
0209     ///< move unused data to the head and upload new chunk of data
0210     // (attemtint to use all free capacity) using the method provided via getNext
0211     size_t append(std::function<size_t(uint8_t *, size_t)> getNext)
0212     {
0213       moveUnusedToHead();
0214       auto nRead = getNext(mEnd, getFreeCapacity());
0215       mEnd += nRead;
0216       return nRead;
0217     }
0218 
0219     /// direct write access
0220     uint8_t *getPtr() { return mPtr; }
0221     void setPtr(uint8_t *ptr) { mPtr = ptr; }
0222     void movePtr(size_t step) { mPtr += step; }
0223 
0224     uint8_t *getEnd() { return mEnd; }
0225     void setEnd(uint8_t *ptr) { mEnd = ptr; }
0226 
0227    private:
0228     std::vector<uint8_t> mBuffer;  //! continuons data buffer
0229     uint8_t *mPtr = nullptr;       ///! pointer on the position in the buffer
0230     uint8_t *mEnd = nullptr;       ///! pointer on the last+1 valid entry in the buffer
0231 
0232     //  ClassDefNV(PayLoadCont, 1);
0233   };
0234 
0235 }  // namespace mvtx
0236 
0237 #endif