3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
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:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
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.
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
35 #include <SupportDefs.h>
37 template<typename ITEM
>
38 class DefaultDefaultItemCreator
{
40 static inline ITEM
GetItem() { return ITEM(0); }
45 \brief A generic list implementation.
47 template<typename ITEM
,
48 typename DEFAULT_ITEM_SUPPLIER
= DefaultDefaultItemCreator
<ITEM
> >
55 static item_t sDefaultItem
;
56 static const size_t kDefaultChunkSize
= 10;
57 static const size_t kMaximalChunkSize
= 1024 * 1024;
60 List(size_t chunkSize
= kDefaultChunkSize
);
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
);
80 int32
CountItems() 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;
89 int32
GetCapacity() const { return fCapacity
; }
92 inline static void _MoveItems(item_t
* items
, int32 offset
, int32 count
);
93 bool _Resize(size_t count
);
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());
109 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
110 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::List(size_t chunkSize
)
112 fChunkSize(chunkSize
),
116 if (fChunkSize
== 0 || fChunkSize
> kMaximalChunkSize
)
117 fChunkSize
= kDefaultChunkSize
;
122 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
123 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::~List()
130 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
132 const typename List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::item_t
&
133 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::GetDefaultItem() const
139 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
141 typename List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::item_t
&
142 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::GetDefaultItem()
148 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
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
));
158 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
160 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::AddItem(const item_t
&item
, int32 index
)
162 bool result
= (index
>= 0 && index
<= fItemCount
163 && _Resize(fItemCount
+ 1));
165 _MoveItems(fItems
+ index
, 1, fItemCount
- index
- 1);
166 new(fItems
+ index
) item_t(item
);
172 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
174 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::AddItem(const item_t
&item
)
177 if ((int32
)fCapacity
> fItemCount
) {
178 new(fItems
+ fItemCount
) item_t(item
);
181 if ((result
= _Resize(fItemCount
+ 1)))
182 new(fItems
+ (fItemCount
- 1)) item_t(item
);
187 // These don't use the copy constructor!
190 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
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);
199 _MoveItems(fItems + index, count, fItemCount - index - count);
200 memcpy(fItems + index, list->fItems,
201 list->fItemCount * sizeof(item_t));
208 template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
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);
218 memcpy(fItems + index, list->fItems,
219 list->fItemCount * sizeof(item_t));
227 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
229 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::RemoveItem(const item_t
&item
)
231 int32 index
= IndexOf(item
);
232 bool result
= (index
>= 0);
239 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
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);
253 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
255 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::ReplaceItem(int32 index
, const item_t
&item
)
257 if (index
>= 0 && index
< fItemCount
) {
258 fItems
[index
] = item
;
265 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
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
;
286 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
288 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::MakeEmpty()
290 for (int32 i
= 0; i
< fItemCount
; i
++)
296 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
298 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::CountItems() const
304 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
306 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::IsEmpty() const
308 return (fItemCount
== 0);
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
];
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
];
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
340 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
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
)
352 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
354 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::HasItem(const item_t
&item
) const
356 return (IndexOf(item
) >= 0);
360 template<typename ITEM
, typename DEFAULT_ITEM_SUPPLIER
>
362 List
<ITEM
, DEFAULT_ITEM_SUPPLIER
>::_Resize(size_t count
)
365 // calculate the new capacity
366 int32 newSize
= count
;
369 newSize
= ((newSize
- 1) / fChunkSize
+ 1) * fChunkSize
;
370 // resize if necessary
371 if ((size_t)newSize
!= fCapacity
) {
373 = (item_t
*)realloc(fItems
, newSize
* sizeof(item_t
));