OpenTTD
fixedsizearray.hpp
Go to the documentation of this file.
1 /* $Id: fixedsizearray.hpp 23640 2011-12-20 17:57:56Z truebrain $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #ifndef FIXEDSIZEARRAY_HPP
13 #define FIXEDSIZEARRAY_HPP
14 
15 #include "../core/alloc_func.hpp"
16 
23 template <class T, uint C>
25 protected:
27  struct ArrayHeader
28  {
29  uint items;
31  };
32 
33  /* make constants visible from outside */
34  static const uint Tsize = sizeof(T);
35  static const uint HeaderSize = sizeof(ArrayHeader);
36 
41  T *data;
42 
44  inline ArrayHeader& Hdr() { return *(ArrayHeader*)(((byte*)data) - HeaderSize); }
46  inline const ArrayHeader& Hdr() const { return *(ArrayHeader*)(((byte*)data) - HeaderSize); }
48  inline uint& RefCnt() { return Hdr().reference_count; }
50  inline uint& SizeRef() { return Hdr().items; }
51 
52 public:
55  {
56  /* Ensure the size won't overflow. */
57  assert_compile(C < (SIZE_MAX - HeaderSize) / Tsize);
58 
59  /* allocate block for header + items (don't construct items) */
60  data = (T*)((MallocT<byte>(HeaderSize + C * Tsize)) + HeaderSize);
61  SizeRef() = 0; // initial number of items
62  RefCnt() = 1; // initial reference counter
63  }
64 
67  {
68  /* share block (header + items) with the source array */
69  data = src.data;
70  RefCnt()++; // now we share block with the source
71  }
72 
75  {
76  /* release one reference to the shared block */
77  if ((--RefCnt()) > 0) return; // and return if there is still some owner
78 
79  Clear();
80  /* free the memory block occupied by items */
81  free(((byte*)data) - HeaderSize);
82  data = NULL;
83  }
84 
86  inline void Clear()
87  {
88  /* Walk through all allocated items backward and destroy them
89  * Note: this->Length() can be zero. In that case data[this->Length() - 1] is evaluated unsigned
90  * on some compilers with some architectures. (e.g. gcc with x86) */
91  for (T *pItem = this->data + this->Length() - 1; pItem >= this->data; pItem--) {
92  pItem->~T();
93  }
94  /* number of items become zero */
95  SizeRef() = 0;
96  }
97 
99  inline uint Length() const { return Hdr().items; }
101  inline bool IsFull() const { return Length() >= C; }
103  inline bool IsEmpty() const { return Length() <= 0; }
105  inline T *Append() { assert(!IsFull()); return &data[SizeRef()++]; }
107  inline T *AppendC() { T *item = Append(); new(item)T; return item; }
109  inline T& operator [] (uint index) { assert(index < Length()); return data[index]; }
111  inline const T& operator [] (uint index) const { assert(index < Length()); return data[index]; }
112 };
113 
114 #endif /* FIXEDSIZEARRAY_HPP */