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