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
241