3975
|
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
|