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