repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / haikudepot / List.h
blob3c2ce085113bb029a29c40b3a00d27affd246c2d
1 /*
2 * Copyright 2009-2013, Stephan Aßmus <superstippi@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5 #ifndef LIST_H
6 #define LIST_H
9 #include <new>
10 #include <stdlib.h>
11 #include <string.h>
13 #include <SupportDefs.h>
16 template <typename ItemType, bool PlainOldData, uint32 BlockSize = 8>
17 class List {
18 typedef List<ItemType, PlainOldData, BlockSize> SelfType;
19 public:
20 List()
22 fItems(NULL),
23 fCount(0),
24 fAllocatedCount(0)
28 List(const SelfType& other)
30 fItems(NULL),
31 fCount(0),
32 fAllocatedCount(0)
34 *this = other;
37 virtual ~List()
39 if (!PlainOldData) {
40 // Make sure to call destructors of old objects.
41 _Resize(0);
43 free(fItems);
46 SelfType& operator=(const SelfType& other)
48 if (this == &other)
49 return *this;
51 if (PlainOldData) {
52 if (_Resize(other.fCount))
53 memcpy(fItems, other.fItems, fCount * sizeof(ItemType));
54 } else {
55 // Make sure to call destructors of old objects.
56 // NOTE: Another option would be to use
57 // ItemType::operator=(const ItemType& other), but then
58 // we would need to be carefull which objects are already
59 // initialized. Also ItemType would be required to implement the
60 // operator, while doing it this way requires only a copy
61 // constructor.
62 _Resize(0);
63 for (uint32 i = 0; i < other.fCount; i++) {
64 if (!Add(other.ItemAtFast(i)))
65 break;
68 return *this;
71 bool operator==(const SelfType& other) const
73 if (this == &other)
74 return true;
76 if (fCount != other.fCount)
77 return false;
78 if (fCount == 0)
79 return true;
81 if (PlainOldData) {
82 return memcmp(fItems, other.fItems,
83 fCount * sizeof(ItemType)) == 0;
84 } else {
85 for (uint32 i = 0; i < other.fCount; i++) {
86 if (ItemAtFast(i) != other.ItemAtFast(i))
87 return false;
90 return true;
93 bool operator!=(const SelfType& other) const
95 return !(*this == other);
98 inline void Clear()
100 _Resize(0);
103 inline bool IsEmpty() const
105 return fCount == 0;
108 inline int32 CountItems() const
110 return fCount;
113 inline bool Add(const ItemType& copyFrom)
115 if (_Resize(fCount + 1)) {
116 ItemType* item = fItems + fCount - 1;
117 // Initialize the new object from the original.
118 if (!PlainOldData)
119 new (item) ItemType(copyFrom);
120 else
121 *item = copyFrom;
122 return true;
124 return false;
127 inline bool Add(const ItemType& copyFrom, int32 index)
129 if (index < 0 || index > (int32)fCount)
130 return false;
132 if (!_Resize(fCount + 1))
133 return false;
135 int32 nextIndex = index + 1;
136 if ((int32)fCount > nextIndex)
137 memmove(fItems + nextIndex, fItems + index,
138 (fCount - nextIndex) * sizeof(ItemType));
140 ItemType* item = fItems + index;
141 if (!PlainOldData)
142 new (item) ItemType(copyFrom);
143 else
144 *item = copyFrom;
146 return true;
149 inline bool Remove()
151 if (fCount > 0) {
152 _Resize(fCount - 1);
153 return true;
155 return false;
158 inline bool Remove(int32 index)
160 if (index < 0 || index >= (int32)fCount)
161 return false;
163 if (!PlainOldData) {
164 ItemType* object = fItems + index;
165 object->~ItemType();
168 int32 nextIndex = index + 1;
169 if ((int32)fCount > nextIndex) {
170 memcpy(fItems + index, fItems + nextIndex,
171 (fCount - nextIndex) * sizeof(ItemType));
174 fCount--;
175 return true;
178 inline bool Remove(const ItemType& item)
180 return Remove(IndexOf(item));
183 inline bool Replace(int32 index, const ItemType& copyFrom)
185 if (index < 0 || index >= (int32)fCount)
186 return false;
188 ItemType* item = fItems + index;
189 // Initialize the new object from the original.
190 if (!PlainOldData) {
191 item->~ItemType();
192 new (item) ItemType(copyFrom);
193 } else
194 *item = copyFrom;
195 return true;
198 inline const ItemType& ItemAt(int32 index) const
200 if (index < 0 || index >= (int32)fCount)
201 return fNullItem;
202 return ItemAtFast(index);
205 inline const ItemType& ItemAtFast(int32 index) const
207 return *(fItems + index);
210 inline const ItemType& LastItem() const
212 if (fCount == 0)
213 return fNullItem;
214 return ItemAt((int32)fCount - 1);
217 inline int32 IndexOf(const ItemType& item) const
219 for (uint32 i = 0; i < fCount; i++) {
220 if (ItemAtFast(i) == item)
221 return i;
223 return -1;
226 inline bool Contains(const ItemType& item) const
228 return IndexOf(item) >= 0;
231 private:
232 inline bool _Resize(uint32 count)
234 if (count > fAllocatedCount) {
235 uint32 allocationCount = (count + BlockSize - 1)
236 / BlockSize * BlockSize;
237 ItemType* items = reinterpret_cast<ItemType*>(
238 realloc(fItems, allocationCount * sizeof(ItemType)));
239 if (items == NULL)
240 return false;
241 fItems = items;
243 fAllocatedCount = allocationCount;
244 } else if (count < fCount) {
245 if (!PlainOldData) {
246 // Uninit old objects so that we can re-use them when
247 // appending objects without the need to re-allocate.
248 for (uint32 i = count; i < fCount; i++) {
249 ItemType* object = fItems + i;
250 object->~ItemType();
254 fCount = count;
255 return true;
258 ItemType* fItems;
259 ItemType fNullItem;
260 uint32 fCount;
261 uint32 fAllocatedCount;
265 #endif // LIST_H