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>
36 #include <util/kernel_cpp.h>
37 #include <KernelUtilsOrder.h>
40 namespace VectorMapEntryStrategy
{
42 template<typename Key
, typename Value
,
43 typename KeyOrder
= KernelUtilsOrder::Ascending
<Key
> > class Pair
;
45 template<typename Key
, typename Value
, typename GetKey
,
46 typename KeyOrder
= KernelUtilsOrder::Ascending
<Key
> >
50 template<typename Entry
, typename Parent
, typename EntryIterator
>
51 class VectorMapIterator
;
52 template<typename _Key
, typename _Value
, typename Entry
, typename Parent
>
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>
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
> >
78 typedef _VECTOR_MAP_CLASS_NAME Class
;
79 typedef typename
EntryStrategy::Entry _Entry
;
80 typedef typename
EntryStrategy::KeyReference KeyReference
;
81 typedef Vector
<_Entry
> ElementVector
;
84 typedef VectorMapEntry
<KeyReference
, Value
, _Entry
, Class
>
86 typedef VectorMapEntry
<KeyReference
, const Value
, const _Entry
,
87 const Class
> ConstEntry
;
88 typedef VectorMapIterator
<Entry
, Class
, typename
ElementVector::Iterator
>
90 typedef VectorMapIterator
<ConstEntry
, const Class
, typename
ElementVector::ConstIterator
>
94 static const size_t kDefaultChunkSize
= 10;
95 static const size_t kMaximalChunkSize
= 1024 * 1024;
98 VectorMap(size_t chunkSize
= kDefaultChunkSize
);
99 // TODO: Copy constructor, assignment operator.
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;
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;
127 int32
_FindInsertionIndex(const Key
&key
, bool &exists
) const;
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
,
136 ElementVector fElements
;
137 EntryStrategy fEntryStrategy
;
142 template<typename KeyReference
, typename _Value
, typename Entry
,
144 class VectorMapEntry
{
146 typedef VectorMapEntry
<KeyReference
, _Value
, Entry
, Parent
> Class
;
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
169 VectorMapEntry(Parent
*parent
, Entry
*entry
)
170 : fParent(parent
), fEntry(entry
) {}
173 const Parent
*fParent
;
179 template<typename Entry
, typename Parent
, typename EntryIterator
>
180 class VectorMapIterator
{
182 typedef VectorMapIterator
<Entry
, Parent
, EntryIterator
> Iterator
;
185 inline VectorMapIterator()
191 inline VectorMapIterator(
192 const Iterator
&other
)
193 : fParent(other
.fParent
),
194 fIterator(other
.fIterator
)
198 inline Iterator
&operator++()
204 inline Iterator
operator++(int)
211 inline Iterator
&operator--()
217 inline Iterator
operator--(int)
224 inline Iterator
&operator=(const Iterator
&other
)
226 fParent
= other
.fParent
;
227 fIterator
= other
.fIterator
;
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
258 inline VectorMapIterator(Parent
*parent
, const EntryIterator
&iterator
)
264 inline EntryIterator
&GetIterator()
269 inline const EntryIterator
&GetIterator() const
276 EntryIterator fIterator
;
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
288 _VECTOR_MAP_TEMPLATE_LIST
289 _VECTOR_MAP_CLASS_NAME::VectorMap(size_t chunkSize
)
290 : fElements(chunkSize
)
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()
306 /*! \brief Associates a key with a value.
308 If there is already a value associated with the key, the old entry
311 \param key The key to which a value shall be associated.
312 \param value The value to be associated with the key.
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
322 _VECTOR_MAP_CLASS_NAME::Insert(const Key
&key
, const Value
&value
)
324 if (!fEntryStrategy
.AreCompatible(key
, value
))
327 int32 index
= _FindInsertionIndex(key
, exists
);
329 fElements
[index
] = fEntryStrategy
.MakeEntry(key
, value
);
332 return fElements
.Insert(fEntryStrategy
.MakeEntry(key
, value
), index
);
336 /*! \brief Equivalent to Insert().
338 _VECTOR_MAP_TEMPLATE_LIST
341 _VECTOR_MAP_CLASS_NAME::Put(const Key
&key
, const Value
&value
)
343 return Insert(key
, value
);
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
357 _VECTOR_MAP_CLASS_NAME::Get(const Key
&key
)
360 int32 index
= _FindInsertionIndex(key
, exists
);
362 return fEntryStrategy
.GetValue(fElements
[0]);
363 return fEntryStrategy
.GetValue(fElements
[index
]);
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
377 _VECTOR_MAP_CLASS_NAME::Get(const Key
&key
) const
380 int32 index
= _FindInsertionIndex(key
, exists
);
382 return fEntryStrategy
.GetValue(fElements
[0]);
383 return fEntryStrategy
.GetValue(fElements
[index
]);
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
394 _VECTOR_MAP_CLASS_NAME::Remove(const Key
&key
)
397 int32 index
= _FindInsertionIndex(key
, exists
);
400 fElements
.Erase(index
);
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()));
420 /*! \brief Returns the number of entry the map contains.
421 \return The number of entries the map contains.
423 _VECTOR_MAP_TEMPLATE_LIST
426 _VECTOR_MAP_CLASS_NAME::Count() const
428 return fElements
.Count();
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
438 _VECTOR_MAP_CLASS_NAME::IsEmpty() const
440 return fElements
.IsEmpty();
444 /*! \brief Removes all entries from the map.
446 _VECTOR_MAP_TEMPLATE_LIST
448 _VECTOR_MAP_CLASS_NAME::MakeEmpty()
450 fElements
.MakeEmpty();
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
463 _VECTOR_MAP_CLASS_TYPE::Iterator
464 _VECTOR_MAP_CLASS_NAME::Begin()
466 return Iterator(this, fElements
.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
479 _VECTOR_MAP_CLASS_TYPE::ConstIterator
480 _VECTOR_MAP_CLASS_NAME::Begin() const
482 return ConstIterator(this, fElements
.Begin());
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
495 _VECTOR_MAP_CLASS_TYPE::Iterator
496 _VECTOR_MAP_CLASS_NAME::End()
498 return Iterator(this, fElements
.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
511 _VECTOR_MAP_CLASS_TYPE::ConstIterator
512 _VECTOR_MAP_CLASS_NAME::End() const
514 return ConstIterator(this, fElements
.End());
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
527 _VECTOR_MAP_CLASS_TYPE::Iterator
528 _VECTOR_MAP_CLASS_NAME::Null()
530 return Iterator(this, fElements
.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
543 _VECTOR_MAP_CLASS_TYPE::ConstIterator
544 _VECTOR_MAP_CLASS_NAME::Null() const
546 return ConstIterator(this, fElements
.Null());
550 /*! \brief Returns an iterator referring to the entry with the
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
)
561 int32 index
= _FindInsertionIndex(key
, exists
);
564 return Iterator(this, fElements
.IteratorForIndex(index
));
568 /*! \brief Returns an iterator referring to the entry with the
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
579 int32 index
= _FindInsertionIndex(key
, exists
);
582 return ConstIterator(this, fElements
.IteratorForIndex(index
));
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
)
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.
618 return Iterator(this, fElements
.IteratorForIndex(index
));
619 // An element with a smaller value is desired. The previous one (if any)
622 return Iterator(this, fElements
.IteratorForIndex(index
- 1));
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
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.
659 return ConstIterator(this, fElements
.IteratorForIndex(index
));
660 // An element with a smaller value is desired. The previous one (if any)
663 return ConstIterator(this, fElements
.IteratorForIndex(index
- 1));
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.
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
678 _VECTOR_MAP_CLASS_NAME::_FindInsertionIndex(const Key
&key
,
683 int32 upper
= Count();
684 while (lower
< upper
) {
685 int32 mid
= (lower
+ upper
) / 2;
686 int cmp
= fEntryStrategy
.Compare(fEntryStrategy
.GetKey(fElements
[mid
]),
693 exists
= (lower
< Count() && fEntryStrategy
.Compare(key
,
694 fEntryStrategy
.GetKey(fElements
[lower
])) == 0);
701 namespace VectorMapEntryStrategy
{
704 template<typename Key
, typename Value
, typename KeyOrder
>
707 typedef const Key
&KeyReference
;
711 Entry(const Key
&key
, const Value
&value
)
712 : key(key
), value(value
) {}
718 inline KeyReference
GetKey(const Entry
&entry
) const
723 inline const Value
&GetValue(const Entry
&entry
) const
728 inline Value
&GetValue(Entry
&entry
) const
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
743 inline int Compare(const Key
&a
, const Key
&b
) const
745 return fCompare(a
, b
);
753 template<typename Key
, typename Value
, typename _GetKey
, typename KeyOrder
>
756 typedef Key KeyReference
;
759 inline KeyReference
GetKey(const Entry
&entry
) const
761 return fGetKey(entry
);
764 inline const Value
&GetValue(const Entry
&entry
) const
769 inline Value
&GetValue(Entry
&entry
) const
774 inline Entry
MakeEntry(const Key
&, const Value
&value
) const
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
);
794 } // VectorMapEntryStrategy
796 #endif // _VECTOR_MAP_H