Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:18

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