btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / private / kernel / util / VectorMap.h
blob0c5cf001845c9037397ec28c2d7d5b9d1971146f
1 // VectorMap.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_MAP_H
29 #define _VECTOR_MAP_H
31 #include <stdlib.h>
32 #include <string.h>
34 #include <SupportDefs.h>
36 #include <util/kernel_cpp.h>
37 #include <KernelUtilsOrder.h>
38 #include <Vector.h>
40 namespace VectorMapEntryStrategy {
41 // Pair
42 template<typename Key, typename Value,
43 typename KeyOrder = KernelUtilsOrder::Ascending<Key> > class Pair;
44 // ImplicitKey
45 template<typename Key, typename Value, typename GetKey,
46 typename KeyOrder = KernelUtilsOrder::Ascending<Key> >
47 class ImplicitKey;
50 template<typename Entry, typename Parent, typename EntryIterator>
51 class VectorMapIterator;
52 template<typename _Key, typename _Value, typename Entry, typename Parent>
53 class VectorMapEntry;
55 // for convenience
56 #define _VECTOR_MAP_TEMPLATE_LIST template<typename Key, typename Value, \
57 typename EntryStrategy>
58 #define _VECTOR_MAP_CLASS_NAME VectorMap<Key, Value, EntryStrategy>
59 #define _VECTOR_MAP_CLASS_TYPE typename VectorMap<Key, Value, EntryStrategy>
61 /*!
62 \class VectorMap
63 \brief A generic vector-based map implementation.
65 The map entries are ordered according to the supplied
66 compare function object. Default is ascending order.
68 Note that VectorMap::Entry is not the same class as EntryStrategy::Entry.
69 It is light-weight class, an object of which is returned when a iterator
70 is dereferenced. It features a Key() and a Value() method returning
71 references to the entry's key/value. This allows EntryStrategy::Entry
72 to be an arbitrary class, not needing to implement a certain interface.
74 template<typename Key, typename Value,
75 typename EntryStrategy = VectorMapEntryStrategy::Pair<Key, Value> >
76 class VectorMap {
77 private:
78 typedef _VECTOR_MAP_CLASS_NAME Class;
79 typedef typename EntryStrategy::Entry _Entry;
80 typedef typename EntryStrategy::KeyReference KeyReference;
81 typedef Vector<_Entry> ElementVector;
83 public:
84 typedef VectorMapEntry<KeyReference, Value, _Entry, Class>
85 Entry;
86 typedef VectorMapEntry<KeyReference, const Value, const _Entry,
87 const Class> ConstEntry;
88 typedef VectorMapIterator<Entry, Class, typename ElementVector::Iterator>
89 Iterator;
90 typedef VectorMapIterator<ConstEntry, const Class, typename ElementVector::ConstIterator>
91 ConstIterator;
93 private:
94 static const size_t kDefaultChunkSize = 10;
95 static const size_t kMaximalChunkSize = 1024 * 1024;
97 public:
98 VectorMap(size_t chunkSize = kDefaultChunkSize);
99 // TODO: Copy constructor, assignment operator.
100 ~VectorMap();
102 status_t Insert(const Key &key, const Value &value);
103 status_t Put(const Key &key, const Value &value);
104 Value &Get(const Key &key);
105 const Value &Get(const Key &key) const;
107 int32 Remove(const Key &key);
108 Iterator Erase(const Iterator &iterator);
110 inline int32 Count() const;
111 inline bool IsEmpty() const;
112 void MakeEmpty();
114 inline Iterator Begin();
115 inline ConstIterator Begin() const;
116 inline Iterator End();
117 inline ConstIterator End() const;
118 inline Iterator Null();
119 inline ConstIterator Null() const;
121 Iterator Find(const Key &key);
122 ConstIterator Find(const Key &key) const;
123 Iterator FindClose(const Key &key, bool less);
124 ConstIterator FindClose(const Key &key, bool less) const;
126 private:
127 int32 _FindInsertionIndex(const Key &key, bool &exists) const;
129 private:
130 // friend class Entry;
131 // friend class ConstEntry;
132 friend class VectorMapEntry<KeyReference, Value, _Entry, Class>;
133 friend class VectorMapEntry<KeyReference, const Value, const _Entry,
134 const Class>;
136 ElementVector fElements;
137 EntryStrategy fEntryStrategy;
141 // VectorMapEntry
142 template<typename KeyReference, typename _Value, typename Entry,
143 typename Parent>
144 class VectorMapEntry {
145 private:
146 typedef VectorMapEntry<KeyReference, _Value, Entry, Parent> Class;
148 public:
149 VectorMapEntry()
150 : fParent(NULL), fEntry(NULL) {}
152 inline KeyReference Key() const
154 return fParent->fEntryStrategy.GetKey(*fEntry);
157 inline _Value &Value() const
159 return fParent->fEntryStrategy.GetValue(*fEntry);
162 inline const Class *operator->() const
164 return this;
167 // private
168 public:
169 VectorMapEntry(Parent *parent, Entry *entry)
170 : fParent(parent), fEntry(entry) {}
172 private:
173 const Parent *fParent;
174 Entry *fEntry;
178 // VectorMapIterator
179 template<typename Entry, typename Parent, typename EntryIterator>
180 class VectorMapIterator {
181 private:
182 typedef VectorMapIterator<Entry, Parent, EntryIterator> Iterator;
184 public:
185 inline VectorMapIterator()
186 : fParent(NULL),
187 fIterator()
191 inline VectorMapIterator(
192 const Iterator &other)
193 : fParent(other.fParent),
194 fIterator(other.fIterator)
198 inline Iterator &operator++()
200 ++fIterator;
201 return *this;
204 inline Iterator operator++(int)
206 Iterator it(*this);
207 ++*this;
208 return it;
211 inline Iterator &operator--()
213 --fIterator;
214 return *this;
217 inline Iterator operator--(int)
219 Iterator it(*this);
220 --*this;
221 return it;
224 inline Iterator &operator=(const Iterator &other)
226 fParent = other.fParent;
227 fIterator = other.fIterator;
228 return *this;
231 inline bool operator==(const Iterator &other) const
233 return (fParent == other.fParent && fIterator == other.fIterator);
236 inline bool operator!=(const Iterator &other) const
238 return !(*this == other);
241 inline Entry operator*() const
243 return Entry(fParent, &*fIterator);
246 inline Entry operator->() const
248 return Entry(fParent, &*fIterator);
251 inline operator bool() const
253 return fIterator;
256 // private
257 public:
258 inline VectorMapIterator(Parent *parent, const EntryIterator &iterator)
259 : fParent(parent),
260 fIterator(iterator)
264 inline EntryIterator &GetIterator()
266 return fIterator;
269 inline const EntryIterator &GetIterator() const
271 return fIterator;
274 protected:
275 Parent *fParent;
276 EntryIterator fIterator;
280 // VectorMap
282 // constructor
283 /*! \brief Creates an empty map.
284 \param chunkSize The granularity for the underlying vector's capacity,
285 i.e. the minimal number of elements the capacity grows or shrinks
286 when necessary.
288 _VECTOR_MAP_TEMPLATE_LIST
289 _VECTOR_MAP_CLASS_NAME::VectorMap(size_t chunkSize)
290 : fElements(chunkSize)
294 // destructor
295 /*! \brief Frees all resources associated with the object.
297 The contained keys and values are destroyed. Note, that for pointer
298 types only the pointer is destroyed, not the object it points to.
300 _VECTOR_MAP_TEMPLATE_LIST
301 _VECTOR_MAP_CLASS_NAME::~VectorMap()
305 // Insert
306 /*! \brief Associates a key with a value.
308 If there is already a value associated with the key, the old entry
309 is replaced.
311 \param key The key to which a value shall be associated.
312 \param value The value to be associated with the key.
313 \return
314 - \c B_OK: Everything went fine.
315 - \c B_NO_MEMORY: Insufficient memory for this operation.
316 - \c B_BAD_VALUE: The map's EntryStrategy requires some special
317 relationship between key and value, that \a key and \a value haven't
318 (doesn't apply to the default strategy).
320 _VECTOR_MAP_TEMPLATE_LIST
321 status_t
322 _VECTOR_MAP_CLASS_NAME::Insert(const Key &key, const Value &value)
324 if (!fEntryStrategy.AreCompatible(key, value))
325 return B_BAD_VALUE;
326 bool exists = false;
327 int32 index = _FindInsertionIndex(key, exists);
328 if (exists) {
329 fElements[index] = fEntryStrategy.MakeEntry(key, value);
330 return B_OK;
332 return fElements.Insert(fEntryStrategy.MakeEntry(key, value), index);
335 // Put
336 /*! \brief Equivalent to Insert().
338 _VECTOR_MAP_TEMPLATE_LIST
339 inline
340 status_t
341 _VECTOR_MAP_CLASS_NAME::Put(const Key &key, const Value &value)
343 return Insert(key, value);
346 // Get
347 /*! \brief Returns the value associated with a given key.
349 \note Invoking this method for a key not know to the map is dangerous!
350 The behavior is unspecified. It may even crash.
352 \param key The key to be looked up.
353 \return The value associated with \a key.
355 _VECTOR_MAP_TEMPLATE_LIST
356 Value &
357 _VECTOR_MAP_CLASS_NAME::Get(const Key &key)
359 bool exists = false;
360 int32 index = _FindInsertionIndex(key, exists);
361 if (!exists)
362 return fEntryStrategy.GetValue(fElements[0]);
363 return fEntryStrategy.GetValue(fElements[index]);
366 // Get
367 /*! \brief Returns the value associated with a given key.
369 \note Invoking this method for a key not know to the map is dangerous!
370 The behavior is unspecified. It may even crash.
372 \param key The key to be looked up.
373 \return The value associated with \a key.
375 _VECTOR_MAP_TEMPLATE_LIST
376 const Value &
377 _VECTOR_MAP_CLASS_NAME::Get(const Key &key) const
379 bool exists = false;
380 int32 index = _FindInsertionIndex(key, exists);
381 if (!exists)
382 return fEntryStrategy.GetValue(fElements[0]);
383 return fEntryStrategy.GetValue(fElements[index]);
386 // Remove
387 /*! \brief Removes the entry with the supplied key.
388 \param key The key to be removed.
389 \return The number of removed occurrences, i.e. \c 1, if the map
390 contained an entry with that key, \c 0 otherwise.
392 _VECTOR_MAP_TEMPLATE_LIST
393 int32
394 _VECTOR_MAP_CLASS_NAME::Remove(const Key &key)
396 bool exists = false;
397 int32 index = _FindInsertionIndex(key, exists);
398 if (!exists)
399 return 0;
400 fElements.Erase(index);
401 return 1;
404 // Erase
405 /*! \brief Removes the entry at the given position.
406 \param iterator An iterator referring to the entry to be removed.
407 \return An iterator referring to the entry succeeding the removed
408 one (End(), if it was the last element that has been
409 removed), or Null(), if \a iterator was an invalid iterator
410 (in this case including End()).
412 _VECTOR_MAP_TEMPLATE_LIST
413 _VECTOR_MAP_CLASS_TYPE::Iterator
414 _VECTOR_MAP_CLASS_NAME::Erase(const Iterator &iterator)
416 return Iterator(this, fElements.Erase(iterator.GetIterator()));
419 // Count
420 /*! \brief Returns the number of entry the map contains.
421 \return The number of entries the map contains.
423 _VECTOR_MAP_TEMPLATE_LIST
424 inline
425 int32
426 _VECTOR_MAP_CLASS_NAME::Count() const
428 return fElements.Count();
431 // IsEmpty
432 /*! \brief Returns whether the map is empty.
433 \return \c true, if the map is empty, \c false otherwise.
435 _VECTOR_MAP_TEMPLATE_LIST
436 inline
437 bool
438 _VECTOR_MAP_CLASS_NAME::IsEmpty() const
440 return fElements.IsEmpty();
443 // MakeEmpty
444 /*! \brief Removes all entries from the map.
446 _VECTOR_MAP_TEMPLATE_LIST
447 void
448 _VECTOR_MAP_CLASS_NAME::MakeEmpty()
450 fElements.MakeEmpty();
453 // Begin
454 /*! \brief Returns an iterator referring to the beginning of the map.
456 If the map is not empty, Begin() refers to its first entry,
457 otherwise it is equal to End() and must not be dereferenced!
459 \return An iterator referring to the beginning of the map.
461 _VECTOR_MAP_TEMPLATE_LIST
462 inline
463 _VECTOR_MAP_CLASS_TYPE::Iterator
464 _VECTOR_MAP_CLASS_NAME::Begin()
466 return Iterator(this, fElements.Begin());
469 // Begin
470 /*! \brief Returns an iterator referring to the beginning of the map.
472 If the map is not empty, Begin() refers to its first entry,
473 otherwise it is equal to End() and must not be dereferenced!
475 \return An iterator referring to the beginning of the map.
477 _VECTOR_MAP_TEMPLATE_LIST
478 inline
479 _VECTOR_MAP_CLASS_TYPE::ConstIterator
480 _VECTOR_MAP_CLASS_NAME::Begin() const
482 return ConstIterator(this, fElements.Begin());
485 // End
486 /*! \brief Returns an iterator referring to the end of the map.
488 The position identified by End() is the one succeeding the last
489 entry, i.e. it must not be dereferenced!
491 \return An iterator referring to the end of the map.
493 _VECTOR_MAP_TEMPLATE_LIST
494 inline
495 _VECTOR_MAP_CLASS_TYPE::Iterator
496 _VECTOR_MAP_CLASS_NAME::End()
498 return Iterator(this, fElements.End());
501 // End
502 /*! \brief Returns an iterator referring to the end of the map.
504 The position identified by End() is the one succeeding the last
505 entry, i.e. it must not be dereferenced!
507 \return An iterator referring to the end of the map.
509 _VECTOR_MAP_TEMPLATE_LIST
510 inline
511 _VECTOR_MAP_CLASS_TYPE::ConstIterator
512 _VECTOR_MAP_CLASS_NAME::End() const
514 return ConstIterator(this, fElements.End());
517 // Null
518 /*! \brief Returns an invalid iterator.
520 Null() is used as a return value, if something went wrong. It must
521 neither be incremented or decremented nor dereferenced!
523 \return An invalid iterator.
525 _VECTOR_MAP_TEMPLATE_LIST
526 inline
527 _VECTOR_MAP_CLASS_TYPE::Iterator
528 _VECTOR_MAP_CLASS_NAME::Null()
530 return Iterator(this, fElements.Null());
533 // Null
534 /*! \brief Returns an invalid iterator.
536 Null() is used as a return value, if something went wrong. It must
537 neither be incremented or decremented nor dereferenced!
539 \return An invalid iterator.
541 _VECTOR_MAP_TEMPLATE_LIST
542 inline
543 _VECTOR_MAP_CLASS_TYPE::ConstIterator
544 _VECTOR_MAP_CLASS_NAME::Null() const
546 return ConstIterator(this, fElements.Null());
549 // Find
550 /*! \brief Returns an iterator referring to the entry with the
551 specified key.
552 \param key The key of the entry to be found.
553 \return An iterator referring to the found entry, or End(), if the
554 map doesn't contain any entry with the given value.
556 _VECTOR_MAP_TEMPLATE_LIST
557 _VECTOR_MAP_CLASS_TYPE::Iterator
558 _VECTOR_MAP_CLASS_NAME::Find(const Key &key)
560 bool exists = false;
561 int32 index = _FindInsertionIndex(key, exists);
562 if (!exists)
563 return End();
564 return Iterator(this, fElements.IteratorForIndex(index));
567 // Find
568 /*! \brief Returns an iterator referring to the entry with the
569 specified key.
570 \param key The key of the entry to be found.
571 \return An iterator referring to the found entry, or End(), if the
572 map doesn't contain any entry with the given value.
574 _VECTOR_MAP_TEMPLATE_LIST
575 _VECTOR_MAP_CLASS_TYPE::ConstIterator
576 _VECTOR_MAP_CLASS_NAME::Find(const Key &key) const
578 bool exists = false;
579 int32 index = _FindInsertionIndex(key, exists);
580 if (!exists)
581 return End();
582 return ConstIterator(this, fElements.IteratorForIndex(index));
585 // FindClose
586 /*! \brief Returns an iterator referring to the entry with a key closest
587 to the specified one.
589 If the map contains an entry with the specified key, an iterator
590 to it is returned. Otherwise \a less indicates whether an iterator to
591 the entry with an directly smaller or greater key shall be returned.
593 If \a less is \c true and the first entry in the map has a greater
594 key than the specified one, End() is returned. Similarly, when \a less
595 is \c false and the last entry's key is smaller. Find() invoked on an
596 empty map always returns End().
598 Note, that the key order used for the set is specified as template
599 argument to the class. Default is ascending order. Descending order
600 inverts the meaning of \a less, i.e. if \c true, greater values will
601 be returned, since they are smaller ones according to the order.
603 \param value The key of the entry to be found.
604 \return An iterator referring to the found entry, or End(), if the
605 map doesn't contain any entry with the given key or a close
606 one according to \a less.
608 _VECTOR_MAP_TEMPLATE_LIST
609 _VECTOR_MAP_CLASS_TYPE::Iterator
610 _VECTOR_MAP_CLASS_NAME::FindClose(const Key &key, bool less)
612 bool exists = false;
613 int32 index = _FindInsertionIndex(key, exists);
614 // If not found, the index _FindInsertionIndex() returns will point to
615 // an element with a greater value or to End(). So, no special handling
616 // is needed for !less.
617 if (exists || !less)
618 return Iterator(this, fElements.IteratorForIndex(index));
619 // An element with a smaller value is desired. The previous one (if any)
620 // will do.
621 if (index > 0)
622 return Iterator(this, fElements.IteratorForIndex(index - 1));
623 return End();
626 // FindClose
627 /*! \brief Returns an iterator referring to the entry with a key closest
628 to the specified one.
630 If the map contains an entry with the specified key, an iterator
631 to it is returned. Otherwise \a less indicates whether an iterator to
632 the entry with an directly smaller or greater key shall be returned.
634 If \a less is \c true and the first entry in the map has a greater
635 key than the specified one, End() is returned. Similarly, when \a less
636 is \c false and the last entry's key is smaller. Find() invoked on an
637 empty map always returns End().
639 Note, that the key order used for the set is specified as template
640 argument to the class. Default is ascending order. Descending order
641 inverts the meaning of \a less, i.e. if \c true, greater values will
642 be returned, since they are smaller ones according to the order.
644 \param value The key of the entry to be found.
645 \return An iterator referring to the found entry, or End(), if the
646 map doesn't contain any entry with the given key or a close
647 one according to \a less.
649 _VECTOR_MAP_TEMPLATE_LIST
650 _VECTOR_MAP_CLASS_TYPE::ConstIterator
651 _VECTOR_MAP_CLASS_NAME::FindClose(const Key &key, bool less) const
653 bool exists = false;
654 int32 index = _FindInsertionIndex(key, exists);
655 // If not found, the index _FindInsertionIndex() returns will point to
656 // an element with a greater value or to End(). So, no special handling
657 // is needed for !less.
658 if (exists || !less)
659 return ConstIterator(this, fElements.IteratorForIndex(index));
660 // An element with a smaller value is desired. The previous one (if any)
661 // will do.
662 if (index > 0)
663 return ConstIterator(this, fElements.IteratorForIndex(index - 1));
664 return End();
667 // _FindInsertionIndex
668 /*! \brief Finds the index at which the entry with the supplied key is
669 located or at which it would need to be inserted.
670 \param key The key.
671 \param exists Is set to \c true, if the map does already contain an
672 entry with that key, to \c false otherwise.
673 \return The index at which the entry with the supplied key is
674 located or at which it would need to be inserted.
676 _VECTOR_MAP_TEMPLATE_LIST
677 int32
678 _VECTOR_MAP_CLASS_NAME::_FindInsertionIndex(const Key &key,
679 bool &exists) const
681 // binary search
682 int32 lower = 0;
683 int32 upper = Count();
684 while (lower < upper) {
685 int32 mid = (lower + upper) / 2;
686 int cmp = fEntryStrategy.Compare(fEntryStrategy.GetKey(fElements[mid]),
687 key);
688 if (cmp < 0)
689 lower = mid + 1;
690 else
691 upper = mid;
693 exists = (lower < Count() && fEntryStrategy.Compare(key,
694 fEntryStrategy.GetKey(fElements[lower])) == 0);
695 return lower;
699 // entry strategies
701 namespace VectorMapEntryStrategy {
703 // Pair
704 template<typename Key, typename Value, typename KeyOrder>
705 class Pair {
706 public:
707 typedef const Key &KeyReference;
709 class Entry {
710 public:
711 Entry(const Key &key, const Value &value)
712 : key(key), value(value) {}
714 Key key;
715 Value value;
718 inline KeyReference GetKey(const Entry &entry) const
720 return entry.key;
723 inline const Value &GetValue(const Entry &entry) const
725 return entry.value;
728 inline Value &GetValue(Entry &entry) const
730 return entry.value;
733 inline Entry MakeEntry(const Key &key, const Value &value) const
735 return Entry(key, value);
738 inline bool AreCompatible(const Key &, const Value &) const
740 return true;
743 inline int Compare(const Key &a, const Key &b) const
745 return fCompare(a, b);
748 private:
749 KeyOrder fCompare;
752 // ImplicitKey
753 template<typename Key, typename Value, typename _GetKey, typename KeyOrder>
754 class ImplicitKey {
755 public:
756 typedef Key KeyReference;
757 typedef Value Entry;
759 inline KeyReference GetKey(const Entry &entry) const
761 return fGetKey(entry);
764 inline const Value &GetValue(const Entry &entry) const
766 return entry;
769 inline Value &GetValue(Entry &entry) const
771 return entry;
774 inline Entry MakeEntry(const Key &, const Value &value) const
776 return value;
779 inline bool AreCompatible(const Key &key, const Value &value) const
781 return (fGetKey(value) == key);
784 inline int Compare(const Key &a, const Key &b) const
786 return fCompare(a, b);
789 private:
790 KeyOrder fCompare;
791 _GetKey fGetKey;
794 } // VectorMapEntryStrategy
796 #endif // _VECTOR_MAP_H