BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / file_systems / ramfs / List.h
blob952e0d453d2c67e2ff12c6b36c58a0d2e9c2b1fe
1 // List.h
2 //
3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
22 //
23 // Except as contained in this notice, the name of a copyright holder shall
24 // not be used in advertising or otherwise to promote the sale, use or other
25 // dealings in this Software without prior written authorization of the
26 // copyright holder.
28 #ifndef LIST_H
29 #define LIST_H
31 #include <new>
32 #include <stdlib.h>
33 #include <string.h>
35 #include <SupportDefs.h>
37 template<typename ITEM>
38 class DefaultDefaultItemCreator {
39 public:
40 static inline ITEM GetItem() { return ITEM(0); }
43 /*!
44 \class List
45 \brief A generic list implementation.
47 template<typename ITEM,
48 typename DEFAULT_ITEM_SUPPLIER = DefaultDefaultItemCreator<ITEM> >
49 class List {
50 public:
51 typedef ITEM item_t;
52 typedef List list_t;
54 private:
55 static item_t sDefaultItem;
56 static const size_t kDefaultChunkSize = 10;
57 static const size_t kMaximalChunkSize = 1024 * 1024;
59 public:
60 List(size_t chunkSize = kDefaultChunkSize);
61 ~List();
63 inline const item_t &GetDefaultItem() const;
64 inline item_t &GetDefaultItem();
66 bool AddItem(const item_t &item, int32 index);
67 bool AddItem(const item_t &item);
68 // bool AddList(list_t *list, int32 index);
69 // bool AddList(list_t *list);
71 bool RemoveItem(const item_t &item);
72 bool RemoveItem(int32 index);
74 bool ReplaceItem(int32 index, const item_t &item);
76 bool MoveItem(int32 oldIndex, int32 newIndex);
78 void MakeEmpty();
80 int32 CountItems() const;
81 bool IsEmpty() const;
82 const item_t &ItemAt(int32 index) const;
83 item_t &ItemAt(int32 index);
84 const item_t *Items() const;
85 int32 IndexOf(const item_t &item) const;
86 bool HasItem(const item_t &item) const;
88 // debugging
89 int32 GetCapacity() const { return fCapacity; }
91 private:
92 inline static void _MoveItems(item_t* items, int32 offset, int32 count);
93 bool _Resize(size_t count);
95 private:
96 size_t fCapacity;
97 size_t fChunkSize;
98 int32 fItemCount;
99 item_t *fItems;
102 // sDefaultItem
103 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
104 typename List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t
105 List<ITEM, DEFAULT_ITEM_SUPPLIER>::sDefaultItem(
106 DEFAULT_ITEM_SUPPLIER::GetItem());
108 // constructor
109 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
110 List<ITEM, DEFAULT_ITEM_SUPPLIER>::List(size_t chunkSize)
111 : fCapacity(0),
112 fChunkSize(chunkSize),
113 fItemCount(0),
114 fItems(NULL)
116 if (fChunkSize == 0 || fChunkSize > kMaximalChunkSize)
117 fChunkSize = kDefaultChunkSize;
118 _Resize(0);
121 // destructor
122 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
123 List<ITEM, DEFAULT_ITEM_SUPPLIER>::~List()
125 MakeEmpty();
126 free(fItems);
129 // GetDefaultItem
130 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
131 inline
132 const typename List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t &
133 List<ITEM, DEFAULT_ITEM_SUPPLIER>::GetDefaultItem() const
135 return sDefaultItem;
138 // GetDefaultItem
139 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
140 inline
141 typename List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t &
142 List<ITEM, DEFAULT_ITEM_SUPPLIER>::GetDefaultItem()
144 return sDefaultItem;
147 // _MoveItems
148 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
149 inline
150 void
151 List<ITEM, DEFAULT_ITEM_SUPPLIER>::_MoveItems(item_t* items, int32 offset, int32 count)
153 if (count > 0 && offset != 0)
154 memmove(items + offset, items, count * sizeof(item_t));
157 // AddItem
158 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
159 bool
160 List<ITEM, DEFAULT_ITEM_SUPPLIER>::AddItem(const item_t &item, int32 index)
162 bool result = (index >= 0 && index <= fItemCount
163 && _Resize(fItemCount + 1));
164 if (result) {
165 _MoveItems(fItems + index, 1, fItemCount - index - 1);
166 new(fItems + index) item_t(item);
168 return result;
171 // AddItem
172 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
173 bool
174 List<ITEM, DEFAULT_ITEM_SUPPLIER>::AddItem(const item_t &item)
176 bool result = true;
177 if ((int32)fCapacity > fItemCount) {
178 new(fItems + fItemCount) item_t(item);
179 fItemCount++;
180 } else {
181 if ((result = _Resize(fItemCount + 1)))
182 new(fItems + (fItemCount - 1)) item_t(item);
184 return result;
187 // These don't use the copy constructor!
189 // AddList
190 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
191 bool
192 List<ITEM, DEFAULT_ITEM_SUPPLIER>::AddList(list_t *list, int32 index)
194 bool result = (list && index >= 0 && index <= fItemCount);
195 if (result && list->fItemCount > 0) {
196 int32 count = list->fItemCount;
197 result = _Resize(fItemCount + count);
198 if (result) {
199 _MoveItems(fItems + index, count, fItemCount - index - count);
200 memcpy(fItems + index, list->fItems,
201 list->fItemCount * sizeof(item_t));
204 return result;
207 // AddList
208 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
209 bool
210 List<ITEM, DEFAULT_ITEM_SUPPLIER>::AddList(list_t *list)
212 bool result = (list);
213 if (result && list->fItemCount > 0) {
214 int32 index = fItemCount;
215 int32 count = list->fItemCount;
216 result = _Resize(fItemCount + count);
217 if (result) {
218 memcpy(fItems + index, list->fItems,
219 list->fItemCount * sizeof(item_t));
222 return result;
226 // RemoveItem
227 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
228 bool
229 List<ITEM, DEFAULT_ITEM_SUPPLIER>::RemoveItem(const item_t &item)
231 int32 index = IndexOf(item);
232 bool result = (index >= 0);
233 if (result)
234 RemoveItem(index);
235 return result;
238 // RemoveItem
239 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
240 bool
241 List<ITEM, DEFAULT_ITEM_SUPPLIER>::RemoveItem(int32 index)
243 if (index >= 0 && index < fItemCount) {
244 fItems[index].~item_t();
245 _MoveItems(fItems + index + 1, -1, fItemCount - index - 1);
246 _Resize(fItemCount - 1);
247 return true;
249 return false;
252 // ReplaceItem
253 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
254 bool
255 List<ITEM, DEFAULT_ITEM_SUPPLIER>::ReplaceItem(int32 index, const item_t &item)
257 if (index >= 0 && index < fItemCount) {
258 fItems[index] = item;
259 return true;
261 return false;
264 // MoveItem
265 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
266 bool
267 List<ITEM, DEFAULT_ITEM_SUPPLIER>::MoveItem(int32 oldIndex, int32 newIndex)
269 if (oldIndex >= 0 && oldIndex < fItemCount
270 && newIndex >= 0 && newIndex <= fItemCount) {
271 if (oldIndex < newIndex - 1) {
272 item_t item = fItems[oldIndex];
273 _MoveItems(fItems + oldIndex + 1, -1, newIndex - oldIndex - 1);
274 fItems[newIndex] = item;
275 } else if (oldIndex > newIndex) {
276 item_t item = fItems[oldIndex];
277 _MoveItems(fItems + newIndex, 1, oldIndex - newIndex);
278 fItems[newIndex] = item;
280 return true;
282 return false;
285 // MakeEmpty
286 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
287 void
288 List<ITEM, DEFAULT_ITEM_SUPPLIER>::MakeEmpty()
290 for (int32 i = 0; i < fItemCount; i++)
291 fItems[i].~item_t();
292 _Resize(0);
295 // CountItems
296 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
297 int32
298 List<ITEM, DEFAULT_ITEM_SUPPLIER>::CountItems() const
300 return fItemCount;
303 // IsEmpty
304 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
305 bool
306 List<ITEM, DEFAULT_ITEM_SUPPLIER>::IsEmpty() const
308 return (fItemCount == 0);
311 // ItemAt
312 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
313 const typename List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t &
314 List<ITEM, DEFAULT_ITEM_SUPPLIER>::ItemAt(int32 index) const
316 if (index >= 0 && index < fItemCount)
317 return fItems[index];
318 return sDefaultItem;
321 // ItemAt
322 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
323 typename List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t &
324 List<ITEM, DEFAULT_ITEM_SUPPLIER>::ItemAt(int32 index)
326 if (index >= 0 && index < fItemCount)
327 return fItems[index];
328 return sDefaultItem;
331 // Items
332 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
333 const typename List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t *
334 List<ITEM, DEFAULT_ITEM_SUPPLIER>::Items() const
336 return fItems;
339 // IndexOf
340 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
341 int32
342 List<ITEM, DEFAULT_ITEM_SUPPLIER>::IndexOf(const item_t &item) const
344 for (int32 i = 0; i < fItemCount; i++) {
345 if (fItems[i] == item)
346 return i;
348 return -1;
351 // HasItem
352 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
353 bool
354 List<ITEM, DEFAULT_ITEM_SUPPLIER>::HasItem(const item_t &item) const
356 return (IndexOf(item) >= 0);
359 // _Resize
360 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
361 bool
362 List<ITEM, DEFAULT_ITEM_SUPPLIER>::_Resize(size_t count)
364 bool result = true;
365 // calculate the new capacity
366 int32 newSize = count;
367 if (newSize <= 0)
368 newSize = 1;
369 newSize = ((newSize - 1) / fChunkSize + 1) * fChunkSize;
370 // resize if necessary
371 if ((size_t)newSize != fCapacity) {
372 item_t* newItems
373 = (item_t*)realloc(fItems, newSize * sizeof(item_t));
374 if (newItems) {
375 fItems = newItems;
376 fCapacity = newSize;
377 } else
378 result = false;
380 if (result)
381 fItemCount = count;
382 return result;
385 #endif // LIST_H