123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- /*!
- * \file include/Map.h
- * \brief Template Map
- *
- * Using RBTree and list overlay for faster access
- *
- * Access: O(1)/O(n)/O(logn) ?
- * Insert: O(nlogn) ?
- * Remove: O(nlogn) ?
- *
- * \author Mongoose
- * \author xythobuz
- */
-
- #ifndef _MAP_H_
- #define _MAP_H_
-
- #include <stdlib.h>
- #include <stdio.h>
-
- #include <Tree.h>
-
- #ifdef DEBUG_MEMORY
- #include <memory_test.h>
- #endif
-
- /*!
- * \brief Template class encapsulating a single map node
- * \tparam K key type
- * \tparam D data type
- */
- template <class K, class D> class MapNode {
- public:
-
- /*!
- * \brief Construct a MapNode
- * \param key key of this Node
- * \param data data of this Node
- */
- MapNode(K key, D data) {
- _data = data;
- _key = key;
- _next = NULL;
- }
-
- /*!
- * \brief Deconstruct a MapNode
- */
- ~MapNode() {
- }
-
- /*!
- * \brief Set the key of this MapNode
- * \param key new key
- */
- void Key(K key) {
- _key = key;
- }
-
- /*!
- * \brief Get the key of this MapNode
- * \returns key
- */
- K Key() {
- return _key;
- }
-
- /*!
- * \brief Set the data of this MapNode
- * \param data new data
- */
- void Data(D data) {
- _data = data;
- }
-
- /*!
- * \brief Get the data of this MapNode
- * \returns data
- */
- D Data() {
- return _data;
- }
-
- /*!
- * \brief Get the next MapNode in the Map
- * \returns next pointer
- */
- MapNode<K, D> *Next() {
- return _next;
- }
-
- /*!
- * \brief Set the next MapNode in the Map
- * \param next new next pointer
- */
- void Next(MapNode<K, D> *next) {
- _next = next;
- }
-
- private:
-
- MapNode<K, D> *_next; //!< Next pointer
- K _key; //!< Key of the MapNode
- D _data; //!< Data of the MapNode
- };
-
- /*!
- * \brief Template class representing a Map, mapping data to a key.
- * \tparam K key type
- * \tparam D data type
- */
- template <class K, class D> class Map {
- public:
-
- /*!
- * \brief Construct a Map
- */
- Map() {
- UnSetError();
- _num_items = 0;
- _head = NULL;
- _current = NULL;
- _cache = NULL;
- }
-
- /*!
- * \brief Deconstruct a Map
- * \sa Map::Clear()
- */
- ~Map() {
- Clear();
- }
-
- /*!
- * \brief Deletes every item in the Map. Clears error flag.
- */
- void Clear() {
- UnSetError();
- _num_items = 0;
- _cache = NULL;
- while (_head) {
- _current = _head;
- _head = _head->Next();
- delete _current;
- }
- _tree.Clear();
- }
-
- /*!
- * \brief Set the error flag
- */
- void SetError() {
- _error = true;
- }
-
- /*!
- * \brief Unset the error flag
- */
- void UnSetError() {
- _error = false;
- }
-
- /*!
- * \brief Get the error flag
- * \returns error flag
- */
- bool GetError() {
- return _error;
- }
-
- /*!
- * \brief Search for data with a key. Sets error flag if nothing is found.
- * \param key key to search for
- * \returns data matching key or 0
- */
- D FindDataByKey(K key) {
- MapNode<K, D> *current = NULL;
- MapNode<K, D> *next = NULL;
-
-
- if (_head) {
- UnSetError();
-
- if (_cache) {
- next = _cache->Next();
- }
-
- // Mongoose 2002.02.19, Optimize for sequential searches
- if (next && key == next->Key()) {
- current = next;
- } else { // Mongoose 2002.02.19, Use search algorithm otherwise
- current = _tree.SearchByKey(key, &_error);
-
- if (_error)
- return false;
- }
-
- if (current) {
- _cache = _current = current;
- return current->Data();
- }
- }
-
- SetError();
- return 0;
- }
-
- /*!
- * \brief Search for data with a key
- * \param key key to search for
- * \returns data matching key or 0
- * \sa Map::FindDataByKey()
- */
- D operator [] (K key) {
- return FindDataByKey(key);
- }
-
- /*!
- * \brief Search for a key with specific data. Sets error flag if nothing is found.
- * \param data data to search for
- * \returns key matching data or 0
- */
- K FindKeyByData(D data) {
- MapNode<K, D> *current = _head;
- MapNode<K, D> *last = NULL;
-
-
- UnSetError();
-
- while (current) {
- // Found
- if (current->Data() == data) {
- _cache = current;
- return current->Key();
- }
-
- last = current;
- current = current->Next();
- }
-
- SetError();
-
- return 0;
- }
-
- /*!
- * \brief Returns data of the cached MapNode
- * \returns cached data
- */
- D getCache() {
- if (_cache == 0x0) {
- printf("Map::getCache> Bad request - should segfault\n");
- }
-
- return _cache->Data();
- }
-
- /*!
- * \brief Check if a key is in this map. Sets error flag if nothing is found.
- * \returns true if the key is in the map, false otherwise
- * \sa Tree:SearchByKey()
- */
- bool findKey(K key) {
- MapNode<K, D> *current = NULL;
- MapNode<K, D> *next = NULL;
-
- if (_head) {
- UnSetError();
-
- if (_cache) {
- if (_cache->Key() == key) {
- return true;
- }
-
- next = _cache->Next();
- }
-
- // Mongoose 2002.02.19, Optimize for sequential searches
- if (next && key == next->Key()) {
- current = next;
- } else { // Mongoose 2002.02.19, Use search algorithm otherwise
- current = _tree.SearchByKey(key, &_error);
- }
-
- if (current) {
- _cache = _current = current;
- //curData = current->Data();
- return true;
- }
- }
-
- SetError();
- return false;
- }
-
- /*!
- * \brief Add a Key-Data pair to the Map, creating a new MapNode. Clears error flag.
- * \param key key to add
- * \param data to add
- * \returns true on success, false if there is not enough memory
- */
- bool Add(K key, D data) {
- MapNode<K, D> *node;
-
- UnSetError();
- node = new MapNode<K, D>(key, data);
- _num_items++;
- return Add(node);
- }
-
- /*!
- * \brief Add a MapNode to the Map. Clears error flag on success.
- * \param node node to add
- * \returns true on success, false if node is NULL
- * \sa Tree:Insert()
- */
- bool Add(MapNode<K, D> *node) {
- MapNode<K, D> *current = _head;
- MapNode<K, D> *last = NULL;
-
- if (!node)
- return false;
-
- UnSetError();
-
- if (_head) {
- current = _head;
- last = NULL;
-
- while (current) {
- // Prepend
- if (current->Key() > node->Key()) {
- node->Next(current);
-
- if (current == _head) {
- _head = node;
- } else if (last) {
- last->Next(node);
- }
-
- _tree.Insert(node->Key(), node);
- return true;
- }
-
- last = current;
- current = current->Next();
- }
-
- // Append
- last->Next(node);
- } else {
- _head = node;
- }
-
- _tree.Insert(node->Key(), node);
- return true;
- }
-
- /*!
- * \brief Remove item with the specified key. Sets error flag if nothing is removed.
- * \param key key to remove
- */
- void RemoveByKey(K key) {
- MapNode<K, D> *current = _head;
- MapNode<K, D> *last = NULL;
-
- UnSetError();
-
- _cache = NULL;
-
- while (current) {
- // Remove
- if (current->Key() == key) {
- if (current == _head) {
- _head = current->Next();
- } else {
- last->Next(current->Next());
- }
-
- if (_current == current) {
- _current = NULL;
- }
-
- _tree.RemoveByKey(current->Key());
- delete current;
- _num_items--;
-
- return;
- }
-
- last = current;
- current = current->Next();
- }
-
- SetError();
- }
-
- /*!
- * \brief Remove item with the specified data. Sets error flag if nothing is removed.
- * \param data data to remove
- */
- void RemoveByData(D data) {
- MapNode<K, D> *current = _head;
- MapNode<K, D> *last = NULL;
-
- UnSetError();
-
- _cache = NULL;
-
- while (current)
- {
- // Remove
- if (current->Data() == data) {
- if (current == _head) {
- _head = current->Next();
- } else {
- last->Next(current->Next());
- }
-
- if (_current == current) {
- _current = NULL;
- }
-
- _tree.RemoveByKey(current->Key());
- delete current;
- _num_items--;
-
- return;
- }
-
- last = current;
- current = current->Next();
- }
-
- SetError();
- }
-
- /*!
- * \brief Check if the Map is empty
- * \returns true if Map is empty, false otherwise
- */
- bool Empty() {
- return (_head == NULL);
- }
-
- /*!
- * \brief Returns number of items in the Map
- * \returns number of items
- */
- unsigned int NumItems() {
- return _num_items;
- }
-
- /*!
- * \brief Print the Map. Sets error flag if one or both functions aren't provided.
- * \param print_key_func function that prints a key
- * \param print_data_func function that prints the data
- */
- void Print(void (*print_key_func)(K), void (*print_data_func)(D)) {
- MapNode<K, D> *current = _head;
-
- UnSetError();
-
- if (!print_key_func || !print_data_func) {
- SetError();
- return;
- }
-
- printf(" [%i] {\n", _num_items);
-
- while (current) {
- printf("(");
- (*print_key_func)(current->Key());
- printf(", ");
- (*print_data_func)(current->Data());
- printf("), ");
-
- current = current->Next();
- fflush(stdout);
- }
-
- printf(" }\n");
- }
-
- /*!
- * \brief Reset the Map iterator
- */
- void Reset() {
- _current = _head;
- _cache = _head;
- }
-
- /*!
- * \brief Iterate over the Map
- * \returns true if there is a new current element
- * \sa Map::Next()
- */
- bool operator ++ (int) {
- return Next();
- }
-
- /*!
- * \brief Iterate over the Map
- * \returns true if there is a new current element
- * \sa Map::Next()
- */
- bool operator ++ () {
- return Next();
- }
-
- /*!
- * \brief Iterate over the Map
- * \returns true if there is a new current element
- * \sa Map::Next()
- */
- bool Next() {
- if (_current) {
- _current = _current->Next();
- }
-
- return (_current != NULL);
- }
-
- /*!
- * \brief Check if there is a current item in the iterator
- * \returns true if the current item exists
- */
- bool CurrentExists() {
- return (_current != 0);
- }
-
- /*!
- * \brief Returns the key of the current item. Sets error flag if there is no current item.
- * \returns key or 0 if there is no current item
- */
- K CurrentKey() {
- UnSetError();
-
- if (!_current) {
- SetError();
- return 0;
- }
-
- return _current->Key();
- }
-
- /*!
- * \brief Returns the data of the current item. Sets error flag if there is no current item.
- * \returns data or 0 if there is no current item
- */
- D Current() {
- UnSetError();
-
- if (!_current) {
- SetError();
- return 0;
- }
-
- return _current->Data();
- }
-
- private:
-
- unsigned int _num_items; //!< Number of items in the Map
- bool _error; //!< Error flag
- Tree<K, MapNode<K, D> *> _tree; //!< Tree containing the MapNodes
- MapNode<K, D> *_head; //!< First item of the Map
- MapNode<K, D> *_current; //!< Current item for the iterator
- MapNode<K, D> *_cache; //!< Cached item used by search & remove methods
- };
- #endif
|