xref: /haiku/src/kits/support/PointerList.cpp (revision 3be9edf8da228afd9fec0390f408c964766122aa)
1 /*
2 ** Copyright 2003-2004, Stefano Ceccherini (burton666@libero.it). All rights reserved.
3 **           2004, Michael Pfeiffer (laplace@users.sourceforge.net).
4 ** Distributed under the terms of the Haiku License.
5 **
6 ** History
7 ** 2003-2004  Initial implementation by Stefano Ceccerini.
8 ** 2004/08/03 Testing, bug fixing and implementation of quick sort, refactoring
9 **            by Michael Pfeiffer.
10 */
11 
12 // TODO:
13 //   - Rewrite to use STL
14 //   - Include ObjectList.h
15 //   - Test if building with jam works
16 
17 // Note: Method Owning() is inlined in header file ObjectList.h
18 
19 #include <ObjectList.h>
20 
21 #include <assert.h>
22 
23 #include <algorithm>
24 #include <functional>
25 
26 #include <List.h>
27 
28 
29 using namespace std;
30 
31 
32 // TODO: The implementation of _PointerList_ should be completely rewritten to
33 // use STL in a more efficent way!
34 
35 struct comparator;
36 
37 
38 class AbstractPointerListHelper {
39 public:
40 	AbstractPointerListHelper() {};
41 	virtual ~AbstractPointerListHelper();
42 
43 	/**
44 		Returns the index of the item that matches key or
45 	    a negative number. Then -(index+1) is the insert position
46 	    of the item not in list.
47 	*/
48 	int32 BinarySearchIndex(const void *key, const BList *list);
49 	/**
50 		Returns the item that matches key or NULL if the item could
51 		not be found in the list.
52 	*/
53 	void* BinarySearch(const void *key, const BList *list);
54 	/**
55 		Sorts the items in list.
56 	*/
57 	void SortItems(BList *list);
58 	/**
59 		Removes the first item in list and appends it at the bottom of
60 		the list and sorts all items but the last item.
61 	*/
62 	void HSortItems(BList *list);
63 
64 	friend struct comparator;
65 
66 private:
67 	enum {
68 		// Use insertion sort if number of elements in list is less than
69 		// kQuickSortThreshold.
70 		kQuickSortThreshold = 11,
71 		// Use simple pivot element computation if number of elements in
72 		// list is less than kPivotThreshold.
73 		kPivotThreshold     = 5,
74 	};
75 
76 	// Methods that do the actual work:
77 	inline void Swap(void **items, int32 i, int32 j);
78 
79 	void* BinarySearch(const void *key, const void **items, int32 numItems, int32 &index);
80 	void QuickSort(void **items, int32 low, int32 high);
81 
82 	// Method to be implemented by sub classes
83 	int virtual Compare(const void *key, const void* item) = 0;
84 };
85 
86 struct comparator : public binary_function<const void*, const void*, bool>
87 {
88 	comparator(AbstractPointerListHelper* helper) : helper(helper) {}
89 
90 	bool operator()(const void* a, const void* b) {
91 		return helper->Compare(b, a) > 0;
92 	}
93 
94 	AbstractPointerListHelper* helper;
95 };
96 
97 
98 AbstractPointerListHelper::~AbstractPointerListHelper()
99 {
100 }
101 
102 
103 void
104 AbstractPointerListHelper::Swap(void **items, int32 i, int32 j)
105 {
106 	void *swap = items[i];
107 	items[i] = items[j];
108 	items[j] = swap;
109 }
110 
111 
112 int32
113 AbstractPointerListHelper::BinarySearchIndex(const void *key, const BList *list)
114 {
115 	int32 index;
116 	const void **items = static_cast<const void**>(list->Items());
117 	BinarySearch(key, items, list->CountItems(), index);
118 	return index;
119 }
120 
121 
122 void *
123 AbstractPointerListHelper::BinarySearch(const void *key, const BList *list)
124 {
125 	int32 index;
126 	const void **items = static_cast<const void**>(list->Items());
127 	return BinarySearch(key, items, list->CountItems(), index);
128 }
129 
130 
131 void
132 AbstractPointerListHelper::SortItems(BList *list)
133 {
134 	void **items = static_cast<void**>(list->Items());
135 	QuickSort(items, 0, list->CountItems()-1);
136 }
137 
138 
139 void
140 AbstractPointerListHelper::HSortItems(BList *list)
141 {
142 	void **items = static_cast<void**>(list->Items());
143 	int32 numItems = list->CountItems();
144 	if (numItems > 1) {
145 		// swap last with first item
146 		Swap(items, 0, numItems-1);
147 	}
148 	// sort all items but last item
149 	QuickSort(items, 0, numItems-2);
150 }
151 
152 
153 void *
154 AbstractPointerListHelper::BinarySearch(const void *key, const void **items, int32 numItems, int32 &index)
155 {
156 	const void** end = &items[numItems];
157 	const void** found = lower_bound(items, end, key, comparator(this));
158 	index = found - items;
159 	if (index != numItems && Compare(key, *found) == 0) {
160 		return const_cast<void*>(*found);
161 	} else {
162 		index = -(index + 1);
163 		return NULL;
164 	}
165 }
166 
167 
168 void
169 AbstractPointerListHelper::QuickSort(void **items, int32 low, int32 high)
170 {
171 	if (low <= high) {
172 		sort(&items[low], &items[high+1], comparator(this));
173 	}
174 }
175 
176 
177 class PointerListHelper : public AbstractPointerListHelper {
178 public:
179 	PointerListHelper(_PointerList_::GenericCompareFunction compareFunc)
180 		: fCompareFunc(compareFunc)
181 	{
182 		// nothing to do
183 	}
184 
185 	int Compare(const void *a, const void *b)
186 	{
187 		return fCompareFunc(a, b);
188 	}
189 
190 private:
191 	_PointerList_::GenericCompareFunction fCompareFunc;
192 };
193 
194 
195 class PointerListHelperWithState : public AbstractPointerListHelper
196 {
197 public:
198 	PointerListHelperWithState(
199 		_PointerList_::GenericCompareFunctionWithState compareFunc,
200 		void* state)
201 		: fCompareFunc(compareFunc)
202 		, fState(state)
203 	{
204 		// nothing to do
205 	}
206 
207 	int Compare(const void *a, const void *b)
208 	{
209 		return fCompareFunc(a, b, fState);
210 	}
211 
212 private:
213 	_PointerList_::GenericCompareFunctionWithState fCompareFunc;
214 	void* fState;
215 };
216 
217 
218 class PointerListHelperUsePredicate : public AbstractPointerListHelper
219 {
220 public:
221 	PointerListHelperUsePredicate(
222 		_PointerList_::UnaryPredicateGlue predicate)
223 		: fPredicate(predicate)
224 	{
225 		// nothing to do
226 	}
227 
228 	int Compare(const void *arg, const void *item)
229 	{
230 		// need to adapt arguments and return value
231 		return -fPredicate(item, const_cast<void *>(arg));
232 	}
233 
234 private:
235 	_PointerList_::UnaryPredicateGlue fPredicate;
236 };
237 
238 
239 // Implementation of class _PointerList_
240 
241 _PointerList_::_PointerList_(int32 itemsPerBlock, bool own)
242 	:
243 	BList(itemsPerBlock),
244 	owning(own)
245 {
246 
247 }
248 
249 
250 _PointerList_::_PointerList_(const _PointerList_ &list)
251 	:
252 	BList(list),
253 	owning(list.owning)
254 {
255 }
256 
257 
258 _PointerList_::~_PointerList_()
259 {
260 	// This is empty by design, the "owning" variable
261 	// is used by the BObjectList subclass
262 }
263 
264 
265 // Note: function pointers must not be NULL!!!
266 
267 void *
268 _PointerList_::EachElement(GenericEachFunction function, void *arg)
269 {
270 	int32 numItems = CountItems();
271 	void *result = NULL;
272 
273 	for (int32 index = 0; index < numItems; index++) {
274 		result = function(ItemAtFast(index), arg);
275 		if (result != NULL)
276 			break;
277 	}
278 
279 	return result;
280 }
281 
282 
283 void
284 _PointerList_::SortItems(GenericCompareFunction compareFunc)
285 {
286 	PointerListHelper helper(compareFunc);
287 	helper.SortItems(this);
288 }
289 
290 
291 void
292 _PointerList_::SortItems(GenericCompareFunctionWithState compareFunc, void *state)
293 {
294 	PointerListHelperWithState helper(compareFunc, state);
295 	helper.SortItems(this);
296 }
297 
298 
299 void
300 _PointerList_::HSortItems(GenericCompareFunction compareFunc)
301 {
302 	PointerListHelper helper(compareFunc);
303 	helper.HSortItems(this);
304 }
305 
306 
307 void
308 _PointerList_::HSortItems(GenericCompareFunctionWithState compareFunc, void *state)
309 {
310 	PointerListHelperWithState helper(compareFunc, state);
311 	helper.HSortItems(this);
312 }
313 
314 
315 void *
316 _PointerList_::BinarySearch(const void *key, GenericCompareFunction compareFunc) const
317 {
318 	PointerListHelper helper(compareFunc);
319 	return helper.BinarySearch(key, this);
320 }
321 
322 
323 void *
324 _PointerList_::BinarySearch(const void *key,
325 			GenericCompareFunctionWithState compareFunc, void *state) const
326 {
327 	PointerListHelperWithState helper(compareFunc, state);
328 	return helper.BinarySearch(key, this);
329 }
330 
331 
332 int32
333 _PointerList_::BinarySearchIndex(const void *key, GenericCompareFunction compareFunc) const
334 {
335 	PointerListHelper helper(compareFunc);
336 	return helper.BinarySearchIndex(key, this);
337 }
338 
339 
340 int32
341 _PointerList_::BinarySearchIndex(const void *key,
342 			GenericCompareFunctionWithState compareFunc, void *state) const
343 {
344 	PointerListHelperWithState helper(compareFunc, state);
345 	return helper.BinarySearchIndex(key, this);
346 }
347 
348 
349 int32
350 _PointerList_::BinarySearchIndexByPredicate(const void *key, UnaryPredicateGlue predicate) const
351 {
352 	PointerListHelperUsePredicate helper(predicate);
353 	return helper.BinarySearchIndex(key, this);
354 }
355 
356 bool
357 _PointerList_::ReplaceItem(int32 index, void *newItem)
358 {
359 	if (index < 0 || index >= CountItems())
360 		return false;
361 
362 	void **items = static_cast<void **>(Items());
363 	items[index] = newItem;
364 
365 	return true;
366 }
367 
368