ListMap.h 5.2 KB

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