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