# fixedsizearray.hpp

Go to the documentation of this file.

    00001 /* $Id: fixedsizearray.hpp 17248 2009-08-21 20:21:05Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #ifndef  FIXEDSIZEARRAY_HPP
    00013 #define  FIXEDSIZEARRAY_HPP
    00014
    00015
    00020 template <class Titem_, int Tcapacity_>
    00021 struct CFixedSizeArrayT {
    00024   Titem_ *m_items;
    00025
    00027   struct CHdr
    00028   {
    00029     int    m_num_items;
    00030     int    m_ref_cnt;
    00031   };
    00032
    00033   /* make types and constants visible from outside */
    00034   typedef Titem_ Titem; // type of array item
    00035
    00036   static const int Tcapacity = Tcapacity_;     // the array capacity (maximum size)
    00037   static const int TitemSize = sizeof(Titem_); // size of item
    00038   static const int ThdrSize  = sizeof(CHdr);   // size of header
    00039
    00041   CFixedSizeArrayT()
    00042   {
    00043     /* allocate block for header + items (don't construct items) */
    00044     m_items = (Titem*)((MallocT<int8>(ThdrSize + Tcapacity * sizeof(Titem))) + ThdrSize);
    00045     SizeRef() = 0; // initial number of items
    00046     RefCnt() = 1; // initial reference counter
    00047   }
    00048
    00050   CFixedSizeArrayT(const CFixedSizeArrayT<Titem_, Tcapacity_>& src)
    00051   {
    00052     /* share block (header + items) with the source array */
    00053     m_items = src.m_items;
    00054     RefCnt()++; // now we share block with the source
    00055   }
    00056
    00058   ~CFixedSizeArrayT()
    00059   {
    00060     /* release one reference to the shared block */
    00061     if ((--RefCnt()) > 0) return; // and return if there is still some owner
    00062
    00063     Clear();
    00064     /* free the memory block occupied by items */
    00065     free(((int8*)m_items) - ThdrSize);
    00066     m_items = NULL;
    00067   }
    00068
    00070   FORCEINLINE void Clear()
    00071   {
    00072     /* walk through all allocated items backward and destroy them */
    00073     for (Titem *pItem = &m_items[Size() - 1]; pItem >= m_items; pItem--) {
    00074       pItem->~Titem_();
    00075     }
    00076     /* number of items become zero */
    00077     SizeRef() = 0;
    00078   }
    00079
    00080 protected:
    00082   FORCEINLINE CHdr& Hdr() { return *(CHdr*)(((int8*)m_items) - ThdrSize); }
    00084   FORCEINLINE const CHdr& Hdr() const { return *(CHdr*)(((int8*)m_items) - ThdrSize); }
    00086   FORCEINLINE int& RefCnt() { return Hdr().m_ref_cnt; }
    00088   FORCEINLINE int& SizeRef() { return Hdr().m_num_items; }
    00089 public:
    00091   FORCEINLINE int Size() const { return Hdr().m_num_items; }
    00093   FORCEINLINE bool IsFull() const { return Size() >= Tcapacity; };
    00095   FORCEINLINE bool IsEmpty() const { return Size() <= 0; };
    00097   FORCEINLINE void CheckIdx(int idx) const { assert(idx >= 0); assert(idx < Size()); }
    00099   FORCEINLINE Titem& AddNC() { assert(!IsFull()); return m_items[SizeRef()++]; }
    00101   FORCEINLINE Titem& Add() { Titem& item = AddNC(); new(&item)Titem; return item; }
    00103   FORCEINLINE Titem& operator [] (int idx) { CheckIdx(idx); return m_items[idx]; }
    00105   FORCEINLINE const Titem& operator [] (int idx) const { CheckIdx(idx); return m_items[idx]; }
    00106 };
    00107
    00108 #endif /* FIXEDSIZEARRAY_HPP */