SDL-1.2.14
[sdl_omap.git] / src / main / symbian / EKA2 / vectorbuffer.h
CommitLineData
e14743d1 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__)
14void VectorPanic(TInt, TInt);
15
16
17//int DEBUG_INT;
18
19NONSHARABLE_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
38inline TNodeBuffer::TNode* TNodeBuffer::TNode::Succ()
39 {
40 return iSucc;
41 }
42
43template <TInt C>
44NONSHARABLE_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
63template <TInt C>
64TVectorBuffer<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
71template<TInt C >
72TInt 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
97template <TInt C>
98TInt 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
105template <TInt C>
106TInt 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/*
134template <TInt C>
135TInt 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*/
148template <TInt C>
149TPtrC8 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
167template <TInt C>
168TInt TVectorBuffer<C>::Size() const
169 {
170 return iSize;
171 }
172
173template <TInt C>
174TPtrC8 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
194template <class T, TInt C>
195NONSHARABLE_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
205template <class T, TInt C>
206TVector<T, C>::TVector() : TVectorBuffer<C * sizeof(T)>()
207 {
208 }
209
210template <class T, TInt C>
211TInt TVector<T, C>::Append(const T& aData)
212 {
213 const TPckgC<T> data(aData);
214 return TVectorBuffer<C * sizeof(T)>::Append(data);
215 }
216
217template <class T, TInt C>
218const 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
225template <class T, TInt C>
226TInt TVector<T, C>::Size() const
227 {
228 return TVectorBuffer<C * sizeof(T)>::Size() / sizeof(T);
229 }
230
231template <class T, TInt C>
232const 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