Big cleanup part 1.
[SDL.s60v3.git] / src / main / symbian / vectorbuffer.h
blob8a1205513c6c9c2b70019df369946f1388a9c34b
1 /*
2 vectorbuffer.cpp
3 yet another circle buffer
5 Markus Mertama
6 */
8 #ifndef __VECTORBUFFER_H__
9 #define __VECTORBUFFER_H__
11 #include<e32std.h>
12 #define VECPANIC(x) VectorPanic(x, __LINE__)
13 void VectorPanic(TInt, TInt);
16 //Internal
18 NONSHARABLE_CLASS(TNodeBuffer)
20 public:
21 protected:
22 NONSHARABLE_CLASS(TNode)
24 public:
25 static TNode* Empty(TUint8* iBuffer);
26 static TNode* New(TNode* aPrev, const TDesC8& aData);
27 const TUint8* Ptr() const;
28 TInt Size() const;
29 inline TNode* Succ();
30 static void SetSucc(TNode*& aNode);
31 void Terminator(TNode* aNode);
32 private:
33 TNode* iSucc;
37 inline TNodeBuffer::TNode* TNodeBuffer::TNode::Succ()
39 return iSucc;
43 //Vector buffer for variable length data
45 template <TInt C>
46 NONSHARABLE_CLASS(TVectorBuffer) : public TNodeBuffer
48 public:
49 TVectorBuffer();
50 TInt Append(const TDesC8& aData);
51 TPtrC8 Shift();
52 TPtrC8 operator[](TInt aIndex) const;
53 TInt Size() const;
54 private:
55 TInt GetRoom(TInt aSize) const;
56 TInt Unreserved() const;
57 private:
58 TNode* iTop;
59 TNode* iBottom;
60 TInt iSize;
61 TUint8 iBuffer[C];
64 template <TInt C>
65 TVectorBuffer<C>::TVectorBuffer() : iSize(0)
67 Mem::FillZ(iBuffer, C);
68 iTop = TNode::Empty(iBuffer); //these points to buffer
69 iBottom = TNode::Empty(iBuffer);
72 template<TInt C >
73 TInt TVectorBuffer<C>::Unreserved() const
75 __ASSERT_DEBUG(iBottom < iBottom->Succ(), VECPANIC(KErrCorrupt));
76 const TInt bytesbetween =
77 reinterpret_cast<const TUint8*>(iBottom->Succ()) -
78 reinterpret_cast<const TUint8*>(iTop);
79 const TInt topsize = sizeof(TNode);
80 if(bytesbetween > 0) //bytesbetween is room between bottom and top
81 { //therefore free room is subracted from free space
83 const TInt room = C - bytesbetween - topsize;
84 return room;
86 if(bytesbetween == 0)
89 if(Size() > 0)
90 return 0;
91 else
92 return C - topsize;
94 const TInt room = -bytesbetween - topsize; //free is space between pointers
95 return room;
98 template <TInt C>
99 TInt TVectorBuffer<C>::GetRoom(TInt aSize) const
101 const TInt bytesnew = sizeof(TNode) + aSize;
102 const TInt room = Unreserved() - bytesnew;
103 return room;
106 template <TInt C>
107 TInt TVectorBuffer<C>::Append(const TDesC8& aData)
109 const TInt len = aData.Length();
110 if(GetRoom(len) < 0)
112 return KErrOverflow;
114 if(iBottom->Succ()->Ptr() - iBuffer > (C - (len + TInt(sizeof(TNode)))))
117 TNode* p = TNode::Empty(iBuffer);
118 iBottom->Terminator(p);
119 iBottom = p;
120 return Append(aData);
124 iBottom = TNode::New(iBottom, aData);
126 iSize += len;
127 return KErrNone;
130 template <TInt C>
131 TPtrC8 TVectorBuffer<C>::Shift()
133 __ASSERT_ALWAYS(iTop->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom
134 TNode* node = iTop;
135 iTop = iTop->Succ();
136 if(iTop > node)
138 iSize -= node->Size();
139 return TPtrC8(node->Ptr(), node->Size());
141 else
143 return Shift(); //this happens when buffer is terminated, and data lies in next
147 template <TInt C>
148 TInt TVectorBuffer<C>::Size() const
150 return iSize;
153 template <TInt C>
154 TPtrC8 TVectorBuffer<C>::operator[](TInt aIndex) const
156 TInt index = 0;
157 TNode* t = iTop->Size() > 0 ? iTop : iTop->Succ(); //eliminate terminator
158 while(index < aIndex)
160 TNode* nt = t->Succ();
161 if(nt < t)
163 nt = nt->Succ();
165 t = nt;
166 if(t->Size() > 0)
167 index++;
168 __ASSERT_ALWAYS(t->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom
170 return t->Ptr();
173 //Vector buffer for fixed length data
175 template <class T, TInt C>
176 NONSHARABLE_CLASS(TVector) : public TVectorBuffer<C * sizeof(T)>
178 public:
179 TVector();
180 TInt Append(const T& aData);
181 const T& Shift();
182 TInt Size() const;
183 const T& operator[](TInt aIndex) const;
186 template <class T, TInt C>
187 TVector<T, C>::TVector() : TVectorBuffer<C * sizeof(T)>()
191 template <class T, TInt C>
192 TInt TVector<T, C>::Append(const T& aData)
194 const TPckgC<T> data(aData);
195 return TVectorBuffer<C * sizeof(T)>::Append(data);
198 template <class T, TInt C>
199 const T& TVector<T, C>::Shift()
201 const TPtrC8 ptr = TVectorBuffer<C * sizeof(T)>::Shift();
202 return *(reinterpret_cast<const T*>(ptr.Ptr()));
206 template <class T, TInt C>
207 TInt TVector<T, C>::Size() const
209 return TVectorBuffer<C * sizeof(T)>::Size() / sizeof(T);
212 template <class T, TInt C>
213 const T& TVector<T, C>::operator[](TInt aIndex) const
215 const TPtrC8 ptr = TVectorBuffer<C * sizeof(T)>::operator[](aIndex);
216 return *(reinterpret_cast<const T*>(ptr.Ptr()));
219 #endif