KUDr@5633: /* $Id$ */ KUDr@5633: belugas@6481: /** @file fixedsizearray.hpp */ belugas@6481: KUDr@5633: #ifndef FIXEDSIZEARRAY_HPP KUDr@5633: #define FIXEDSIZEARRAY_HPP KUDr@5633: KUDr@5633: KUDr@5633: /** fixed size array KUDr@5633: * Upon construction it preallocates fixed size block of memory KUDr@5633: * for all items, but doesn't construct them. Item's construction KUDr@5633: * is delayed. */ KUDr@5633: template KUDr@5633: struct CFixedSizeArrayT { KUDr@5633: /** the only member of fixed size array is pointer to the block KUDr@5633: * of C array of items. Header can be found on the offset -sizeof(CHdr). */ KUDr@5633: Titem_ *m_items; KUDr@5633: KUDr@5633: /** header for fixed size array */ KUDr@5633: struct CHdr KUDr@5633: { KUDr@5633: int m_num_items; ///< number of items in the array KUDr@5633: int m_ref_cnt; ///< block reference counter (used by copy constructor and by destructor) KUDr@5633: }; KUDr@5633: KUDr@5633: // make types and constants visible from outside KUDr@5633: typedef Titem_ Titem; // type of array item KUDr@5633: KUDr@5633: static const int Tcapacity = Tcapacity_; // the array capacity (maximum size) KUDr@5633: static const int TitemSize = sizeof(Titem_); // size of item KUDr@5633: static const int ThdrSize = sizeof(CHdr); // size of header KUDr@5633: KUDr@5633: /** Default constructor. Preallocate space for items and header, then initialize header. */ KUDr@5633: CFixedSizeArrayT() KUDr@5633: { KUDr@5633: // allocate block for header + items (don't construct items) rubidium@8037: m_items = (Titem*)((MallocT(ThdrSize + Tcapacity * sizeof(Titem))) + ThdrSize); KUDr@5633: SizeRef() = 0; // initial number of items KUDr@5633: RefCnt() = 1; // initial reference counter KUDr@5633: } KUDr@5633: KUDr@5633: /** Copy constructor. Preallocate space for items and header, then initialize header. */ KUDr@5633: CFixedSizeArrayT(const CFixedSizeArrayT& src) KUDr@5633: { KUDr@5633: // share block (header + items) with the source array KUDr@5633: m_items = src.m_items; KUDr@5633: RefCnt()++; // now we share block with the source KUDr@5633: } KUDr@5633: KUDr@5633: /** destroy remaining items and free the memory block */ KUDr@5633: ~CFixedSizeArrayT() KUDr@5633: { KUDr@5633: // release one reference to the shared block KUDr@5633: if ((--RefCnt()) > 0) return; // and return if there is still some owner KUDr@5633: KUDr@5633: Clear(); KUDr@5633: // free the memory block occupied by items KUDr@5633: free(((int8*)m_items) - ThdrSize); KUDr@5633: m_items = NULL; KUDr@5633: } KUDr@5633: KUDr@5633: /** Clear (destroy) all items */ KUDr@5633: FORCEINLINE void Clear() KUDr@5633: { KUDr@5633: // walk through all allocated items backward and destroy them KUDr@5633: for (Titem* pItem = &m_items[Size() - 1]; pItem >= m_items; pItem--) { KUDr@5633: pItem->~Titem_(); KUDr@5633: } KUDr@5633: // number of items become zero KUDr@5633: SizeRef() = 0; KUDr@5633: } KUDr@5633: KUDr@5633: protected: KUDr@5633: /** return reference to the array header (non-const) */ KUDr@5633: FORCEINLINE CHdr& Hdr() { return *(CHdr*)(((int8*)m_items) - ThdrSize); } KUDr@5633: /** return reference to the array header (const) */ KUDr@5633: FORCEINLINE const CHdr& Hdr() const { return *(CHdr*)(((int8*)m_items) - ThdrSize); } KUDr@5633: /** return reference to the block reference counter */ KUDr@5633: FORCEINLINE int& RefCnt() { return Hdr().m_ref_cnt; } KUDr@5633: /** return reference to number of used items */ KUDr@5633: FORCEINLINE int& SizeRef() { return Hdr().m_num_items; } KUDr@5633: public: KUDr@5633: /** return number of used items */ KUDr@5633: FORCEINLINE int Size() const { return Hdr().m_num_items; } KUDr@5633: /** return true if array is full */ KUDr@5633: FORCEINLINE bool IsFull() const { return Size() >= Tcapacity; }; KUDr@5633: /** return true if array is empty */ KUDr@5633: FORCEINLINE bool IsEmpty() const { return Size() <= 0; }; KUDr@5633: /** index validation */ KUDr@5633: FORCEINLINE void CheckIdx(int idx) const { assert(idx >= 0); assert(idx < Size()); } KUDr@5633: /** add (allocate), but don't construct item */ KUDr@5633: FORCEINLINE Titem& AddNC() { assert(!IsFull()); return m_items[SizeRef()++]; } KUDr@5633: /** add and construct item using default constructor */ KUDr@5633: FORCEINLINE Titem& Add() { Titem& item = AddNC(); new(&item)Titem; return item; } KUDr@5633: /** return item by index (non-const version) */ KUDr@5633: FORCEINLINE Titem& operator [] (int idx) { CheckIdx(idx); return m_items[idx]; } KUDr@5633: /** return item by index (const version) */ KUDr@5633: FORCEINLINE const Titem& operator [] (int idx) const { CheckIdx(idx); return m_items[idx]; } KUDr@5633: }; KUDr@5633: KUDr@5633: #endif /* FIXEDSIZEARRAY_HPP */