SDL-1.2.14
[sdl_omap.git] / src / main / symbian / EKA2 / vectorbuffer.h
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