3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
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:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
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.
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
34 #include <SupportDefs.h>
35 #include <util/kernel_cpp.h>
37 template<typename Value
> class VectorIterator
;
40 #define _VECTOR_TEMPLATE_LIST template<typename Value>
41 #define _VECTOR_CLASS_NAME Vector<Value>
42 #define _VECTOR_CLASS_TYPE typename Vector<Value>
46 \brief A generic vector implementation.
48 template<typename Value
>
51 typedef VectorIterator
<Value
> Iterator
;
52 typedef VectorIterator
<const Value
> ConstIterator
;
55 static const size_t kDefaultChunkSize
= 10;
56 static const size_t kMaximalChunkSize
= 1024 * 1024;
59 Vector(size_t chunkSize
= kDefaultChunkSize
);
62 status_t
PushFront(const Value
&value
);
63 status_t
PushBack(const Value
&value
);
68 status_t
Add(const Value
&value
) { return PushBack(value
); }
69 status_t
Add(const Value
&value
, int32 index
) { return Insert(value
, index
); }
71 status_t
Insert(const Value
&value
, int32 index
);
72 status_t
Insert(const Value
&value
, const Iterator
&iterator
);
74 int32
Remove(const Value
&value
);
75 Iterator
Erase(int32 index
);
76 Iterator
Erase(const Iterator
&iterator
);
78 inline int32
Count() const;
79 inline bool IsEmpty() const;
82 inline Iterator
Begin();
83 inline ConstIterator
Begin() const;
84 inline Iterator
End();
85 inline ConstIterator
End() const;
86 inline Iterator
Null();
87 inline ConstIterator
Null() const;
88 inline Iterator
IteratorForIndex(int32 index
);
89 inline ConstIterator
IteratorForIndex(int32 index
) const;
91 inline const Value
&ElementAt(int32 index
) const;
92 inline Value
&ElementAt(int32 index
);
94 int32
IndexOf(const Value
&value
, int32 start
= 0) const;
95 Iterator
Find(const Value
&value
);
96 Iterator
Find(const Value
&value
, const Iterator
&start
);
97 ConstIterator
Find(const Value
&value
) const;
98 ConstIterator
Find(const Value
&value
, const ConstIterator
&start
) const;
100 inline Value
&operator[](int32 index
);
101 inline const Value
&operator[](int32 index
) const;
104 int32
GetCapacity() const { return fCapacity
; }
107 inline static void _MoveItems(Value
*values
, int32 offset
, int32 count
);
108 bool _Resize(size_t count
);
109 inline int32
_IteratorIndex(const Iterator
&iterator
) const;
110 inline int32
_IteratorIndex(const ConstIterator
&iterator
) const;
121 template<typename Value
>
122 class VectorIterator
{
124 typedef VectorIterator
<Value
> Iterator
;
127 inline VectorIterator
<Value
>()
132 inline VectorIterator
<Value
>(const Iterator
&other
)
133 : fElement(other
.fElement
)
137 inline Iterator
&operator++()
144 inline Iterator
operator++(int)
151 inline Iterator
&operator--()
158 inline Iterator
operator--(int)
165 inline Iterator
&operator=(const Iterator
&other
)
167 fElement
= other
.fElement
;
172 inline bool operator==(const Iterator
&other
) const
174 return (fElement
== other
.fElement
);
177 inline bool operator!=(const Iterator
&other
) const
179 return !(*this == other
);
182 inline Value
&operator*() const
187 inline Value
*operator->() const
192 inline operator bool() const
199 inline VectorIterator
<Value
>(Value
*element
)
204 inline Value
*Element() const
217 /*! \brief Creates an empty vector.
218 \param chunkSize The granularity for the vector's capacity, i.e. the
219 minimal number of elements the capacity grows or shrinks when
222 _VECTOR_TEMPLATE_LIST
223 _VECTOR_CLASS_NAME::Vector(size_t chunkSize
)
225 fChunkSize(chunkSize
),
229 if (fChunkSize
== 0 || fChunkSize
> kMaximalChunkSize
)
230 fChunkSize
= kDefaultChunkSize
;
235 /*! \brief Frees all resources associated with the object.
237 The contained elements are destroyed. Note, that, if the element
238 type is a pointer type, only the pointer is destroyed, not the object
241 _VECTOR_TEMPLATE_LIST
242 _VECTOR_CLASS_NAME::~Vector()
249 /*! \brief Inserts a copy of the supplied value at the beginning of the
251 \param value The element to be inserted.
253 - \c B_OK: Everything went fine.
254 - \c B_NO_MEMORY: Insufficient memory for this operation.
256 _VECTOR_TEMPLATE_LIST
258 _VECTOR_CLASS_NAME::PushFront(const Value
&value
)
260 return Insert(value
, 0);
264 /*! \brief Inserts a copy of the supplied value at the end of the vector.
265 \param value The element to be inserted.
267 - \c B_OK: Everything went fine.
268 - \c B_NO_MEMORY: Insufficient memory for this operation.
270 _VECTOR_TEMPLATE_LIST
272 _VECTOR_CLASS_NAME::PushBack(const Value
&value
)
274 return Insert(value
, fItemCount
);
278 /*! \brief Removes the first element of the vector.
280 Invocation on an empty vector is harmless.
282 _VECTOR_TEMPLATE_LIST
284 _VECTOR_CLASS_NAME::PopFront()
291 /*! \brief Removes the last element of the vector.
293 Invocation on an empty vector is harmless.
295 _VECTOR_TEMPLATE_LIST
297 _VECTOR_CLASS_NAME::PopBack()
300 Erase(fItemCount
- 1);
304 /*! \brief Moves elements within an array.
305 \param items The elements to be moved.
306 \param offset The index to which the elements shall be moved. May be
308 \param count The number of elements to be moved.
310 _VECTOR_TEMPLATE_LIST
313 _VECTOR_CLASS_NAME::_MoveItems(Value
* items
, int32 offset
, int32 count
)
315 if (count
> 0 && offset
!= 0)
316 memmove(items
+ offset
, items
, count
* sizeof(Value
));
320 /*! \brief Inserts a copy of the the supplied value at the given index.
321 \param value The value to be inserted.
322 \param index The index at which to insert the new element. It must
323 hold: 0 <= \a index <= Count().
325 - \c B_OK: Everything went fine.
326 - \c B_BAD_VALUE: \a index is out of range.
327 - \c B_NO_MEMORY: Insufficient memory for this operation.
329 _VECTOR_TEMPLATE_LIST
331 _VECTOR_CLASS_NAME::Insert(const Value
&value
, int32 index
)
333 if (index
< 0 || index
> fItemCount
)
335 if (!_Resize(fItemCount
+ 1))
337 _MoveItems(fItems
+ index
, 1, fItemCount
- index
- 1);
338 new(fItems
+ index
) Value(value
);
343 /*! \brief Inserts a copy of the the supplied value at the given position.
344 \param value The value to be inserted.
345 \param iterator An iterator specifying the position at which to insert
348 - \c B_OK: Everything went fine.
349 - \c B_BAD_VALUE: \a iterator is is invalid.
350 - \c B_NO_MEMORY: Insufficient memory for this operation.
352 _VECTOR_TEMPLATE_LIST
354 _VECTOR_CLASS_NAME::Insert(const Value
&value
, const Iterator
&iterator
)
356 int32 index
= _IteratorIndex(iterator
);
358 return Insert(value
, index
);
363 /*! \brief Removes all elements of the supplied value.
364 \param value The value of the elements to be removed.
365 \return The number of removed occurrences.
367 _VECTOR_TEMPLATE_LIST
369 _VECTOR_CLASS_NAME::Remove(const Value
&value
)
372 for (int32 i
= fItemCount
- 1; i
>= 0; i
--) {
373 if (ElementAt(i
) == value
) {
382 /*! \brief Removes the element at the given index.
383 \param index The position of the element to be removed.
384 \return An iterator referring to the element now being located at index
385 \a index (End(), if it was the last element that has been
386 removed), or Null(), if \a index was out of range.
388 _VECTOR_TEMPLATE_LIST
389 _VECTOR_CLASS_TYPE::Iterator
390 _VECTOR_CLASS_NAME::Erase(int32 index
)
392 if (index
>= 0 && index
< fItemCount
) {
393 fItems
[index
].~Value();
394 _MoveItems(fItems
+ index
+ 1, -1, fItemCount
- index
- 1);
395 _Resize(fItemCount
- 1);
396 return Iterator(fItems
+ index
);
402 /*! \brief Removes the element at the given position.
403 \param iterator An iterator referring to the element to be removed.
404 \return An iterator referring to the element succeeding the removed
405 one (End(), if it was the last element that has been
406 removed), or Null(), if \a iterator was an invalid iterator
407 (in this case including End()).
409 _VECTOR_TEMPLATE_LIST
410 _VECTOR_CLASS_TYPE::Iterator
411 _VECTOR_CLASS_NAME::Erase(const Iterator
&iterator
)
413 int32 index
= _IteratorIndex(iterator
);
414 if (index
>= 0 && index
< fItemCount
)
420 /*! \brief Returns the number of elements the vector contains.
421 \return The number of elements the vector contains.
423 _VECTOR_TEMPLATE_LIST
426 _VECTOR_CLASS_NAME::Count() const
432 /*! \brief Returns whether the vector is empty.
433 \return \c true, if the vector is empty, \c false otherwise.
435 _VECTOR_TEMPLATE_LIST
438 _VECTOR_CLASS_NAME::IsEmpty() const
440 return (fItemCount
== 0);
444 /*! \brief Removes all elements from the vector.
446 _VECTOR_TEMPLATE_LIST
448 _VECTOR_CLASS_NAME::MakeEmpty()
450 for (int32 i
= 0; i
< fItemCount
; i
++)
456 /*! \brief Returns an iterator referring to the beginning of the vector.
458 If the vector is not empty, Begin() refers to its first element,
459 otherwise it is equal to End() and must not be dereferenced!
461 \return An iterator referring to the beginning of the vector.
463 _VECTOR_TEMPLATE_LIST
465 _VECTOR_CLASS_TYPE::Iterator
466 _VECTOR_CLASS_NAME::Begin()
468 return Iterator(fItems
);
472 /*! \brief Returns an iterator referring to the beginning of the vector.
474 If the vector is not empty, Begin() refers to its first element,
475 otherwise it is equal to End() and must not be dereferenced!
477 \return An iterator referring to the beginning of the vector.
479 _VECTOR_TEMPLATE_LIST
481 _VECTOR_CLASS_TYPE::ConstIterator
482 _VECTOR_CLASS_NAME::Begin() const
484 return ConstIterator(fItems
);
488 /*! \brief Returns an iterator referring to the end of the vector.
490 The position identified by End() is the one succeeding the last
491 element, i.e. it must not be dereferenced!
493 \return An iterator referring to the end of the vector.
495 _VECTOR_TEMPLATE_LIST
497 _VECTOR_CLASS_TYPE::Iterator
498 _VECTOR_CLASS_NAME::End()
500 return Iterator(fItems
+ fItemCount
);
504 /*! \brief Returns an iterator referring to the end of the vector.
506 The position identified by End() is the one succeeding the last
507 element, i.e. it must not be dereferenced!
509 \return An iterator referring to the end of the vector.
511 _VECTOR_TEMPLATE_LIST
513 _VECTOR_CLASS_TYPE::ConstIterator
514 _VECTOR_CLASS_NAME::End() const
516 return ConstIterator(fItems
+ fItemCount
);
520 /*! \brief Returns an invalid iterator.
522 Null() is used as a return value, if something went wrong. It must
523 neither be incremented or decremented nor dereferenced!
525 \return An invalid iterator.
527 _VECTOR_TEMPLATE_LIST
529 _VECTOR_CLASS_TYPE::Iterator
530 _VECTOR_CLASS_NAME::Null()
532 return Iterator(NULL
);
536 /*! \brief Returns an invalid iterator.
538 Null() is used as a return value, if something went wrong. It must
539 neither be incremented or decremented nor dereferenced!
541 \return An invalid iterator.
543 _VECTOR_TEMPLATE_LIST
545 _VECTOR_CLASS_TYPE::ConstIterator
546 _VECTOR_CLASS_NAME::Null() const
548 return ConstIterator(NULL
);
552 /*! \brief Returns an iterator for a given index.
553 \return An iterator referring to the same element as \a index, or
554 End(), if \a index is out of range.
556 _VECTOR_TEMPLATE_LIST
558 _VECTOR_CLASS_TYPE::Iterator
559 _VECTOR_CLASS_NAME::IteratorForIndex(int32 index
)
561 if (index
>= 0 && index
<= fItemCount
)
562 return Iterator(fItems
+ index
);
567 /*! \brief Returns an iterator for a given index.
568 \return An iterator referring to the same element as \a index, or
569 End(), if \a index is out of range.
571 _VECTOR_TEMPLATE_LIST
573 _VECTOR_CLASS_TYPE::ConstIterator
574 _VECTOR_CLASS_NAME::IteratorForIndex(int32 index
) const
576 if (index
>= 0 && index
<= fItemCount
)
577 return ConstIterator(fItems
+ index
);
582 /*! \brief Returns the element at a given index.
583 \param index The index identifying the element to be returned.
584 \return The element identified by the given index.
586 _VECTOR_TEMPLATE_LIST
589 _VECTOR_CLASS_NAME::ElementAt(int32 index
) const
591 if (index
>= 0 && index
< fItemCount
)
592 return fItems
[index
];
593 // Return the 0th element by default. Unless the allocation failed, there
594 // is always a 0th element -- uninitialized perhaps.
599 /*! \brief Returns the element at a given index.
600 \param index The index identifying the element to be returned.
601 \return The element identified by the given index.
603 _VECTOR_TEMPLATE_LIST
606 _VECTOR_CLASS_NAME::ElementAt(int32 index
)
608 if (index
>= 0 && index
< fItemCount
)
609 return fItems
[index
];
610 // Return the 0th element by default. Unless the allocation failed, there
611 // is always a 0th element -- uninitialized perhaps.
616 /*! \brief Returns the index of the next element with the specified value.
617 \param value The value of the element to be found.
618 \param start The index at which to be started to search for the element.
619 \return The index of the found element, or \c -1, if no further element
620 with the given value could be found or \a index is out of range.
622 _VECTOR_TEMPLATE_LIST
624 _VECTOR_CLASS_NAME::IndexOf(const Value
&value
, int32 start
) const
627 for (int32 i
= start
; i
< fItemCount
; i
++) {
628 if (fItems
[i
] == value
)
636 /*! \brief Returns an iterator referring to the next element with the
638 \param value The value of the element to be found.
639 \return An iterator referring to the found element, or End(), if no
640 further with the given value could be found.
642 _VECTOR_TEMPLATE_LIST
644 _VECTOR_CLASS_TYPE::Iterator
645 _VECTOR_CLASS_NAME::Find(const Value
&value
)
647 return Find(value
, Begin());
651 /*! \brief Returns an iterator referring to the next element with the
653 \param value The value of the element to be found.
654 \param start And iterator specifying where to start searching for the
656 \return An iterator referring to the found element, or End(), if no
657 further with the given value could be found or \a start was
660 _VECTOR_TEMPLATE_LIST
661 _VECTOR_CLASS_TYPE::Iterator
662 _VECTOR_CLASS_NAME::Find(const Value
&value
, const Iterator
&start
)
664 int32 index
= IndexOf(value
, _IteratorIndex(start
));
666 return Iterator(fItems
+ index
);
671 /*! \brief Returns an iterator referring to the of the next element with the
673 \param value The value of the element to be found.
674 \return An iterator referring to the found element, or End(), if no
675 further with the given value could be found.
677 _VECTOR_TEMPLATE_LIST
679 _VECTOR_CLASS_TYPE::ConstIterator
680 _VECTOR_CLASS_NAME::Find(const Value
&value
) const
682 return Find(value
, Begin());
686 /*! \brief Returns an iterator referring to the of the next element with the
688 \param value The value of the element to be found.
689 \param start And iterator specifying where to start searching for the
691 \return An iterator referring to the found element, or End(), if no
692 further with the given value could be found or \a start was
695 _VECTOR_TEMPLATE_LIST
696 _VECTOR_CLASS_TYPE::ConstIterator
697 _VECTOR_CLASS_NAME::Find(const Value
&value
, const ConstIterator
&start
) const
699 int32 index
= IndexOf(value
, _IteratorIndex(start
));
701 return ConstIterator(fItems
+ index
);
706 /*! \brief Semantically equivalent to ElementAt().
708 _VECTOR_TEMPLATE_LIST
711 _VECTOR_CLASS_NAME::operator[](int32 index
)
713 return ElementAt(index
);
717 /*! \brief Semantically equivalent to ElementAt().
719 _VECTOR_TEMPLATE_LIST
722 _VECTOR_CLASS_NAME::operator[](int32 index
) const
724 return ElementAt(index
);
728 /*! \brief Resizes the vector.
730 The internal element array will be grown or shrunk to the next multiple
731 of \a fChunkSize >= \a count, but no less than \a fChunkSize.
733 Also adjusts \a fItemCount according to the supplied \a count, but does
734 not invoke a destructor or constructor on any element.
736 \param count The number of element.
737 \return \c true, if everything went fine, \c false, if the memory
740 _VECTOR_TEMPLATE_LIST
742 _VECTOR_CLASS_NAME::_Resize(size_t count
)
745 // calculate the new capacity
746 int32 newSize
= count
;
749 newSize
= ((newSize
- 1) / fChunkSize
+ 1) * fChunkSize
;
750 // resize if necessary
751 if ((size_t)newSize
!= fCapacity
) {
752 Value
* newItems
= (Value
*)realloc(fItems
, newSize
* sizeof(Value
));
765 /*! \brief Returns index of the element the supplied iterator refers to.
766 \return The index of the element the supplied iterator refers to, or
767 \c -1, if the iterator is invalid (End() is considered valid
768 here, and Count() is returned).
770 _VECTOR_TEMPLATE_LIST
773 _VECTOR_CLASS_NAME::_IteratorIndex(const Iterator
&iterator
) const
775 if (iterator
.Element()) {
776 int32 index
= iterator
.Element() - fItems
;
777 if (index
>= 0 && index
<= fItemCount
)
784 /*! \brief Returns index of the element the supplied iterator refers to.
785 \return The index of the element the supplied iterator refers to, or
786 \c -1, if the iterator is invalid (End() is considered valid
787 here, and Count() is returned).
789 _VECTOR_TEMPLATE_LIST
792 _VECTOR_CLASS_NAME::_IteratorIndex(const ConstIterator
&iterator
) const
794 if (iterator
.Element()) {
795 int32 index
= iterator
.Element() - fItems
;
796 if (index
>= 0 && index
<= fItemCount
)