Home | History | Annotate | Download | only in EKA2
      1 /*
      2     vectorbuffer.cpp
      3     yet another circle buffer
      4 
      5     Markus Mertama
      6 */
      7 
      8 #ifndef __VECTORBUFFER_H__
      9 #define __VECTORBUFFER_H__
     10 
     11 #include<e32std.h>
     12 #define VLOG(x)
     13 #define VECPANIC(x) VectorPanic(x, __LINE__)
     14 void VectorPanic(TInt, TInt);
     15 
     16 
     17 //int DEBUG_INT;
     18 
     19 NONSHARABLE_CLASS(TNodeBuffer)
     20     {
     21     public:
     22     protected:
     23         NONSHARABLE_CLASS(TNode)
     24             {
     25             public:
     26                 static  TNode* Empty(TUint8* iBuffer);
     27                 static  TNode* New(TNode* aPrev,  const TDesC8& aData);
     28                 const TUint8* Ptr() const;
     29                 TInt Size() const;
     30                 inline TNode* Succ();
     31                 static void SetSucc(TNode*& aNode);
     32                 void Terminator(TNode* aNode);
     33             private:
     34                 TNode* iSucc;
     35             };
     36     };
     37 
     38 inline TNodeBuffer::TNode* TNodeBuffer::TNode::Succ()
     39     {
     40     return iSucc;
     41     }
     42 
     43 template <TInt C>
     44 NONSHARABLE_CLASS(TVectorBuffer) : public TNodeBuffer
     45     {
     46     public:
     47         TVectorBuffer();
     48         TInt Append(const TDesC8& aData);
     49      //   TInt AppendOverwrite(const TDesC8& aData);
     50         TPtrC8 Shift();
     51         TPtrC8 operator[](TInt aIndex) const;
     52         TInt Size() const;
     53     private:
     54         TInt GetRoom(TInt aSize) const;
     55         TInt Unreserved() const;
     56     private:
     57         TNode* iTop;
     58         TNode* iBottom;
     59         TInt iSize;
     60         TUint8 iBuffer[C];
     61     };
     62 
     63 template <TInt C>
     64 TVectorBuffer<C>::TVectorBuffer() : iSize(0)
     65     {
     66     Mem::FillZ(iBuffer, C);
     67     iTop = TNode::Empty(iBuffer); //these points to buffer
     68     iBottom = TNode::Empty(iBuffer);
     69     }
     70 
     71 template<TInt C >
     72 TInt TVectorBuffer<C>::Unreserved() const
     73     {
     74     __ASSERT_DEBUG(iBottom < iBottom->Succ(), VECPANIC(KErrCorrupt));
     75     const TInt bytesbetween =
     76         reinterpret_cast<const TUint8*>(iBottom->Succ()) -
     77         reinterpret_cast<const TUint8*>(iTop);
     78     const TInt topsize = sizeof(TNode);
     79     if(bytesbetween > 0)            //bytesbetween is room between bottom and top
     80         {                           //therefore free room is subracted from free space
     81 
     82         const TInt room = C - bytesbetween - topsize;
     83         return room;
     84         }
     85     if(bytesbetween == 0)
     86         {
     87 
     88         if(Size() > 0)
     89             return 0;
     90         else
     91             return C - topsize;
     92         }
     93     const TInt room = -bytesbetween - topsize; //free is space between pointers
     94     return room;
     95     }
     96 
     97 template <TInt C>
     98 TInt TVectorBuffer<C>::GetRoom(TInt aSize) const
     99     {
    100     const TInt bytesnew = sizeof(TNode) + aSize;
    101     const TInt room = Unreserved() - bytesnew;
    102     return room;
    103     }
    104 
    105 template <TInt C>
    106 TInt TVectorBuffer<C>::Append(const TDesC8& aData) //ei ole ok!
    107     {
    108     const TInt len = aData.Length();
    109     if(GetRoom(len) < 0)
    110         {
    111         return KErrOverflow;
    112         }
    113     if(iBottom->Succ()->Ptr() - iBuffer > (C - (len + TInt(sizeof(TNode)))))
    114         {
    115         VLOG("rc");
    116        // RDebug::Print(_L("vector: append"));
    117         TNode* p = TNode::Empty(iBuffer);
    118         iBottom->Terminator(p);
    119       	iBottom = p;
    120       	return Append(aData);
    121      //	Append();
    122      //	iBottom = TNode::New(p, aData); //just append something into end
    123         }
    124 
    125     //DEBUG_INT++;
    126 
    127     iBottom = TNode::New(iBottom, aData);
    128 
    129     iSize += len;
    130     return KErrNone;
    131     }
    132 
    133 /*
    134 template <TInt C>
    135 TInt TVectorBuffer<C>::AppendOverwrite(const TDesC8& aData) //ei ole ok!
    136     {
    137     while(Append(aData) == KErrOverflow)
    138         {
    139         if(iTop->Succ() == NULL)
    140             {
    141             return KErrUnderflow;
    142             }
    143         //Shift(); //data is lost
    144         }
    145     return KErrNone;
    146     }
    147 */
    148 template <TInt C>
    149 TPtrC8 TVectorBuffer<C>::Shift()
    150     {
    151     __ASSERT_ALWAYS(iTop->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom
    152     TNode* node = iTop;
    153     iTop = iTop->Succ();
    154     if(iTop > node)
    155         {
    156       //  DEBUG_INT--;
    157         iSize -= node->Size();
    158         return TPtrC8(node->Ptr(), node->Size());
    159         }
    160     else
    161         {
    162       //  RDebug::Print(_L("vector: shift"));
    163         return Shift(); //this happens when buffer is terminated, and data lies in next
    164         }
    165     }
    166 
    167 template <TInt C>
    168 TInt TVectorBuffer<C>::Size() const
    169     {
    170     return iSize;
    171     }
    172 
    173 template <TInt C>
    174 TPtrC8 TVectorBuffer<C>::operator[](TInt aIndex) const
    175     {
    176     TInt index = 0;
    177     TNode* t = iTop->Size() > 0 ? iTop : iTop->Succ(); //eliminate terminator
    178     while(index < aIndex)
    179         {
    180         TNode* nt = t->Succ();
    181         if(nt < t)
    182             {
    183             nt = nt->Succ();
    184             }
    185         t = nt;
    186         if(t->Size() > 0)
    187         	index++;
    188         __ASSERT_ALWAYS(t->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom
    189         }
    190     return t->Ptr();
    191     }
    192 
    193 
    194 template <class T, TInt C>
    195 NONSHARABLE_CLASS(TVector) : public TVectorBuffer<C * sizeof(T)>
    196     {
    197     public:
    198         TVector();
    199         TInt Append(const T& aData);
    200         const T& Shift();
    201         TInt Size() const;
    202         const T& operator[](TInt aIndex) const;
    203     };
    204 
    205 template <class T, TInt C>
    206 TVector<T, C>::TVector() : TVectorBuffer<C * sizeof(T)>()
    207     {
    208     }
    209 
    210 template <class T, TInt C>
    211 TInt TVector<T, C>::Append(const T& aData)
    212     {
    213     const TPckgC<T> data(aData);
    214     return TVectorBuffer<C * sizeof(T)>::Append(data);
    215     }
    216 
    217 template <class T, TInt C>
    218 const T& TVector<T, C>::Shift()
    219     {
    220     const TPtrC8 ptr = TVectorBuffer<C * sizeof(T)>::Shift();
    221     return *(reinterpret_cast<const T*>(ptr.Ptr()));
    222     }
    223 
    224 
    225 template <class T, TInt C>
    226 TInt TVector<T, C>::Size() const
    227     {
    228     return TVectorBuffer<C * sizeof(T)>::Size() / sizeof(T);
    229     }
    230 
    231 template <class T, TInt C>
    232 const T& TVector<T, C>::operator[](TInt aIndex) const
    233     {
    234     const TPtrC8 ptr = TVectorBuffer<C * sizeof(T)>::operator[](aIndex);
    235     return *(reinterpret_cast<const T*>(ptr.Ptr()));
    236     }
    237 
    238 #endif
    239 
    240 
    241