3 yet another circle buffer
8 #ifndef __VECTORBUFFER_H__
9 #define __VECTORBUFFER_H__
12 #define VECPANIC(x) VectorPanic(x, __LINE__)
13 void VectorPanic(TInt
, TInt
);
18 NONSHARABLE_CLASS(TNodeBuffer
)
22 NONSHARABLE_CLASS(TNode
)
25 static TNode
* Empty(TUint8
* iBuffer
);
26 static TNode
* New(TNode
* aPrev
, const TDesC8
& aData
);
27 const TUint8
* Ptr() const;
30 static void SetSucc(TNode
*& aNode
);
31 void Terminator(TNode
* aNode
);
37 inline TNodeBuffer::TNode
* TNodeBuffer::TNode::Succ()
43 //Vector buffer for variable length data
46 NONSHARABLE_CLASS(TVectorBuffer
) : public TNodeBuffer
50 TInt
Append(const TDesC8
& aData
);
52 TPtrC8
operator[](TInt aIndex
) const;
55 TInt
GetRoom(TInt aSize
) const;
56 TInt
Unreserved() const;
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
);
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
;
94 const TInt room
= -bytesbetween
- topsize
; //free is space between pointers
99 TInt TVectorBuffer
<C
>::GetRoom(TInt aSize
) const
101 const TInt bytesnew
= sizeof(TNode
) + aSize
;
102 const TInt room
= Unreserved() - bytesnew
;
107 TInt TVectorBuffer
<C
>::Append(const TDesC8
& aData
)
109 const TInt len
= aData
.Length();
114 if(iBottom
->Succ()->Ptr() - iBuffer
> (C
- (len
+ TInt(sizeof(TNode
)))))
117 TNode
* p
= TNode::Empty(iBuffer
);
118 iBottom
->Terminator(p
);
120 return Append(aData
);
124 iBottom
= TNode::New(iBottom
, aData
);
131 TPtrC8 TVectorBuffer
<C
>::Shift()
133 __ASSERT_ALWAYS(iTop
->Succ() != NULL
, VECPANIC(KErrUnderflow
)); //can never pass-by bottom
138 iSize
-= node
->Size();
139 return TPtrC8(node
->Ptr(), node
->Size());
143 return Shift(); //this happens when buffer is terminated, and data lies in next
148 TInt TVectorBuffer
<C
>::Size() const
154 TPtrC8 TVectorBuffer
<C
>::operator[](TInt aIndex
) const
157 TNode
* t
= iTop
->Size() > 0 ? iTop
: iTop
->Succ(); //eliminate terminator
158 while(index
< aIndex
)
160 TNode
* nt
= t
->Succ();
168 __ASSERT_ALWAYS(t
->Succ() != NULL
, VECPANIC(KErrUnderflow
)); //can never pass-by bottom
173 //Vector buffer for fixed length data
175 template <class T
, TInt C
>
176 NONSHARABLE_CLASS(TVector
) : public TVectorBuffer
<C
* sizeof(T
)>
180 TInt
Append(const T
& aData
);
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()));