yapf/fixedsizearray.hpp
changeset 3900 4984308f9125
child 4549 60410aa1aa88
equal deleted inserted replaced
3899:4c5b1de6cb17 3900:4984308f9125
       
     1 /* $Id$ */
       
     2 
       
     3 #ifndef  FIXEDSIZEARRAY_HPP
       
     4 #define  FIXEDSIZEARRAY_HPP
       
     5 
       
     6 
       
     7 /** fixed size array
       
     8     Upon construction it preallocates fixed size block of memory
       
     9 		for all items, but doesn't construct them. Item's construction
       
    10 		is delayed. */
       
    11 template <class Titem_, int Tcapacity_>
       
    12 struct CFixedSizeArrayT {
       
    13 	/** the only member of fixed size array is pointer to the block
       
    14 	    of C array of items. Header can be found on the offset -sizeof(CHdr). */
       
    15 	Titem_ *m_items;
       
    16 
       
    17 	/** header for fixed size array */
       
    18 	struct CHdr
       
    19 	{
       
    20 		int    m_num_items; ///< number of items in the array
       
    21 		int    m_ref_cnt;   ///< block reference counter (used by copy constructor and by destructor)
       
    22 	};
       
    23 
       
    24 	// make types and constants visible from outside
       
    25 	typedef Titem_ Titem; // type of array item
       
    26 
       
    27 	ST_CONST(int, Tcapacity = Tcapacity_); // the array capacity (maximum size)
       
    28 	ST_CONST(int, TitemSize = sizeof(Titem_)); // size of item
       
    29 	ST_CONST(int, ThdrSize  = sizeof(CHdr)); // size of header
       
    30 
       
    31 	/** Default constructor. Preallocate space for items and header, then initialize header. */
       
    32 	CFixedSizeArrayT()
       
    33 	{
       
    34 		// allocate block for header + items (don't construct items)
       
    35 		m_items = (Titem*)(((int8*)malloc(ThdrSize + Tcapacity * sizeof(Titem))) + ThdrSize);
       
    36 		SizeRef() = 0; // initial number of items
       
    37 		RefCnt() = 1; // initial reference counter
       
    38 	}
       
    39 
       
    40 	/** Copy constructor. Preallocate space for items and header, then initialize header. */
       
    41 	CFixedSizeArrayT(const CFixedSizeArrayT<Titem_, Tcapacity_>& src)
       
    42 	{
       
    43 		// share block (header + items) with the source array
       
    44 		m_items = const_cast<Titem*>(src.m_items); // here we break the 'const' modifier
       
    45 		RefCnt()++; // now we share block with the source
       
    46 	}
       
    47 
       
    48 	/** destroy remaining items and free the memory block */
       
    49 	~CFixedSizeArrayT()
       
    50 	{
       
    51 		// release one reference to the shared block
       
    52 		if ((--RefCnt()) > 0) return; // and return if there is still some owner
       
    53 
       
    54 		// walk through all allocated items backward and destroy them
       
    55 		for (Titem* pItem = &m_items[Size() - 1]; pItem >= m_items; pItem--) {
       
    56 			pItem->~Titem_();
       
    57 		}
       
    58 		free(((int8*)m_items) - ThdrSize);
       
    59 		m_items = NULL;
       
    60 	}
       
    61 
       
    62 protected:
       
    63 	/** return reference to the array header (non-const) */
       
    64 	FORCEINLINE CHdr& Hdr() { return *(CHdr*)(((int8*)m_items) - ThdrSize); }
       
    65 	/** return reference to the array header (const) */
       
    66 	FORCEINLINE const CHdr& Hdr() const { return *(CHdr*)(((int8*)m_items) - ThdrSize); }
       
    67 	/** return reference to the block reference counter */
       
    68 	FORCEINLINE int& RefCnt() { return Hdr().m_ref_cnt; }
       
    69 	/** return reference to number of used items */
       
    70 	FORCEINLINE int& SizeRef() { return Hdr().m_num_items; }
       
    71 public:
       
    72 	/** return number of used items */
       
    73 	FORCEINLINE int Size() const { return Hdr().m_num_items; }
       
    74 	/** return true if array is full */
       
    75 	FORCEINLINE bool IsFull() const { return Size() >= Tcapacity; };
       
    76 	/** return true if array is empty */
       
    77 	FORCEINLINE bool IsEmpty() const { return Size() <= 0; };
       
    78 	/** index validation */
       
    79 	FORCEINLINE void CheckIdx(int idx) const { assert(idx >= 0); assert(idx < Size()); }
       
    80 	/** add (allocate), but don't construct item */
       
    81 	FORCEINLINE Titem& AddNC() { assert(!IsFull()); return m_items[SizeRef()++]; }
       
    82 	/** add and construct item using default constructor */
       
    83 	FORCEINLINE Titem& Add() { Titem& item = AddNC(); new(&item)Titem; return item; }
       
    84 	/** return item by index (non-const version) */
       
    85 	FORCEINLINE Titem& operator [] (int idx) { CheckIdx(idx); return m_items[idx]; }
       
    86 	/** return item by index (const version) */
       
    87 	FORCEINLINE const Titem& operator [] (int idx) const { CheckIdx(idx); return m_items[idx]; }
       
    88 };
       
    89 
       
    90 #endif /* FIXEDSIZEARRAY_HPP */