1 // Vector.h 2 // 3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de) 4 // 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: 11 // 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 // 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. 22 // 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 26 // copyright holder. 27 28 #ifndef _VECTOR_H 29 #define _VECTOR_H 30 31 #include <new> 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include <SupportDefs.h> 36 37 template<typename Value> class VectorIterator; 38 39 // for convenience 40 #define _VECTOR_TEMPLATE_LIST template<typename Value> 41 #define _VECTOR_CLASS_NAME Vector<Value> 42 43 /*! 44 \class Vector 45 \brief A generic vector implementation. 46 */ 47 template<typename Value> 48 class Vector { 49 public: 50 typedef VectorIterator<Value> Iterator; 51 typedef VectorIterator<const Value> ConstIterator; 52 53 private: 54 static const size_t kDefaultChunkSize = 10; 55 static const size_t kMaximalChunkSize = 1024 * 1024; 56 57 public: 58 Vector(size_t chunkSize = kDefaultChunkSize); 59 ~Vector(); 60 61 status_t PushFront(const Value &value); 62 status_t PushBack(const Value &value); 63 64 void PopFront(); 65 void PopBack(); 66 67 status_t Insert(const Value &value, int32 index); 68 status_t Insert(const Value &value, const Iterator &iterator); 69 70 int32 Remove(const Value &value); 71 Iterator Erase(int32 index); 72 Iterator Erase(const Iterator &iterator); 73 74 inline int32 Count() const; 75 inline bool IsEmpty() const; 76 void MakeEmpty(); 77 78 inline Iterator Begin(); 79 inline ConstIterator Begin() const; 80 inline Iterator End(); 81 inline ConstIterator End() const; 82 inline Iterator Null(); 83 inline ConstIterator Null() const; 84 inline Iterator IteratorForIndex(int32 index); 85 inline ConstIterator IteratorForIndex(int32 index) const; 86 87 inline const Value &ElementAt(int32 index) const; 88 inline Value &ElementAt(int32 index); 89 90 int32 IndexOf(const Value &value, int32 start = 0) const; 91 Iterator Find(const Value &value); 92 Iterator Find(const Value &value, const Iterator &start); 93 ConstIterator Find(const Value &value) const; 94 ConstIterator Find(const Value &value, const ConstIterator &start) const; 95 96 inline Value &operator[](int32 index); 97 inline const Value &operator[](int32 index) const; 98 99 // debugging 100 int32 GetCapacity() const { return fCapacity; } 101 102 private: 103 inline static void _MoveItems(Value *values, int32 offset, int32 count); 104 bool _Resize(size_t count); 105 inline int32 _IteratorIndex(const Iterator &iterator) const; 106 inline int32 _IteratorIndex(const ConstIterator &iterator) const; 107 108 private: 109 size_t fCapacity; 110 size_t fChunkSize; 111 int32 fItemCount; 112 Value *fItems; 113 }; 114 115 116 // VectorIterator 117 template<typename Value> 118 class VectorIterator { 119 private: 120 typedef VectorIterator<Value> Iterator; 121 122 public: 123 inline VectorIterator<Value>() 124 : fElement(NULL) 125 { 126 } 127 128 inline VectorIterator<Value>(const Iterator &other) 129 : fElement(other.fElement) 130 { 131 } 132 133 inline Iterator &operator++() 134 { 135 if (fElement) 136 ++fElement; 137 return *this; 138 } 139 140 inline Iterator operator++(int) 141 { 142 Iterator it(*this); 143 ++*this; 144 return it; 145 } 146 147 inline Iterator &operator--() 148 { 149 if (fElement) 150 --fElement; 151 return *this; 152 } 153 154 inline Iterator operator--(int) 155 { 156 Iterator it(*this); 157 --*this; 158 return it; 159 } 160 161 inline Iterator &operator=(const Iterator &other) 162 { 163 fElement = other.fElement; 164 return *this; 165 } 166 167 168 inline bool operator==(const Iterator &other) const 169 { 170 return (fElement == other.fElement); 171 } 172 173 inline bool operator!=(const Iterator &other) const 174 { 175 return !(*this == other); 176 } 177 178 inline Value &operator*() const 179 { 180 return *fElement; 181 } 182 183 inline Value *operator->() const 184 { 185 return fElement; 186 } 187 188 inline operator bool() const 189 { 190 return fElement; 191 } 192 193 // private 194 public: 195 inline VectorIterator<Value>(Value *element) 196 : fElement(element) 197 { 198 } 199 200 inline Value *Element() const 201 { 202 return fElement; 203 } 204 205 protected: 206 Value *fElement; 207 }; 208 209 210 // Vector 211 212 // constructor 213 /*! \brief Creates an empty vector. 214 \param chunkSize The granularity for the vector's capacity, i.e. the 215 minimal number of elements the capacity grows or shrinks when 216 necessary. 217 */ 218 _VECTOR_TEMPLATE_LIST 219 _VECTOR_CLASS_NAME::Vector(size_t chunkSize) 220 : fCapacity(0), 221 fChunkSize(chunkSize), 222 fItemCount(0), 223 fItems(NULL) 224 { 225 if (fChunkSize == 0 || fChunkSize > kMaximalChunkSize) 226 fChunkSize = kDefaultChunkSize; 227 _Resize(0); 228 } 229 230 // destructor 231 /*! \brief Frees all resources associated with the object. 232 233 The contained elements are destroyed. Note, that, if the element 234 type is a pointer type, only the pointer is destroyed, not the object 235 it points to. 236 */ 237 _VECTOR_TEMPLATE_LIST 238 _VECTOR_CLASS_NAME::~Vector() 239 { 240 MakeEmpty(); 241 free(fItems); 242 } 243 244 // PushFront 245 /*! \brief Inserts a copy of the supplied value at the beginning of the 246 vector. 247 \param value The element to be inserted. 248 \return 249 - \c B_OK: Everything went fine. 250 - \c B_NO_MEMORY: Insufficient memory for this operation. 251 */ 252 _VECTOR_TEMPLATE_LIST 253 status_t 254 _VECTOR_CLASS_NAME::PushFront(const Value &value) 255 { 256 return Insert(value, 0); 257 } 258 259 // PushBack 260 /*! \brief Inserts a copy of the supplied value at the end of the vector. 261 \param value The element to be inserted. 262 \return 263 - \c B_OK: Everything went fine. 264 - \c B_NO_MEMORY: Insufficient memory for this operation. 265 */ 266 _VECTOR_TEMPLATE_LIST 267 status_t 268 _VECTOR_CLASS_NAME::PushBack(const Value &value) 269 { 270 return Insert(value, fItemCount); 271 } 272 273 // PopFront 274 /*! \brief Removes the first element of the vector. 275 276 Invocation on an empty vector is harmless. 277 */ 278 _VECTOR_TEMPLATE_LIST 279 void 280 _VECTOR_CLASS_NAME::PopFront() 281 { 282 if (fItemCount > 0) 283 Erase(0); 284 } 285 286 // PopBack 287 /*! \brief Removes the last element of the vector. 288 289 Invocation on an empty vector is harmless. 290 */ 291 _VECTOR_TEMPLATE_LIST 292 void 293 _VECTOR_CLASS_NAME::PopBack() 294 { 295 if (fItemCount > 0) 296 Erase(fItemCount - 1); 297 } 298 299 // _MoveItems 300 /*! \brief Moves elements within an array. 301 \param items The elements to be moved. 302 \param offset The index to which the elements shall be moved. May be 303 negative. 304 \param count The number of elements to be moved. 305 */ 306 _VECTOR_TEMPLATE_LIST 307 inline 308 void 309 _VECTOR_CLASS_NAME::_MoveItems(Value* items, int32 offset, int32 count) 310 { 311 if (count > 0 && offset != 0) 312 memmove(items + offset, items, count * sizeof(Value)); 313 } 314 315 // Insert 316 /*! \brief Inserts a copy of the the supplied value at the given index. 317 \param value The value to be inserted. 318 \param index The index at which to insert the new element. It must 319 hold: 0 <= \a index <= Count(). 320 \return 321 - \c B_OK: Everything went fine. 322 - \c B_BAD_VALUE: \a index is out of range. 323 - \c B_NO_MEMORY: Insufficient memory for this operation. 324 */ 325 _VECTOR_TEMPLATE_LIST 326 status_t 327 _VECTOR_CLASS_NAME::Insert(const Value &value, int32 index) 328 { 329 if (index < 0 || index > fItemCount) 330 return B_BAD_VALUE; 331 if (!_Resize(fItemCount + 1)) 332 return B_NO_MEMORY; 333 _MoveItems(fItems + index, 1, fItemCount - index - 1); 334 new(fItems + index) Value(value); 335 return B_OK; 336 } 337 338 // Insert 339 /*! \brief Inserts a copy of the the supplied value at the given position. 340 \param value The value to be inserted. 341 \param iterator An iterator specifying the position at which to insert 342 the new element. 343 \return 344 - \c B_OK: Everything went fine. 345 - \c B_BAD_VALUE: \a iterator is is invalid. 346 - \c B_NO_MEMORY: Insufficient memory for this operation. 347 */ 348 _VECTOR_TEMPLATE_LIST 349 status_t 350 _VECTOR_CLASS_NAME::Insert(const Value &value, const Iterator &iterator) 351 { 352 int32 index = _IteratorIndex(iterator); 353 if (index >= 0) 354 return Insert(value, index); 355 return B_BAD_VALUE; 356 } 357 358 // Remove 359 /*! \brief Removes all elements of the supplied value. 360 \param value The value of the elements to be removed. 361 \return The number of removed occurrences. 362 */ 363 _VECTOR_TEMPLATE_LIST 364 int32 365 _VECTOR_CLASS_NAME::Remove(const Value &value) 366 { 367 int32 count = 0; 368 for (int32 i = fItemCount - 1; i >= 0; i--) { 369 if (ElementAt(i) == value) { 370 Erase(i); 371 count++; 372 } 373 } 374 return count; 375 } 376 377 // Erase 378 /*! \brief Removes the element at the given index. 379 \param index The position of the element to be removed. 380 \return An iterator referring to the element now being located at index 381 \a index (End(), if it was the last element that has been 382 removed), or Null(), if \a index was out of range. 383 */ 384 _VECTOR_TEMPLATE_LIST 385 typename _VECTOR_CLASS_NAME::Iterator 386 _VECTOR_CLASS_NAME::Erase(int32 index) 387 { 388 if (index >= 0 && index < fItemCount) { 389 fItems[index].~Value(); 390 _MoveItems(fItems + index + 1, -1, fItemCount - index - 1); 391 _Resize(fItemCount - 1); 392 return Iterator(fItems + index); 393 } 394 return Null(); 395 } 396 397 // Erase 398 /*! \brief Removes the element at the given position. 399 \param iterator An iterator referring to the element to be removed. 400 \return An iterator referring to the element succeeding the removed 401 one (End(), if it was the last element that has been 402 removed), or Null(), if \a iterator was an invalid iterator 403 (in this case including End()). 404 */ 405 _VECTOR_TEMPLATE_LIST 406 typename _VECTOR_CLASS_NAME::Iterator 407 _VECTOR_CLASS_NAME::Erase(const Iterator &iterator) 408 { 409 int32 index = _IteratorIndex(iterator); 410 if (index >= 0 && index < fItemCount) 411 return Erase(index); 412 return Null(); 413 } 414 415 // Count 416 /*! \brief Returns the number of elements the vector contains. 417 \return The number of elements the vector contains. 418 */ 419 _VECTOR_TEMPLATE_LIST 420 inline 421 int32 422 _VECTOR_CLASS_NAME::Count() const 423 { 424 return fItemCount; 425 } 426 427 // IsEmpty 428 /*! \brief Returns whether the vector is empty. 429 \return \c true, if the vector is empty, \c false otherwise. 430 */ 431 _VECTOR_TEMPLATE_LIST 432 inline 433 bool 434 _VECTOR_CLASS_NAME::IsEmpty() const 435 { 436 return (fItemCount == 0); 437 } 438 439 // MakeEmpty 440 /*! \brief Removes all elements from the vector. 441 */ 442 _VECTOR_TEMPLATE_LIST 443 void 444 _VECTOR_CLASS_NAME::MakeEmpty() 445 { 446 for (int32 i = 0; i < fItemCount; i++) 447 fItems[i].~Value(); 448 _Resize(0); 449 } 450 451 // Begin 452 /*! \brief Returns an iterator referring to the beginning of the vector. 453 454 If the vector is not empty, Begin() refers to its first element, 455 otherwise it is equal to End() and must not be dereferenced! 456 457 \return An iterator referring to the beginning of the vector. 458 */ 459 _VECTOR_TEMPLATE_LIST 460 inline 461 typename _VECTOR_CLASS_NAME::Iterator 462 _VECTOR_CLASS_NAME::Begin() 463 { 464 return Iterator(fItems); 465 } 466 467 // Begin 468 /*! \brief Returns an iterator referring to the beginning of the vector. 469 470 If the vector is not empty, Begin() refers to its first element, 471 otherwise it is equal to End() and must not be dereferenced! 472 473 \return An iterator referring to the beginning of the vector. 474 */ 475 _VECTOR_TEMPLATE_LIST 476 inline 477 typename _VECTOR_CLASS_NAME::ConstIterator 478 _VECTOR_CLASS_NAME::Begin() const 479 { 480 return ConstIterator(fItems); 481 } 482 483 // End 484 /*! \brief Returns an iterator referring to the end of the vector. 485 486 The position identified by End() is the one succeeding the last 487 element, i.e. it must not be dereferenced! 488 489 \return An iterator referring to the end of the vector. 490 */ 491 _VECTOR_TEMPLATE_LIST 492 inline 493 typename _VECTOR_CLASS_NAME::Iterator 494 _VECTOR_CLASS_NAME::End() 495 { 496 return Iterator(fItems + fItemCount); 497 } 498 499 // End 500 /*! \brief Returns an iterator referring to the end of the vector. 501 502 The position identified by End() is the one succeeding the last 503 element, i.e. it must not be dereferenced! 504 505 \return An iterator referring to the end of the vector. 506 */ 507 _VECTOR_TEMPLATE_LIST 508 inline 509 typename _VECTOR_CLASS_NAME::ConstIterator 510 _VECTOR_CLASS_NAME::End() const 511 { 512 return ConstIterator(fItems + fItemCount); 513 } 514 515 // Null 516 /*! \brief Returns an invalid iterator. 517 518 Null() is used as a return value, if something went wrong. It must 519 neither be incremented or decremented nor dereferenced! 520 521 \return An invalid iterator. 522 */ 523 _VECTOR_TEMPLATE_LIST 524 inline 525 typename _VECTOR_CLASS_NAME::Iterator 526 _VECTOR_CLASS_NAME::Null() 527 { 528 return Iterator(NULL); 529 } 530 531 // Null 532 /*! \brief Returns an invalid iterator. 533 534 Null() is used as a return value, if something went wrong. It must 535 neither be incremented or decremented nor dereferenced! 536 537 \return An invalid iterator. 538 */ 539 _VECTOR_TEMPLATE_LIST 540 inline 541 typename _VECTOR_CLASS_NAME::ConstIterator 542 _VECTOR_CLASS_NAME::Null() const 543 { 544 return ConstIterator(NULL); 545 } 546 547 // IteratorForIndex 548 /*! \brief Returns an iterator for a given index. 549 \return An iterator referring to the same element as \a index, or 550 End(), if \a index is out of range. 551 */ 552 _VECTOR_TEMPLATE_LIST 553 inline 554 typename _VECTOR_CLASS_NAME::Iterator 555 _VECTOR_CLASS_NAME::IteratorForIndex(int32 index) 556 { 557 if (index >= 0 && index <= fItemCount) 558 return Iterator(fItems + index); 559 return End(); 560 } 561 562 // IteratorForIndex 563 /*! \brief Returns an iterator for a given index. 564 \return An iterator referring to the same element as \a index, or 565 End(), if \a index is out of range. 566 */ 567 _VECTOR_TEMPLATE_LIST 568 inline 569 typename _VECTOR_CLASS_NAME::ConstIterator 570 _VECTOR_CLASS_NAME::IteratorForIndex(int32 index) const 571 { 572 if (index >= 0 && index <= fItemCount) 573 return ConstIterator(fItems + index); 574 return End(); 575 } 576 577 // ElementAt 578 /*! \brief Returns the element at a given index. 579 \param index The index identifying the element to be returned. 580 \return The element identified by the given index. 581 */ 582 _VECTOR_TEMPLATE_LIST 583 inline 584 const Value & 585 _VECTOR_CLASS_NAME::ElementAt(int32 index) const 586 { 587 if (index >= 0 && index < fItemCount) 588 return fItems[index]; 589 // Return the 0th element by default. Unless the allocation failed, there 590 // is always a 0th element -- uninitialized perhaps. 591 return fItems[0]; 592 } 593 594 // ElementAt 595 /*! \brief Returns the element at a given index. 596 \param index The index identifying the element to be returned. 597 \return The element identified by the given index. 598 */ 599 _VECTOR_TEMPLATE_LIST 600 inline 601 Value & 602 _VECTOR_CLASS_NAME::ElementAt(int32 index) 603 { 604 if (index >= 0 && index < fItemCount) 605 return fItems[index]; 606 // Return the 0th element by default. Unless the allocation failed, there 607 // is always a 0th element -- uninitialized perhaps. 608 return fItems[0]; 609 } 610 611 // IndexOf 612 /*! \brief Returns the index of the next element with the specified value. 613 \param value The value of the element to be found. 614 \param start The index at which to be started to search for the element. 615 \return The index of the found element, or \c -1, if no further element 616 with the given value could be found or \a index is out of range. 617 */ 618 _VECTOR_TEMPLATE_LIST 619 int32 620 _VECTOR_CLASS_NAME::IndexOf(const Value &value, int32 start) const 621 { 622 if (start >= 0) { 623 for (int32 i = start; i < fItemCount; i++) { 624 if (fItems[i] == value) 625 return i; 626 } 627 } 628 return -1; 629 } 630 631 // Find 632 /*! \brief Returns an iterator referring to the next element with the 633 specified value. 634 \param value The value of the element to be found. 635 \return An iterator referring to the found element, or End(), if no 636 further with the given value could be found. 637 */ 638 _VECTOR_TEMPLATE_LIST 639 inline 640 typename _VECTOR_CLASS_NAME::Iterator 641 _VECTOR_CLASS_NAME::Find(const Value &value) 642 { 643 return Find(value, Begin()); 644 } 645 646 // Find 647 /*! \brief Returns an iterator referring to the next element with the 648 specified value. 649 \param value The value of the element to be found. 650 \param start And iterator specifying where to start searching for the 651 element. 652 \return An iterator referring to the found element, or End(), if no 653 further with the given value could be found or \a start was 654 invalid. 655 */ 656 _VECTOR_TEMPLATE_LIST 657 typename _VECTOR_CLASS_NAME::Iterator 658 _VECTOR_CLASS_NAME::Find(const Value &value, const Iterator &start) 659 { 660 int32 index = IndexOf(value, _IteratorIndex(start)); 661 if (index >= 0) 662 return Iterator(fItems + index); 663 return End(); 664 } 665 666 // Find 667 /*! \brief Returns an iterator referring to the of the next element with the 668 specified value. 669 \param value The value of the element to be found. 670 \return An iterator referring to the found element, or End(), if no 671 further with the given value could be found. 672 */ 673 _VECTOR_TEMPLATE_LIST 674 inline 675 typename _VECTOR_CLASS_NAME::ConstIterator 676 _VECTOR_CLASS_NAME::Find(const Value &value) const 677 { 678 return Find(value, Begin()); 679 } 680 681 // Find 682 /*! \brief Returns an iterator referring to the of the next element with the 683 specified value. 684 \param value The value of the element to be found. 685 \param start And iterator specifying where to start searching for the 686 element. 687 \return An iterator referring to the found element, or End(), if no 688 further with the given value could be found or \a start was 689 invalid. 690 */ 691 _VECTOR_TEMPLATE_LIST 692 typename _VECTOR_CLASS_NAME::ConstIterator 693 _VECTOR_CLASS_NAME::Find(const Value &value, const ConstIterator &start) const 694 { 695 int32 index = IndexOf(value, _IteratorIndex(start)); 696 if (index >= 0) 697 return ConstIterator(fItems + index); 698 return End(); 699 } 700 701 // [] 702 /*! \brief Semantically equivalent to ElementAt(). 703 */ 704 _VECTOR_TEMPLATE_LIST 705 inline 706 Value & 707 _VECTOR_CLASS_NAME::operator[](int32 index) 708 { 709 return ElementAt(index); 710 } 711 712 // [] 713 /*! \brief Semantically equivalent to ElementAt(). 714 */ 715 _VECTOR_TEMPLATE_LIST 716 inline 717 const Value & 718 _VECTOR_CLASS_NAME::operator[](int32 index) const 719 { 720 return ElementAt(index); 721 } 722 723 // _Resize 724 /*! \brief Resizes the vector. 725 726 The internal element array will be grown or shrunk to the next multiple 727 of \a fChunkSize >= \a count, but no less than \a fChunkSize. 728 729 Also adjusts \a fItemCount according to the supplied \a count, but does 730 not invoke a destructor or constructor on any element. 731 732 \param count The number of element. 733 \return \c true, if everything went fine, \c false, if the memory 734 allocation failed. 735 */ 736 _VECTOR_TEMPLATE_LIST 737 bool 738 _VECTOR_CLASS_NAME::_Resize(size_t count) 739 { 740 bool result = true; 741 // calculate the new capacity 742 int32 newSize = count; 743 if (newSize <= 0) 744 newSize = 1; 745 newSize = ((newSize - 1) / fChunkSize + 1) * fChunkSize; 746 // resize if necessary 747 if ((size_t)newSize != fCapacity) { 748 Value* newItems = (Value*)realloc(fItems, newSize * sizeof(Value)); 749 if (newItems) { 750 fItems = newItems; 751 fCapacity = newSize; 752 } else 753 result = false; 754 } 755 if (result) 756 fItemCount = count; 757 return result; 758 } 759 760 // _IteratorIndex 761 /*! \brief Returns index of the element the supplied iterator refers to. 762 \return The index of the element the supplied iterator refers to, or 763 \c -1, if the iterator is invalid (End() is considered valid 764 here, and Count() is returned). 765 */ 766 _VECTOR_TEMPLATE_LIST 767 inline 768 int32 769 _VECTOR_CLASS_NAME::_IteratorIndex(const Iterator &iterator) const 770 { 771 if (iterator.Element()) { 772 int32 index = iterator.Element() - fItems; 773 if (index >= 0 && index <= fItemCount) 774 return index; 775 } 776 return -1; 777 } 778 779 // _IteratorIndex 780 /*! \brief Returns index of the element the supplied iterator refers to. 781 \return The index of the element the supplied iterator refers to, or 782 \c -1, if the iterator is invalid (End() is considered valid 783 here, and Count() is returned). 784 */ 785 _VECTOR_TEMPLATE_LIST 786 inline 787 int32 788 _VECTOR_CLASS_NAME::_IteratorIndex(const ConstIterator &iterator) const 789 { 790 if (iterator.Element()) { 791 int32 index = iterator.Element() - fItems; 792 if (index >= 0 && index <= fItemCount) 793 return index; 794 } 795 return -1; 796 } 797 798 #endif // _VECTOR_H 799