229 class CBlobT : public Tbase_ { |
229 class CBlobT : public Tbase_ { |
230 // make template arguments public: |
230 // make template arguments public: |
231 public: |
231 public: |
232 typedef Titem_ Titem; |
232 typedef Titem_ Titem; |
233 typedef Tbase_ Tbase; |
233 typedef Tbase_ Tbase; |
|
234 typedef typename Tbase::size_t size_t; |
234 |
235 |
235 static const size_t Titem_size = sizeof(Titem); |
236 static const size_t Titem_size = sizeof(Titem); |
236 |
237 |
237 struct OnTransfer { |
238 struct OnTransfer { |
238 typename Tbase_::CHdr *m_pHdr_1; |
239 typename Tbase_::CHdr *m_pHdr_1; |
239 OnTransfer(OnTransfer& src) : m_pHdr_1(src.m_pHdr_1) {assert(src.m_pHdr_1 != NULL); src.m_pHdr_1 = NULL;} |
240 OnTransfer(const OnTransfer& src) : m_pHdr_1(src.m_pHdr_1) {assert(src.m_pHdr_1 != NULL); *(typename Tbase_::CHdr**)&src.m_pHdr_1 = NULL;} |
240 OnTransfer(CBlobT& src) : m_pHdr_1(src.ptr_u.m_pHdr_1) {src.InitEmpty();} |
241 OnTransfer(CBlobT& src) : m_pHdr_1(src.ptr_u.m_pHdr_1) {src.InitEmpty();} |
241 ~OnTransfer() {assert(m_pHdr_1 == NULL);} |
242 ~OnTransfer() {assert(m_pHdr_1 == NULL);} |
242 }; |
243 }; |
243 |
244 |
244 /** Default constructor - makes new Blob ready to accept any data */ |
245 /** Default constructor - makes new Blob ready to accept any data */ |
245 FORCEINLINE CBlobT() : Tbase() {} |
246 FORCEINLINE CBlobT() : Tbase() {} |
246 /** Constructor - makes new Blob with data */ |
247 /** Constructor - makes new Blob with data */ |
247 FORCEINLINE CBlobT(const Titem_ *p, size_t num_items) : Tbase((int8*)p, num_items * Titem_size) {} |
248 FORCEINLINE CBlobT(const Titem_ *p, size_t num_items) : Tbase((int8*)p, num_items * Titem_size) {} |
248 /** Copy constructor - make new blob to become copy of the original (source) blob */ |
249 /** Copy constructor - make new blob to become copy of the original (source) blob */ |
249 FORCEINLINE CBlobT(const Tbase& src) : Tbase(src) {assert((RawSize() % Titem_size) == 0);} |
250 FORCEINLINE CBlobT(const Tbase& src) : Tbase(src) {assert((Tbase::RawSize() % Titem_size) == 0);} |
250 /** Take ownership constructor */ |
251 /** Take ownership constructor */ |
251 FORCEINLINE CBlobT(OnTransfer& ot) : Tbase(ot.m_pHdr_1) {} |
252 FORCEINLINE CBlobT(const OnTransfer& ot) : Tbase(ot.m_pHdr_1) {} |
252 /** Destructor - ensures that allocated memory (if any) is freed */ |
253 /** Destructor - ensures that allocated memory (if any) is freed */ |
253 FORCEINLINE ~CBlobT() { Free(); } |
254 FORCEINLINE ~CBlobT() { Free(); } |
254 /** Check the validity of item index (only in debug mode) */ |
255 /** Check the validity of item index (only in debug mode) */ |
255 FORCEINLINE void CheckIdx(size_t idx) { assert(idx >= 0); assert(idx < Size()); } |
256 FORCEINLINE void CheckIdx(size_t idx) { assert(idx >= 0); assert(idx < Size()); } |
256 /** Return posize_ter to the first data item - non-const version */ |
257 /** Return posize_ter to the first data item - non-const version */ |
257 FORCEINLINE Titem* Data() { return (Titem*)RawData(); } |
258 FORCEINLINE Titem* Data() { return (Titem*)Tbase::RawData(); } |
258 /** Return posize_ter to the first data item - const version */ |
259 /** Return posize_ter to the first data item - const version */ |
259 FORCEINLINE const Titem* Data() const { return (const Titem*)RawData(); } |
260 FORCEINLINE const Titem* Data() const { return (const Titem*)Tbase::RawData(); } |
260 /** Return posize_ter to the idx-th data item - non-const version */ |
261 /** Return posize_ter to the idx-th data item - non-const version */ |
261 FORCEINLINE Titem* Data(size_t idx) { CheckIdx(idx); return (Data() + idx); } |
262 FORCEINLINE Titem* Data(size_t idx) { CheckIdx(idx); return (Data() + idx); } |
262 /** Return posize_ter to the idx-th data item - const version */ |
263 /** Return posize_ter to the idx-th data item - const version */ |
263 FORCEINLINE const Titem* Data(size_t idx) const { CheckIdx(idx); return (Data() + idx); } |
264 FORCEINLINE const Titem* Data(size_t idx) const { CheckIdx(idx); return (Data() + idx); } |
264 /** Return number of items in the Blob */ |
265 /** Return number of items in the Blob */ |
265 FORCEINLINE size_t Size() const { return (RawSize() / Titem_size); } |
266 FORCEINLINE size_t Size() const { return (Tbase::RawSize() / Titem_size); } |
266 /** Return total number of items that can fit in the Blob without buffer reallocation */ |
267 /** Return total number of items that can fit in the Blob without buffer reallocation */ |
267 FORCEINLINE size_t MaxSize() const { return (MaxRawSize() / Titem_size); } |
268 FORCEINLINE size_t MaxSize() const { return (Tbase::MaxRawSize() / Titem_size); } |
268 /** Return number of additional items that can fit in the Blob without buffer reallocation */ |
269 /** Return number of additional items that can fit in the Blob without buffer reallocation */ |
269 FORCEINLINE size_t GetReserve() const { return ((MaxRawSize() - RawSize()) / Titem_size); } |
270 FORCEINLINE size_t GetReserve() const { return ((Tbase::MaxRawSize() - Tbase::RawSize()) / Titem_size); } |
270 /** Free the memory occupied by Blob destroying all items */ |
271 /** Free the memory occupied by Blob destroying all items */ |
271 FORCEINLINE void Free() |
272 FORCEINLINE void Free() |
272 { |
273 { |
273 assert((RawSize() % Titem_size) == 0); |
274 assert((Tbase::RawSize() % Titem_size) == 0); |
274 size_t old_size = Size(); |
275 size_t old_size = Size(); |
275 if (old_size > 0) { |
276 if (old_size > 0) { |
276 // destroy removed items; |
277 // destroy removed items; |
277 Titem* pI_last_to_destroy = Data(0); |
278 Titem* pI_last_to_destroy = Data(0); |
278 for (Titem* pI = Data(old_size - 1); pI >= pI_last_to_destroy; pI--) pI->~Titem_(); |
279 for (Titem* pI = Data(old_size - 1); pI >= pI_last_to_destroy; pI--) pI->~Titem_(); |
279 } |
280 } |
280 Tbase::Free(); |
281 Tbase::Free(); |
281 } |
282 } |
282 /** Grow number of data items in Blob by given number - doesn't construct items */ |
283 /** Grow number of data items in Blob by given number - doesn't construct items */ |
283 FORCEINLINE Titem* GrowSizeNC(size_t num_items) { return (Titem*)GrowRawSize(num_items * Titem_size); } |
284 FORCEINLINE Titem* GrowSizeNC(size_t num_items) { return (Titem*)Tbase::GrowRawSize(num_items * Titem_size); } |
284 /** Grow number of data items in Blob by given number - constructs new items (using Titem_'s default constructor) */ |
285 /** Grow number of data items in Blob by given number - constructs new items (using Titem_'s default constructor) */ |
285 FORCEINLINE Titem* GrowSizeC(size_t num_items) |
286 FORCEINLINE Titem* GrowSizeC(size_t num_items) |
286 { |
287 { |
287 Titem* pI = GrowSizeNC(num_items); |
288 Titem* pI = GrowSizeNC(num_items); |
288 for (size_t i = num_items; i > 0; i--, pI++) new (pI) Titem(); |
289 for (size_t i = num_items; i > 0; i--, pI++) new (pI) Titem(); |
289 } |
290 } |
290 /** Destroy given number of items and reduce the Blob's data size */ |
291 /** Destroy given number of items and reduce the Blob's data size */ |
291 FORCEINLINE void ReduceSize(size_t num_items) |
292 FORCEINLINE void ReduceSize(size_t num_items) |
292 { |
293 { |
293 assert((RawSize() % Titem_size) == 0); |
294 assert((Tbase::RawSize() % Titem_size) == 0); |
294 size_t old_size = Size(); |
295 size_t old_size = Size(); |
295 assert(num_items <= old_size); |
296 assert(num_items <= old_size); |
296 size_t new_size = (num_items <= old_size) ? (old_size - num_items) : 0; |
297 size_t new_size = (num_items <= old_size) ? (old_size - num_items) : 0; |
297 // destroy removed items; |
298 // destroy removed items; |
298 Titem* pI_last_to_destroy = Data(new_size); |
299 Titem* pI_last_to_destroy = Data(new_size); |
299 for (Titem* pI = Data(old_size - 1); pI >= pI_last_to_destroy; pI--) pI->~Titem(); |
300 for (Titem* pI = Data(old_size - 1); pI >= pI_last_to_destroy; pI--) pI->~Titem(); |
300 // remove them |
301 // remove them |
301 ReduceRawSize(num_items * Titem_size); |
302 Tbase::ReduceRawSize(num_items * Titem_size); |
302 } |
303 } |
303 /** Append one data item at the end (calls Titem_'s default constructor) */ |
304 /** Append one data item at the end (calls Titem_'s default constructor) */ |
304 FORCEINLINE Titem* AppendNew() |
305 FORCEINLINE Titem* AppendNew() |
305 { |
306 { |
306 Titem& dst = *GrowSizeNC(1); // Grow size by one item |
307 Titem& dst = *GrowSizeNC(1); // Grow size by one item |