From 0714dc6e06d7bbd30b12775d1f7f39bac189b216 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 20:31:30 +0200 Subject: [PATCH] taken over container --- container/FixedOrderedMultimap.h | 250 +++++++++++++++++++---------- container/FixedOrderedMultimap.tpp | 190 +++++++++------------- 2 files changed, 243 insertions(+), 197 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index cb8ab10f..96bc0073 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -5,120 +5,200 @@ #include /** - * @brief Map implementation which allows entries with identical keys + * @brief An associative container which allows multiple entries of the same key. * @details - * Performs no dynamic memory allocation except on initialization. - * Uses an ArrayList as the underlying container and thus has a linear + * Same keys are ordered by KEY_COMPARE function which is std::less > by default. + * + * It uses the ArrayList, so technically this is not a real map, it is an array of pairs + * of type key_t, T. It is ordered by key_t as FixedMap but allows same keys. Thus it has a linear * complexity O(n). As long as the number of entries remains low, this * should not be an issue. * The number of insertion and deletion operation should be minimized - * as those incur exensive memory move operations (the underlying container + * as those incur extensive memory move operations (the underlying container * is not node based). - * @ingroup container + * + * Its of fixed size so no allocations are performed after the construction. + * + * The maximum size is given as first parameter of the constructor. + * + * It provides an iterator to do list iterations. + * + * The type T must have a copy constructor if it is not trivial copy-able. + * + * @warning Iterators return a non-const key_t in the pair. + * @warning A User is not allowed to change the key, otherwise the map is corrupted. + * + * \ingroup container */ template> class FixedOrderedMultimap { public: static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP; - static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); - static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); - static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); + + /*** + * Constructor which needs a size_t for the maximum allowed size + * + * Can not be resized during runtime + * + * Allocates memory at construction + * @param maxSize size_t of Maximum allowed size + */ + FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){ + } + + /*** + * Virtual destructor frees Memory by deleting its member + */ + virtual ~FixedOrderedMultimap() { + } + + /*** + * Special iterator for FixedOrderedMultimap + */ + class Iterator: public ArrayList, size_t>::Iterator { + public: + Iterator() : + ArrayList, size_t>::Iterator() { + } + + Iterator(std::pair *pair) : + ArrayList, size_t>::Iterator(pair) { + } + }; + + /*** + * Returns an iterator pointing to the first element + * @return Iterator pointing to first element + */ + Iterator begin() const { + return Iterator(&theMap[0]); + } /** - * Initializes the ordered multimap with a fixed maximum size. - * @param maxSize + * Returns an iterator pointing to one element past the end + * @return Iterator pointing to one element past the end */ - FixedOrderedMultimap(size_t maxSize); + Iterator end() const { + return Iterator(&theMap[_size]); + } - virtual ~FixedOrderedMultimap() {} + /*** + * Returns the current size of the map (not maximum size!) + * @return Current size + */ + size_t size() const{ + return _size; + } - class Iterator: public ArrayList, uint32_t>::Iterator { - public: - /** Returns an iterator to nullptr */ - Iterator(); - /** Initializes iterator to given entry */ - Iterator(std::pair *pair); - }; + /** + * Clears the map, does not deallocate any memory + */ + void clear(){ + _size = 0; + } - /** Iterator to start of map */ - Iterator begin() const; - /** Iterator to end of map */ - Iterator end() const; - /** Current (variable) size of the map */ - size_t size() const; + /** + * Returns the maximum size of the map + * @return Maximum size of the map + */ + size_t maxSize() const{ + return theMap.maxSize(); + } - /** - * Insert a key/value pair inside the map. An iterator to the stored - * value might be returned optionally. - * @param key - * @param value - * @param storedValue - * @return - */ - ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr); - /** - * Insert a given std::pair - * @param pair - * @return - */ - ReturnValue_t insert(std::pair pair); - /** - * Checks existence of key in map. - * @param key - * @return - * - @c KEY_DOES_NOT_EXIST if key does not exists. - * - @c RETURN_OK otherwise. - */ - ReturnValue_t exists(key_t key) const; + /*** + * Used to insert a key and value separately. + * + * @param[in] key Key of the new element + * @param[in] value Value of the new element + * @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr + * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + */ + ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr); - ReturnValue_t erase(Iterator *iter); - ReturnValue_t erase(key_t key); + /*** + * Used to insert new pair instead of single values + * + * @param pair Pair to be inserted + * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + */ + ReturnValue_t insert(std::pair pair); - Iterator find(key_t key) const; - ReturnValue_t find(key_t key, T **value) const; + /*** + * Can be used to check if a certain key is in the map + * @param key Key to be checked + * @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise + */ + ReturnValue_t exists(key_t key) const; - void clear(); + /*** + * Used to delete the element in the iterator + * + * The iterator will point to the element before or begin(), + * but never to one element in front of the map. + * + * @warning The iterator needs to be valid and dereferenceable + * @param[in/out] iter Pointer to iterator to the element that needs to be ereased + * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + */ + ReturnValue_t erase(Iterator *iter); - size_t maxSize() const; + /*** + * Used to erase by key + * @param key Key to be erased + * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + */ + ReturnValue_t erase(key_t key); + + /*** + * Find returns the first appearance of the key + * + * If the key does not exist, it points to end() + * + * @param key Key to search for + * @return Iterator pointing to the first entry of key + */ + Iterator find(key_t key) const{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return end(); + } + return Iterator(&theMap[findFirstIndex(key)]); + }; + + /*** + * Finds first entry of the given key and returns a + * pointer to the value + * + * @param key Key to search for + * @param value Found value + * @return RETURN_OK if it points to the value, + * KEY_DOES_NOT_EXIST if the key is not in the map + */ + ReturnValue_t find(key_t key, T **value) const; + + friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs, + const typename FixedOrderedMultimap::Iterator& rhs) { + return (lhs.value == rhs.value); + } + + friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs, + const typename FixedOrderedMultimap::Iterator& rhs) { + return not (lhs.value == rhs.value); + } private: typedef KEY_COMPARE compare; compare myComp; - ArrayList, uint32_t> theMap; + ArrayList, size_t> theMap; size_t _size; - uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { - if (startAt >= _size) { - return startAt + 1; - } - uint32_t i = startAt; - for (i = startAt; i < _size; ++i) { - if (theMap[i].first == key) { - return i; - } - } - return i; - } + size_t findFirstIndex(key_t key, size_t startAt = 0) const; - uint32_t findNicePlace(key_t key) const { - uint32_t i = 0; - for (i = 0; i < _size; ++i) { - if (myComp(key, theMap[i].first)) { - return i; - } - } - return i; - } + size_t findNicePlace(key_t key) const; - void removeFromPosition(uint32_t position) { - if (_size <= position) { - return; - } - std::memmove(static_cast(&theMap[position]), - static_cast(&theMap[position + 1]), - (_size - position - 1) * sizeof(std::pair)); - --_size; - } + void removeFromPosition(size_t position); }; #include "FixedOrderedMultimap.tpp" diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp index bc76c594..4aa85e97 100644 --- a/container/FixedOrderedMultimap.tpp +++ b/container/FixedOrderedMultimap.tpp @@ -1,142 +1,108 @@ #ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ -template -inline FixedOrderedMultimap::Iterator::Iterator(): - ArrayList, uint32_t>::Iterator(){} template -inline FixedOrderedMultimap::Iterator::Iterator( - std::pair *pair): - ArrayList, uint32_t>::Iterator(pair){} - +inline ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { + if (_size == theMap.maxSize()) { + return MAP_FULL; + } + size_t position = findNicePlace(key); + memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), + (_size - position) * sizeof(std::pair)); + theMap[position].first = key; + theMap[position].second = value; + ++_size; + if (storedValue != nullptr) { + *storedValue = Iterator(&theMap[position]); + } + return HasReturnvaluesIF::RETURN_OK; +} template -inline typename FixedOrderedMultimap::Iterator -FixedOrderedMultimap::begin() const { - return Iterator(&theMap[0]); +inline ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { + return insert(pair.first, pair.second); } template -inline typename FixedOrderedMultimap::Iterator -FixedOrderedMultimap::end() const { - return Iterator(&theMap[_size]); -} - - -template -inline size_t FixedOrderedMultimap::size() const { - return _size; +inline ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { + ReturnValue_t result = KEY_DOES_NOT_EXIST; + if (findFirstIndex(key) < _size) { + result = HasReturnvaluesIF::RETURN_OK; + } + return result; } template -inline FixedOrderedMultimap::FixedOrderedMultimap( - size_t maxSize): theMap(maxSize), _size(0) {} - - -template -inline ReturnValue_t FixedOrderedMultimap::insert( - key_t key, T value, Iterator *storedValue) { - if (_size == theMap.maxSize()) { - return MAP_FULL; - } - uint32_t position = findNicePlace(key); - // Compiler might emitt warning because std::pair is not a POD type (yet..) - // See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm#std::pair-example - // Circumvent warning by casting to void* - std::memmove(static_cast(&theMap[position + 1]), - static_cast(&theMap[position]), - (_size - position) * sizeof(std::pair)); - theMap[position].first = key; - theMap[position].second = value; - ++_size; - if (storedValue != nullptr) { - *storedValue = Iterator(&theMap[position]); - } - return HasReturnvaluesIF::RETURN_OK; +inline ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { + size_t i; + if ((i = findFirstIndex((*iter).value->first)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + removeFromPosition(i); + if (*iter != begin()) { + (*iter)--; + } else { + *iter = begin(); + } + return HasReturnvaluesIF::RETURN_OK; } template -inline ReturnValue_t FixedOrderedMultimap::insert( - std::pair pair) { - return insert(pair.fist, pair.second); +inline ReturnValue_t FixedOrderedMultimap::erase(key_t key) { + size_t i; + if ((i = findFirstIndex(key)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + do { + removeFromPosition(i); + i = findFirstIndex(key, i); + } while (i < _size); + return HasReturnvaluesIF::RETURN_OK; } template -inline ReturnValue_t FixedOrderedMultimap::exists( - key_t key) const { - ReturnValue_t result = KEY_DOES_NOT_EXIST; - if (findFirstIndex(key) < _size) { - result = HasReturnvaluesIF::RETURN_OK; - } - return result; +inline ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + *value = &theMap[findFirstIndex(key)].second; + return HasReturnvaluesIF::RETURN_OK; } template -inline ReturnValue_t FixedOrderedMultimap::erase( - Iterator *iter) -{ - uint32_t i; - if ((i = findFirstIndex((*iter).value->first)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - removeFromPosition(i); - if (*iter != begin()) { - (*iter)--; - } else { - *iter = begin(); - } - return HasReturnvaluesIF::RETURN_OK; +inline size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { + if (startAt >= _size) { + return startAt + 1; + } + size_t i = startAt; + for (i = startAt; i < _size; ++i) { + if (theMap[i].first == key) { + return i; + } + } + return i; } template -inline ReturnValue_t FixedOrderedMultimap::erase( - key_t key) -{ - uint32_t i; - if ((i = findFirstIndex(key)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - do { - removeFromPosition(i); - i = findFirstIndex(key, i); - } while (i < _size); - return HasReturnvaluesIF::RETURN_OK; +inline size_t FixedOrderedMultimap::findNicePlace(key_t key) const { + size_t i = 0; + for (i = 0; i < _size; ++i) { + if (myComp(key, theMap[i].first)) { + return i; + } + } + return i; } template -inline ReturnValue_t FixedOrderedMultimap::find( - key_t key, T **value) const -{ - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - *value = &theMap[findFirstIndex(key)].second; - return HasReturnvaluesIF::RETURN_OK; -} - -template -inline typename FixedOrderedMultimap::Iterator -FixedOrderedMultimap::find( - key_t key) const -{ - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return end(); - } - return Iterator(&theMap[findFirstIndex(key)]); -} - -template -inline void FixedOrderedMultimap::clear() -{ - _size = 0; -} - -template -inline size_t FixedOrderedMultimap::maxSize() const -{ - return theMap.maxSize(); +inline void FixedOrderedMultimap::removeFromPosition(size_t position) { + if (_size <= position) { + return; + } + memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + (_size - position - 1) * sizeof(std::pair)); + --_size; }