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