btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / private / kernel / util / Vector.h
blob6a90cdc3aa326f2166915e12fba927022b642c3f
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.
28 #ifndef _VECTOR_H
29 #define _VECTOR_H
31 #include <stdlib.h>
32 #include <string.h>
34 #include <SupportDefs.h>
35 #include <util/kernel_cpp.h>
37 template<typename Value> class VectorIterator;
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>
44 /*!
45 \class Vector
46 \brief A generic vector implementation.
48 template<typename Value>
49 class Vector {
50 public:
51 typedef VectorIterator<Value> Iterator;
52 typedef VectorIterator<const Value> ConstIterator;
54 private:
55 static const size_t kDefaultChunkSize = 10;
56 static const size_t kMaximalChunkSize = 1024 * 1024;
58 public:
59 Vector(size_t chunkSize = kDefaultChunkSize);
60 ~Vector();
62 status_t PushFront(const Value &value);
63 status_t PushBack(const Value &value);
65 void PopFront();
66 void PopBack();
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;
80 void MakeEmpty();
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;
103 // debugging
104 int32 GetCapacity() const { return fCapacity; }
106 private:
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;
112 private:
113 size_t fCapacity;
114 size_t fChunkSize;
115 int32 fItemCount;
116 Value *fItems;
120 // VectorIterator
121 template<typename Value>
122 class VectorIterator {
123 private:
124 typedef VectorIterator<Value> Iterator;
126 public:
127 inline VectorIterator<Value>()
128 : fElement(NULL)
132 inline VectorIterator<Value>(const Iterator &other)
133 : fElement(other.fElement)
137 inline Iterator &operator++()
139 if (fElement)
140 ++fElement;
141 return *this;
144 inline Iterator operator++(int)
146 Iterator it(*this);
147 ++*this;
148 return it;
151 inline Iterator &operator--()
153 if (fElement)
154 --fElement;
155 return *this;
158 inline Iterator operator--(int)
160 Iterator it(*this);
161 --*this;
162 return it;
165 inline Iterator &operator=(const Iterator &other)
167 fElement = other.fElement;
168 return *this;
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
184 return *fElement;
187 inline Value *operator->() const
189 return fElement;
192 inline operator bool() const
194 return fElement;
197 // private
198 public:
199 inline VectorIterator<Value>(Value *element)
200 : fElement(element)
204 inline Value *Element() const
206 return fElement;
209 protected:
210 Value *fElement;
214 // Vector
216 // constructor
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
220 necessary.
222 _VECTOR_TEMPLATE_LIST
223 _VECTOR_CLASS_NAME::Vector(size_t chunkSize)
224 : fCapacity(0),
225 fChunkSize(chunkSize),
226 fItemCount(0),
227 fItems(NULL)
229 if (fChunkSize == 0 || fChunkSize > kMaximalChunkSize)
230 fChunkSize = kDefaultChunkSize;
231 _Resize(0);
234 // destructor
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
239 it points to.
241 _VECTOR_TEMPLATE_LIST
242 _VECTOR_CLASS_NAME::~Vector()
244 MakeEmpty();
245 free(fItems);
248 // PushFront
249 /*! \brief Inserts a copy of the supplied value at the beginning of the
250 vector.
251 \param value The element to be inserted.
252 \return
253 - \c B_OK: Everything went fine.
254 - \c B_NO_MEMORY: Insufficient memory for this operation.
256 _VECTOR_TEMPLATE_LIST
257 status_t
258 _VECTOR_CLASS_NAME::PushFront(const Value &value)
260 return Insert(value, 0);
263 // PushBack
264 /*! \brief Inserts a copy of the supplied value at the end of the vector.
265 \param value The element to be inserted.
266 \return
267 - \c B_OK: Everything went fine.
268 - \c B_NO_MEMORY: Insufficient memory for this operation.
270 _VECTOR_TEMPLATE_LIST
271 status_t
272 _VECTOR_CLASS_NAME::PushBack(const Value &value)
274 return Insert(value, fItemCount);
277 // PopFront
278 /*! \brief Removes the first element of the vector.
280 Invocation on an empty vector is harmless.
282 _VECTOR_TEMPLATE_LIST
283 void
284 _VECTOR_CLASS_NAME::PopFront()
286 if (fItemCount > 0)
287 Erase(0);
290 // PopBack
291 /*! \brief Removes the last element of the vector.
293 Invocation on an empty vector is harmless.
295 _VECTOR_TEMPLATE_LIST
296 void
297 _VECTOR_CLASS_NAME::PopBack()
299 if (fItemCount > 0)
300 Erase(fItemCount - 1);
303 // _MoveItems
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
307 negative.
308 \param count The number of elements to be moved.
310 _VECTOR_TEMPLATE_LIST
311 inline
312 void
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));
319 // Insert
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().
324 \return
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
330 status_t
331 _VECTOR_CLASS_NAME::Insert(const Value &value, int32 index)
333 if (index < 0 || index > fItemCount)
334 return B_BAD_VALUE;
335 if (!_Resize(fItemCount + 1))
336 return B_NO_MEMORY;
337 _MoveItems(fItems + index, 1, fItemCount - index - 1);
338 new(fItems + index) Value(value);
339 return B_OK;
342 // Insert
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
346 the new element.
347 \return
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
353 status_t
354 _VECTOR_CLASS_NAME::Insert(const Value &value, const Iterator &iterator)
356 int32 index = _IteratorIndex(iterator);
357 if (index >= 0)
358 return Insert(value, index);
359 return B_BAD_VALUE;
362 // Remove
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
368 int32
369 _VECTOR_CLASS_NAME::Remove(const Value &value)
371 int32 count = 0;
372 for (int32 i = fItemCount - 1; i >= 0; i--) {
373 if (ElementAt(i) == value) {
374 Erase(i);
375 count++;
378 return count;
381 // Erase
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);
398 return Null();
401 // Erase
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)
415 return Erase(index);
416 return Null();
419 // Count
420 /*! \brief Returns the number of elements the vector contains.
421 \return The number of elements the vector contains.
423 _VECTOR_TEMPLATE_LIST
424 inline
425 int32
426 _VECTOR_CLASS_NAME::Count() const
428 return fItemCount;
431 // IsEmpty
432 /*! \brief Returns whether the vector is empty.
433 \return \c true, if the vector is empty, \c false otherwise.
435 _VECTOR_TEMPLATE_LIST
436 inline
437 bool
438 _VECTOR_CLASS_NAME::IsEmpty() const
440 return (fItemCount == 0);
443 // MakeEmpty
444 /*! \brief Removes all elements from the vector.
446 _VECTOR_TEMPLATE_LIST
447 void
448 _VECTOR_CLASS_NAME::MakeEmpty()
450 for (int32 i = 0; i < fItemCount; i++)
451 fItems[i].~Value();
452 _Resize(0);
455 // Begin
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
464 inline
465 _VECTOR_CLASS_TYPE::Iterator
466 _VECTOR_CLASS_NAME::Begin()
468 return Iterator(fItems);
471 // Begin
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
480 inline
481 _VECTOR_CLASS_TYPE::ConstIterator
482 _VECTOR_CLASS_NAME::Begin() const
484 return ConstIterator(fItems);
487 // End
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
496 inline
497 _VECTOR_CLASS_TYPE::Iterator
498 _VECTOR_CLASS_NAME::End()
500 return Iterator(fItems + fItemCount);
503 // End
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
512 inline
513 _VECTOR_CLASS_TYPE::ConstIterator
514 _VECTOR_CLASS_NAME::End() const
516 return ConstIterator(fItems + fItemCount);
519 // Null
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
528 inline
529 _VECTOR_CLASS_TYPE::Iterator
530 _VECTOR_CLASS_NAME::Null()
532 return Iterator(NULL);
535 // 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
544 inline
545 _VECTOR_CLASS_TYPE::ConstIterator
546 _VECTOR_CLASS_NAME::Null() const
548 return ConstIterator(NULL);
551 // IteratorForIndex
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
557 inline
558 _VECTOR_CLASS_TYPE::Iterator
559 _VECTOR_CLASS_NAME::IteratorForIndex(int32 index)
561 if (index >= 0 && index <= fItemCount)
562 return Iterator(fItems + index);
563 return End();
566 // IteratorForIndex
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
572 inline
573 _VECTOR_CLASS_TYPE::ConstIterator
574 _VECTOR_CLASS_NAME::IteratorForIndex(int32 index) const
576 if (index >= 0 && index <= fItemCount)
577 return ConstIterator(fItems + index);
578 return End();
581 // ElementAt
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
587 inline
588 const Value &
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.
595 return fItems[0];
598 // ElementAt
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
604 inline
605 Value &
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.
612 return fItems[0];
615 // IndexOf
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
623 int32
624 _VECTOR_CLASS_NAME::IndexOf(const Value &value, int32 start) const
626 if (start >= 0) {
627 for (int32 i = start; i < fItemCount; i++) {
628 if (fItems[i] == value)
629 return i;
632 return -1;
635 // Find
636 /*! \brief Returns an iterator referring to the next element with the
637 specified value.
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
643 inline
644 _VECTOR_CLASS_TYPE::Iterator
645 _VECTOR_CLASS_NAME::Find(const Value &value)
647 return Find(value, Begin());
650 // Find
651 /*! \brief Returns an iterator referring to the next element with the
652 specified value.
653 \param value The value of the element to be found.
654 \param start And iterator specifying where to start searching for the
655 element.
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
658 invalid.
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));
665 if (index >= 0)
666 return Iterator(fItems + index);
667 return End();
670 // Find
671 /*! \brief Returns an iterator referring to the of the next element with the
672 specified value.
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
678 inline
679 _VECTOR_CLASS_TYPE::ConstIterator
680 _VECTOR_CLASS_NAME::Find(const Value &value) const
682 return Find(value, Begin());
685 // Find
686 /*! \brief Returns an iterator referring to the of the next element with the
687 specified value.
688 \param value The value of the element to be found.
689 \param start And iterator specifying where to start searching for the
690 element.
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
693 invalid.
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));
700 if (index >= 0)
701 return ConstIterator(fItems + index);
702 return End();
705 // []
706 /*! \brief Semantically equivalent to ElementAt().
708 _VECTOR_TEMPLATE_LIST
709 inline
710 Value &
711 _VECTOR_CLASS_NAME::operator[](int32 index)
713 return ElementAt(index);
716 // []
717 /*! \brief Semantically equivalent to ElementAt().
719 _VECTOR_TEMPLATE_LIST
720 inline
721 const Value &
722 _VECTOR_CLASS_NAME::operator[](int32 index) const
724 return ElementAt(index);
727 // _Resize
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
738 allocation failed.
740 _VECTOR_TEMPLATE_LIST
741 bool
742 _VECTOR_CLASS_NAME::_Resize(size_t count)
744 bool result = true;
745 // calculate the new capacity
746 int32 newSize = count;
747 if (newSize <= 0)
748 newSize = 1;
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));
753 if (newItems) {
754 fItems = newItems;
755 fCapacity = newSize;
756 } else
757 result = false;
759 if (result)
760 fItemCount = count;
761 return result;
764 // _IteratorIndex
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
771 inline
772 int32
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)
778 return index;
780 return -1;
783 // _IteratorIndex
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
790 inline
791 int32
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)
797 return index;
799 return -1;
802 #endif // _VECTOR_H