Mercurial > sdl-ios-xcode
view src/main/symbian/EKA2/vectorbuffer.h @ 4146:dc726b233f5f SDL-1.2
Merged r3674:3675 from trunk: comment in README about svn RSS feed.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 05 Jul 2008 18:27:27 +0000 |
parents | e85e65aec22f |
children |
line wrap: on
line source
/* vectorbuffer.cpp yet another circle buffer Markus Mertama */ #ifndef __VECTORBUFFER_H__ #define __VECTORBUFFER_H__ #include<e32std.h> #define VLOG(x) #define VECPANIC(x) VectorPanic(x, __LINE__) void VectorPanic(TInt, TInt); //int DEBUG_INT; NONSHARABLE_CLASS(TNodeBuffer) { public: protected: NONSHARABLE_CLASS(TNode) { public: static TNode* Empty(TUint8* iBuffer); static TNode* New(TNode* aPrev, const TDesC8& aData); const TUint8* Ptr() const; TInt Size() const; inline TNode* Succ(); static void SetSucc(TNode*& aNode); void Terminator(TNode* aNode); private: TNode* iSucc; }; }; inline TNodeBuffer::TNode* TNodeBuffer::TNode::Succ() { return iSucc; } template <TInt C> NONSHARABLE_CLASS(TVectorBuffer) : public TNodeBuffer { public: TVectorBuffer(); TInt Append(const TDesC8& aData); // TInt AppendOverwrite(const TDesC8& aData); TPtrC8 Shift(); TPtrC8 operator[](TInt aIndex) const; TInt Size() const; private: TInt GetRoom(TInt aSize) const; TInt Unreserved() const; private: TNode* iTop; TNode* iBottom; TInt iSize; TUint8 iBuffer[C]; }; template <TInt C> TVectorBuffer<C>::TVectorBuffer() : iSize(0) { Mem::FillZ(iBuffer, C); iTop = TNode::Empty(iBuffer); //these points to buffer iBottom = TNode::Empty(iBuffer); } template<TInt C > TInt TVectorBuffer<C>::Unreserved() const { __ASSERT_DEBUG(iBottom < iBottom->Succ(), VECPANIC(KErrCorrupt)); const TInt bytesbetween = reinterpret_cast<const TUint8*>(iBottom->Succ()) - reinterpret_cast<const TUint8*>(iTop); const TInt topsize = sizeof(TNode); if(bytesbetween > 0) //bytesbetween is room between bottom and top { //therefore free room is subracted from free space const TInt room = C - bytesbetween - topsize; return room; } if(bytesbetween == 0) { if(Size() > 0) return 0; else return C - topsize; } const TInt room = -bytesbetween - topsize; //free is space between pointers return room; } template <TInt C> TInt TVectorBuffer<C>::GetRoom(TInt aSize) const { const TInt bytesnew = sizeof(TNode) + aSize; const TInt room = Unreserved() - bytesnew; return room; } template <TInt C> TInt TVectorBuffer<C>::Append(const TDesC8& aData) //ei ole ok! { const TInt len = aData.Length(); if(GetRoom(len) < 0) { return KErrOverflow; } if(iBottom->Succ()->Ptr() - iBuffer > (C - (len + TInt(sizeof(TNode))))) { VLOG("rc"); // RDebug::Print(_L("vector: append")); TNode* p = TNode::Empty(iBuffer); iBottom->Terminator(p); iBottom = p; return Append(aData); // Append(); // iBottom = TNode::New(p, aData); //just append something into end } //DEBUG_INT++; iBottom = TNode::New(iBottom, aData); iSize += len; return KErrNone; } /* template <TInt C> TInt TVectorBuffer<C>::AppendOverwrite(const TDesC8& aData) //ei ole ok! { while(Append(aData) == KErrOverflow) { if(iTop->Succ() == NULL) { return KErrUnderflow; } //Shift(); //data is lost } return KErrNone; } */ template <TInt C> TPtrC8 TVectorBuffer<C>::Shift() { __ASSERT_ALWAYS(iTop->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom TNode* node = iTop; iTop = iTop->Succ(); if(iTop > node) { // DEBUG_INT--; iSize -= node->Size(); return TPtrC8(node->Ptr(), node->Size()); } else { // RDebug::Print(_L("vector: shift")); return Shift(); //this happens when buffer is terminated, and data lies in next } } template <TInt C> TInt TVectorBuffer<C>::Size() const { return iSize; } template <TInt C> TPtrC8 TVectorBuffer<C>::operator[](TInt aIndex) const { TInt index = 0; TNode* t = iTop->Size() > 0 ? iTop : iTop->Succ(); //eliminate terminator while(index < aIndex) { TNode* nt = t->Succ(); if(nt < t) { nt = nt->Succ(); } t = nt; if(t->Size() > 0) index++; __ASSERT_ALWAYS(t->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom } return t->Ptr(); } template <class T, TInt C> NONSHARABLE_CLASS(TVector) : public TVectorBuffer<C * sizeof(T)> { public: TVector(); TInt Append(const T& aData); const T& Shift(); TInt Size() const; const T& operator[](TInt aIndex) const; }; template <class T, TInt C> TVector<T, C>::TVector() : TVectorBuffer<C * sizeof(T)>() { } template <class T, TInt C> TInt TVector<T, C>::Append(const T& aData) { const TPckgC<T> data(aData); return TVectorBuffer<C * sizeof(T)>::Append(data); } template <class T, TInt C> const T& TVector<T, C>::Shift() { const TPtrC8 ptr = TVectorBuffer<C * sizeof(T)>::Shift(); return *(reinterpret_cast<const T*>(ptr.Ptr())); } template <class T, TInt C> TInt TVector<T, C>::Size() const { return TVectorBuffer<C * sizeof(T)>::Size() / sizeof(T); } template <class T, TInt C> const T& TVector<T, C>::operator[](TInt aIndex) const { const TPtrC8 ptr = TVectorBuffer<C * sizeof(T)>::operator[](aIndex); return *(reinterpret_cast<const T*>(ptr.Ptr())); } #endif