1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: List.cpp 23 // Author(s): The Storage kit Team 24 // Isaac Yonemoto 25 // Description: BList class provides storage for pointers. 26 // Not thread safe. 27 //------------------------------------------------------------------------------ 28 29 30 // Standard Includes ----------------------------------------------------------- 31 #include <List.h> 32 33 // System Includes ------------------------------------------------------------- 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 38 39 // helper function 40 static inline 41 void 42 move_items(void** items, int32 offset, int32 count) 43 { 44 if (count > 0 && offset != 0) 45 memmove(items + offset, items, count * sizeof(void*)); 46 } 47 48 49 // constructor 50 BList::BList(int32 count) 51 : fObjectList(NULL), 52 fPhysicalSize(0), 53 fItemCount(0), 54 fBlockSize(count) 55 { 56 if (fBlockSize <= 0) 57 fBlockSize = 1; 58 Resize(fItemCount); 59 } 60 61 62 // copy constructor 63 BList::BList(const BList& anotherList) 64 : fObjectList(NULL), 65 fPhysicalSize(0), 66 fItemCount(0), 67 fBlockSize(anotherList.fBlockSize) 68 { 69 *this = anotherList; 70 } 71 72 73 // destructor 74 BList::~BList() 75 { 76 free(fObjectList); 77 } 78 79 80 // = 81 BList& 82 BList::operator =(const BList &list) 83 { 84 fBlockSize = list.fBlockSize; 85 Resize(list.fItemCount); 86 memcpy(fObjectList, list.fObjectList, fItemCount * sizeof(void*)); 87 return *this; 88 } 89 90 91 // AddItem 92 bool 93 BList::AddItem(void *item, int32 index) 94 { 95 bool result = (index >= 0 && index <= fItemCount 96 && Resize(fItemCount + 1)); 97 if (result) { 98 move_items(fObjectList + index, 1, fItemCount - index - 1); 99 fObjectList[index] = item; 100 } 101 return result; 102 } 103 104 105 // AddItem 106 bool 107 BList::AddItem(void *item) 108 { 109 bool result = true; 110 if ((int32)fPhysicalSize > fItemCount) { 111 fObjectList[fItemCount] = item; 112 fItemCount++; 113 } else { 114 if ((result = Resize(fItemCount + 1))) 115 fObjectList[fItemCount - 1] = item; 116 } 117 return result; 118 } 119 120 121 // AddList 122 bool 123 BList::AddList(const BList *list, int32 index) 124 { 125 bool result = (list && index >= 0 && index <= fItemCount); 126 if (result && list->fItemCount > 0) { 127 int32 count = list->fItemCount; 128 result = Resize(fItemCount + count); 129 if (result) { 130 move_items(fObjectList + index, count, fItemCount - index - count); 131 memcpy(fObjectList + index, list->fObjectList, 132 list->fItemCount * sizeof(void *)); 133 } 134 } 135 return result; 136 } 137 138 139 // AddList 140 bool 141 BList::AddList(const BList *list) 142 { 143 bool result = (list != NULL); 144 if (result && list->fItemCount > 0) { 145 int32 index = fItemCount; 146 int32 count = list->fItemCount; 147 result = Resize(fItemCount + count); 148 if (result) { 149 memcpy(fObjectList + index, list->fObjectList, 150 list->fItemCount * sizeof(void *)); 151 } 152 } 153 return result; 154 } 155 156 157 // RemoveItem 158 bool 159 BList::RemoveItem(void *item) 160 { 161 int32 index = IndexOf(item); 162 bool result = (index >= 0); 163 if (result) 164 RemoveItem(index); 165 return result; 166 } 167 168 169 // RemoveItem 170 void * 171 BList::RemoveItem(int32 index) 172 { 173 void *item = NULL; 174 if (index >= 0 && index < fItemCount) { 175 item = fObjectList[index]; 176 move_items(fObjectList + index + 1, -1, fItemCount - index - 1); 177 Resize(fItemCount - 1); 178 } 179 return item; 180 } 181 182 183 // RemoveItems 184 bool 185 BList::RemoveItems(int32 index, int32 count) 186 { 187 bool result = (index >= 0 && index <= fItemCount); 188 if (result) { 189 if (index + count > fItemCount) 190 count = fItemCount - index; 191 if (count > 0) { 192 move_items(fObjectList + index + count, -count, 193 fItemCount - index - count); 194 Resize(fItemCount - count); 195 } else 196 result = false; 197 } 198 return result; 199 } 200 201 202 //ReplaceItem 203 bool 204 BList::ReplaceItem(int32 index, void *newItem) 205 { 206 bool result = false; 207 208 if (index >= 0 && index < fItemCount) { 209 fObjectList[index] = newItem; 210 result = true; 211 } 212 return result; 213 } 214 215 216 // MakeEmpty 217 void 218 BList::MakeEmpty() 219 { 220 Resize(0); 221 } 222 223 224 /* Reordering items. */ 225 // SortItems 226 void 227 BList::SortItems(int (*compareFunc)(const void *, const void *)) 228 { 229 if (compareFunc) 230 qsort(fObjectList, fItemCount, sizeof(void *), compareFunc); 231 } 232 233 234 //SwapItems 235 bool 236 BList::SwapItems(int32 indexA, int32 indexB) 237 { 238 bool result = false; 239 240 if (indexA >= 0 && indexA < fItemCount 241 && indexB >= 0 && indexB < fItemCount) { 242 243 void *tmpItem = fObjectList[indexA]; 244 fObjectList[indexA] = fObjectList[indexB]; 245 fObjectList[indexB] = tmpItem; 246 247 result = true; 248 } 249 250 return result; 251 } 252 253 254 //MoveItem 255 //This moves a list item from posititon a to position b, moving the appropriate block of 256 // list elements to make up for the move. For example, in the array: 257 // A B C D E F G H I J 258 // Moveing 1(B)->6(G) would result in this: 259 // A C D E F G B H I J 260 bool 261 BList::MoveItem(int32 fromIndex, int32 toIndex) 262 { 263 if ((fromIndex >= fItemCount) || (toIndex >= fItemCount) || (fromIndex < 0) || (toIndex < 0)) 264 return false; 265 266 if (fromIndex < toIndex) 267 { 268 void * tmp_mover = fObjectList[fromIndex]; 269 memmove(fObjectList + fromIndex + 1, fObjectList + fromIndex, (toIndex - fromIndex) * sizeof(void *)); 270 fObjectList[toIndex] = tmp_mover; 271 } 272 else if (fromIndex > toIndex) 273 { 274 void * tmp_mover = fObjectList[fromIndex]; 275 memmove(fObjectList + toIndex + 1, fObjectList + toIndex, (fromIndex - toIndex) * sizeof(void *)); 276 fObjectList[toIndex] = tmp_mover; 277 }; 278 return true; 279 } 280 281 282 /* Retrieving items. */ 283 // ItemAt 284 void * 285 BList::ItemAt(int32 index) const 286 { 287 void *item = NULL; 288 if (index >= 0 && index < fItemCount) 289 item = fObjectList[index]; 290 return item; 291 } 292 293 294 // FirstItem 295 void * 296 BList::FirstItem() const 297 { 298 void *item = NULL; 299 if (fItemCount > 0) 300 item = fObjectList[0]; 301 return item; 302 } 303 304 305 // ItemAtFast 306 void * 307 BList::ItemAtFast(int32 index) const 308 { 309 return fObjectList[index]; 310 } 311 312 313 // Items 314 void * 315 BList::Items() const 316 { 317 return fObjectList; 318 } 319 320 321 // LastItem 322 void * 323 BList::LastItem() const 324 { 325 void *item = NULL; 326 if (fItemCount > 0) 327 item = fObjectList[fItemCount - 1]; 328 return item; 329 } 330 331 332 /* Querying the list. */ 333 // HasItem 334 bool 335 BList::HasItem(void *item) const 336 { 337 return (IndexOf(item) >= 0); 338 } 339 340 341 // IndexOf 342 int32 343 BList::IndexOf(void *item) const 344 { 345 for (int32 i = 0; i < fItemCount; i++) { 346 if (fObjectList[i] == item) 347 return i; 348 } 349 return -1; 350 } 351 352 353 // CountItems 354 int32 355 BList::CountItems() const 356 { 357 return fItemCount; 358 } 359 360 361 // IsEmpty 362 bool 363 BList::IsEmpty() const 364 { 365 return (fItemCount == 0); 366 } 367 368 369 /* Iterating over the list. */ 370 //iterate a function over the whole list. If the function outputs a true 371 //value, then the process is terminated. 372 373 void 374 BList::DoForEach(bool (*func)(void *)) 375 { 376 bool terminate = false; int32 index = 0; //set terminate condition variables to go. 377 if (func != NULL) 378 { 379 while ((!terminate) && (index < fItemCount)) //check terminate condition. 380 { 381 terminate = func(fObjectList[index]); //reset immediate terminator 382 index++; //advance along the list. 383 }; 384 } 385 386 } 387 388 389 //same as above, except this function takes an argument. 390 void 391 BList::DoForEach(bool (*func)(void *, void*), void * arg) 392 { 393 bool terminate = false; int32 index = 0; 394 if (func != NULL) 395 { 396 while ((!terminate) && (index < fItemCount)) 397 { 398 terminate = func(fObjectList[index], arg); 399 index++; 400 }; 401 } 402 } 403 404 405 // obsolete AddList(BList* list, int32 index) and AddList(BList* list) 406 407 // AddList 408 extern "C" bool 409 AddList__5BListP5BListl(BList* self, BList* list, int32 index) 410 { 411 return self->AddList((const BList*)list, index); 412 } 413 414 415 // AddList 416 extern "C" bool 417 AddList__5BListP5BList(BList* self, BList* list) 418 { 419 return self->AddList((const BList*)list); 420 } 421 422 423 // FBC 424 void BList::_ReservedList1() {} 425 void BList::_ReservedList2() {} 426 427 428 // Resize 429 // 430 // Resizes fObjectList to be large enough to contain count items. 431 // fItemCount is adjusted accordingly. 432 bool 433 BList::Resize(int32 count) 434 { 435 bool result = true; 436 // calculate the new physical size 437 int32 newSize = count; 438 if (newSize <= 0) 439 newSize = 1; 440 newSize = ((newSize - 1) / fBlockSize + 1) * fBlockSize; 441 // resize if necessary 442 if ((size_t)newSize != fPhysicalSize) { 443 void** newObjectList 444 = (void**)realloc(fObjectList, newSize * sizeof(void*)); 445 if (newObjectList) { 446 fObjectList = newObjectList; 447 fPhysicalSize = newSize; 448 } else 449 result = false; 450 } 451 if (result) 452 fItemCount = count; 453 return result; 454 } 455 456