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 241