2 * Copyright 2001-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
9 * John Scipione, jscipione@gmail.com
13 //! BList class provides storage for pointers. Not thread safe.
25 move_items(void** items
, int32 offset
, int32 count
)
27 if (count
> 0 && offset
!= 0)
28 memmove(items
+ offset
, items
, count
* sizeof(void*));
32 BList::BList(int32 count
)
42 _ResizeArray(fItemCount
);
46 BList::BList(const BList
& other
)
51 fBlockSize(other
.fBlockSize
)
64 BList::operator=(const BList
& other
)
67 fBlockSize
= other
.fBlockSize
;
68 if (_ResizeArray(other
.fItemCount
)) {
69 fItemCount
= other
.fItemCount
;
70 memcpy(fObjectList
, other
.fObjectList
, fItemCount
* sizeof(void*));
79 BList::operator==(const BList
& other
) const
84 if (other
.fItemCount
!= fItemCount
)
88 return memcmp(fObjectList
, other
.fObjectList
,
89 fItemCount
* sizeof(void*)) == 0;
97 BList::operator!=(const BList
& other
) const
99 return !(*this == other
);
104 BList::AddItem(void* item
, int32 index
)
106 if (index
< 0 || index
> fItemCount
)
111 if (fItemCount
+ 1 > fPhysicalSize
)
112 result
= _ResizeArray(fItemCount
+ 1);
115 move_items(fObjectList
+ index
, 1, fItemCount
- index
- 1);
116 fObjectList
[index
] = item
;
123 BList::AddItem(void* item
)
126 if (fPhysicalSize
> fItemCount
) {
127 fObjectList
[fItemCount
] = item
;
130 if ((result
= _ResizeArray(fItemCount
+ 1))) {
131 fObjectList
[fItemCount
] = item
;
140 BList::AddList(const BList
* list
, int32 index
)
142 bool result
= (list
&& index
>= 0 && index
<= fItemCount
);
143 if (result
&& list
->fItemCount
> 0) {
144 int32 count
= list
->fItemCount
;
145 if (fItemCount
+ count
> fPhysicalSize
)
146 result
= _ResizeArray(fItemCount
+ count
);
150 move_items(fObjectList
+ index
, count
, fItemCount
- index
- count
);
151 memcpy(fObjectList
+ index
, list
->fObjectList
,
152 list
->fItemCount
* sizeof(void*));
161 BList::AddList(const BList
* list
)
163 bool result
= (list
!= NULL
);
164 if (result
&& list
->fItemCount
> 0) {
165 int32 index
= fItemCount
;
166 int32 count
= list
->fItemCount
;
167 if (fItemCount
+ count
> fPhysicalSize
)
168 result
= _ResizeArray(fItemCount
+ count
);
172 memcpy(fObjectList
+ index
, list
->fObjectList
,
173 list
->fItemCount
* sizeof(void*));
182 BList::RemoveItem(void* item
)
184 int32 index
= IndexOf(item
);
185 bool result
= (index
>= 0);
193 BList::RemoveItem(int32 index
)
196 if (index
>= 0 && index
< fItemCount
) {
197 item
= fObjectList
[index
];
198 move_items(fObjectList
+ index
+ 1, -1, fItemCount
- index
- 1);
200 if (fItemCount
<= fResizeThreshold
)
201 _ResizeArray(fItemCount
);
208 BList::RemoveItems(int32 index
, int32 count
)
210 bool result
= (index
>= 0 && index
<= fItemCount
);
212 if (index
+ count
> fItemCount
)
213 count
= fItemCount
- index
;
215 move_items(fObjectList
+ index
+ count
, -count
,
216 fItemCount
- index
- count
);
218 if (fItemCount
<= fResizeThreshold
)
219 _ResizeArray(fItemCount
);
228 BList::ReplaceItem(int32 index
, void* item
)
232 if (index
>= 0 && index
< fItemCount
) {
233 fObjectList
[index
] = item
;
248 // #pragma mark - Reordering items.
252 BList::SortItems(int (*compareFunc
)(const void*, const void*))
255 qsort(fObjectList
, fItemCount
, sizeof(void*), compareFunc
);
260 BList::SwapItems(int32 indexA
, int32 indexB
)
264 if (indexA
>= 0 && indexA
< fItemCount
265 && indexB
>= 0 && indexB
< fItemCount
) {
267 void* tmpItem
= fObjectList
[indexA
];
268 fObjectList
[indexA
] = fObjectList
[indexB
];
269 fObjectList
[indexB
] = tmpItem
;
278 /*! This moves a list item from posititon a to position b, moving the
279 appropriate block of list elements to make up for the move. For example,
282 Moveing 1(B)->6(G) would result in this:
286 BList::MoveItem(int32 from
, int32 to
)
288 if ((from
>= fItemCount
) || (to
>= fItemCount
) || (from
< 0) || (to
< 0))
291 void* tmpMover
= fObjectList
[from
];
293 memmove(fObjectList
+ from
, fObjectList
+ from
+ 1,
294 (to
- from
) * sizeof(void*));
295 } else if (from
> to
) {
296 memmove(fObjectList
+ to
+ 1, fObjectList
+ to
,
297 (from
- to
) * sizeof(void*));
299 fObjectList
[to
] = tmpMover
;
305 // #pragma mark - Retrieving items.
309 BList::ItemAt(int32 index
) const
312 if (index
>= 0 && index
< fItemCount
)
313 item
= fObjectList
[index
];
319 BList::FirstItem() const
323 item
= fObjectList
[0];
329 BList::ItemAtFast(int32 index
) const
331 return fObjectList
[index
];
343 BList::LastItem() const
347 item
= fObjectList
[fItemCount
- 1];
352 // #pragma mark - Querying the list.
356 BList::HasItem(void* item
) const
358 return (IndexOf(item
) >= 0);
363 BList::HasItem(const void* item
) const
365 return (IndexOf(item
) >= 0);
370 BList::IndexOf(void* item
) const
372 for (int32 i
= 0; i
< fItemCount
; i
++) {
373 if (fObjectList
[i
] == item
)
381 BList::IndexOf(const void* item
) const
383 for (int32 i
= 0; i
< fItemCount
; i
++) {
384 if (fObjectList
[i
] == item
)
392 BList::CountItems() const
399 BList::IsEmpty() const
401 return fItemCount
== 0;
405 // #pragma mark - Iterating over the list.
407 /*! Iterate a function over the whole list. If the function outputs a true
408 value, then the process is terminated.
411 BList::DoForEach(bool (*func
)(void*))
416 bool terminate
= false;
419 while ((!terminate
) && (index
< fItemCount
)) {
420 terminate
= func(fObjectList
[index
]);
426 /*! Iterate a function over the whole list. If the function outputs a true
427 value, then the process is terminated. This version takes an additional
428 argument which is passed to the function.
431 BList::DoForEach(bool (*func
)(void*, void*), void* arg
)
436 bool terminate
= false; int32 index
= 0;
437 while ((!terminate
) && (index
< fItemCount
)) {
438 terminate
= func(fObjectList
[index
], arg
);
446 // This is somewhat of a hack for backwards compatibility -
447 // the reason these functions are defined this way rather than simply
448 // being made private members is that if they are included, then whenever
449 // gcc encounters someone calling AddList() with a non-const BList pointer,
450 // it will try to use the private version and fail with a compiler error.
452 // obsolete AddList(BList* list, int32 index) and AddList(BList* list)
455 AddList__5BListP5BListl(BList
* self
, BList
* list
, int32 index
)
457 return self
->AddList((const BList
*)list
, index
);
462 AddList__5BListP5BList(BList
* self
, BList
* list
)
464 return self
->AddList((const BList
*)list
);
469 void BList::_ReservedList1() {}
470 void BList::_ReservedList2() {}
473 //! Resizes fObjectList to be large enough to contain count items.
475 BList::_ResizeArray(int32 count
)
478 // calculate the new physical size
479 // by doubling the existing size
480 // until we can hold at least count items
481 int32 newSize
= fPhysicalSize
> 0 ? fPhysicalSize
: fBlockSize
;
482 int32 targetSize
= count
;
484 targetSize
= fBlockSize
;
486 if (targetSize
> fPhysicalSize
) {
487 while (newSize
< targetSize
)
489 } else if (targetSize
<= fResizeThreshold
)
490 newSize
= fResizeThreshold
;
492 // resize if necessary
493 if (newSize
!= fPhysicalSize
) {
495 = (void**)realloc(fObjectList
, newSize
* sizeof(void*));
497 fObjectList
= newObjectList
;
498 fPhysicalSize
= newSize
;
499 // set our lower bound to either 1/4
500 //of the current physical size, or 0
501 fResizeThreshold
= fPhysicalSize
>> 2 >= fBlockSize
502 ? fPhysicalSize
>> 2 : 0;