ListMap.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //
  2. // ListMap.h
  3. //
  4. // Library: Foundation
  5. // Package: Hashing
  6. // Module: ListMap
  7. //
  8. // Definition of the ListMap class.
  9. //
  10. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef Foundation_ListMap_INCLUDED
  16. #define Foundation_ListMap_INCLUDED
  17. #include "Poco/Foundation.h"
  18. #include "Poco/String.h"
  19. #include "Poco/Exception.h"
  20. #include <list>
  21. #include <utility>
  22. namespace Poco {
  23. template <class Key, class Mapped, class Container = std::list<std::pair<Key, Mapped> >, bool CaseSensitive = false >
  24. class ListMap
  25. /// This class implements a multimap in terms of a sequential container.
  26. /// The use for this type of associative container is wherever automatic
  27. /// ordering of elements is not desirable. Naturally, this container will
  28. /// have inferior data retrieval performance and it is not recommended for
  29. /// use with large datasets. The main purpose within POCO is for Internet
  30. /// messages (email message, http headers etc), to prevent automatic
  31. /// header entry reordering.
  32. {
  33. public:
  34. typedef Key KeyType;
  35. typedef Mapped MappedType;
  36. typedef Mapped& Reference;
  37. typedef const Mapped& ConstReference;
  38. typedef Mapped* Pointer;
  39. typedef const Mapped* ConstPointer;
  40. typedef typename Container::value_type ValueType;
  41. typedef typename Container::size_type SizeType;
  42. typedef typename Container::iterator Iterator;
  43. typedef typename Container::const_iterator ConstIterator;
  44. ListMap()
  45. /// Creates an empty ListMap.
  46. {
  47. }
  48. ListMap(std::size_t initialReserve):
  49. _list(initialReserve)
  50. /// Creates the ListMap with room for initialReserve entries.
  51. {
  52. }
  53. ListMap& operator = (const ListMap& map)
  54. /// Assigns another ListMap.
  55. {
  56. ListMap tmp(map);
  57. swap(tmp);
  58. return *this;
  59. }
  60. void swap(ListMap& map)
  61. /// Swaps the ListMap with another one.
  62. {
  63. _list.swap(map._list);
  64. }
  65. ConstIterator begin() const
  66. /// Returns the beginning of the map.
  67. {
  68. return _list.begin();
  69. }
  70. ConstIterator end() const
  71. /// Returns the end of the map.
  72. {
  73. return _list.end();
  74. }
  75. Iterator begin()
  76. /// Returns the beginning of the map.
  77. {
  78. return _list.begin();
  79. }
  80. Iterator end()
  81. /// Returns the end of the map.
  82. {
  83. return _list.end();
  84. }
  85. ConstIterator find(const KeyType& key) const
  86. /// Finds the first occurrence of the key and
  87. /// returns iterator pointing to the found entry
  88. /// or iterator pointing to the end if entry is
  89. /// not found.
  90. {
  91. typename Container::const_iterator it = _list.begin();
  92. typename Container::const_iterator itEnd = _list.end();
  93. for(; it != itEnd; ++it)
  94. {
  95. if (isEqual(it->first, key)) return it;
  96. }
  97. return itEnd;
  98. }
  99. Iterator find(const KeyType& key)
  100. /// Finds the first occurrence of the key and
  101. /// returns iterator pointing to the found entry
  102. /// or iterator pointing to the end if entry is
  103. /// not found.
  104. {
  105. typename Container::iterator it = _list.begin();
  106. typename Container::iterator itEnd = _list.end();
  107. for(; it != itEnd; ++it)
  108. {
  109. if (isEqual(it->first, key)) return it;
  110. }
  111. return itEnd;
  112. }
  113. Iterator insert(const ValueType& val)
  114. /// Inserts the value into the map. If one or more values
  115. /// already exist, new value is inserted at the end of the
  116. /// block. Thus, all the equal value entries are located
  117. /// sequentially at all times.
  118. /// Returns iterator pointing to the newly inserted value
  119. {
  120. Iterator it = find(val.first);
  121. while (it != _list.end() && isEqual(it->first, val.first)) ++it;
  122. return _list.insert(it, val);
  123. }
  124. void erase(Iterator it)
  125. {
  126. _list.erase(it);
  127. }
  128. SizeType erase(const KeyType& key)
  129. {
  130. SizeType count = 0;
  131. Iterator it = find(key);
  132. bool removed = false;
  133. while (it != _list.end())
  134. {
  135. if (isEqual(it->first, key))
  136. {
  137. ++count;
  138. it = _list.erase(it);
  139. removed = true;
  140. }
  141. else
  142. {
  143. if (removed) return count;
  144. ++it;
  145. }
  146. }
  147. return count;
  148. }
  149. void clear()
  150. {
  151. _list.clear();
  152. }
  153. std::size_t size() const
  154. {
  155. return _list.size();
  156. }
  157. bool empty() const
  158. {
  159. return _list.empty();
  160. }
  161. ConstReference operator [] (const KeyType& key) const
  162. {
  163. ConstIterator it = find(key);
  164. if (it != _list.end())
  165. return it->second;
  166. else
  167. throw NotFoundException();
  168. }
  169. Reference operator [] (const KeyType& key)
  170. {
  171. Iterator it = find(key);
  172. if (it != _list.end())
  173. return it->second;
  174. else
  175. {
  176. ValueType value(key, Mapped());
  177. Iterator itInsert = insert(value);
  178. return itInsert->second;
  179. }
  180. }
  181. private:
  182. template <typename T1, typename T2>
  183. bool isEqual(T1 val1, T2 val2) const
  184. {
  185. return val1 == val2;
  186. }
  187. bool isEqual(const std::string& s1, const std::string& s2) const
  188. {
  189. if (!CaseSensitive)
  190. return Poco::icompare(s1, s2) == 0;
  191. else
  192. return s1 == s2;
  193. }
  194. bool isEqual(const std::string& s1, const char* s2) const
  195. {
  196. return isEqual(s1, std::string(s2));
  197. }
  198. bool isEqual(const char* s1, const std::string& s2) const
  199. {
  200. return isEqual(std::string(s1), s2);
  201. }
  202. bool isEqual(const char* s1, const char* s2) const
  203. {
  204. return isEqual(std::string(s1), std::string(s2));
  205. }
  206. Container _list;
  207. };
  208. } // namespace Poco
  209. #endif // Foundation_ListMap_INCLUDED