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 */