/qlandkartegt-1.5.0/src/Dictionary.h

# · C Header · 235 lines · 202 code · 12 blank · 21 comment · 32 complexity · 9fd0b2efee61f16866e13cdc6c175a81 MD5 · raw file

  1. #ifndef DICTIONARY_H
  2. #define DICTIONARY_H
  3. #include <QHash>
  4. /*
  5. * The purpose of this class is to have an efficient bi-directional
  6. * hash map similar to QHash. Actually, the interface mimicks QHash
  7. * as close as possible, but all operations are efficient in both
  8. * directions. And storage requirements are reasonable, with each
  9. * object stored only once.
  10. *
  11. * A sample use case would be translating color names to QColor
  12. * and using the same mapping for reverse translation.
  13. */
  14. template <typename KeyL, typename KeyR>
  15. class Dictionary
  16. {
  17. protected:
  18. // The pointers are actually iterators over the other hash map
  19. typedef QHash<KeyL, void*> HashL;
  20. typedef QHash<KeyR, void*> HashR;
  21. HashL hashL;
  22. HashR hashR;
  23. protected:
  24. // These convert left iterators to right iterators and back
  25. static typename HashR::iterator left2right(typename HashL::iterator il)
  26. { return typename HashR::iterator(il.value()); }
  27. static typename HashR::const_iterator left2right(typename HashL::const_iterator il)
  28. { return typename HashR::const_iterator(il.value()); }
  29. static typename HashL::iterator right2left(typename HashR::iterator ir)
  30. { return typename HashL::iterator(ir.value()); }
  31. static typename HashL::const_iterator right2left(typename HashR::const_iterator ir)
  32. { return typename HashL::const_iterator(ir.value()); }
  33. template<typename I>
  34. class iterator_base
  35. {
  36. friend class Dictionary;
  37. protected:
  38. I i;
  39. iterator_base(const I& i): i(i) {}
  40. public:
  41. iterator_base() {}
  42. iterator_base(const iterator_base<I>& other): i(other.i) {}
  43. const KeyL& left() { return i.key(); }
  44. const KeyR& right() { return left2right(i).key(); }
  45. bool operator!= (const iterator_base<I>& other) const { return i!=other.i; }
  46. iterator_base<I> operator+(int j) const { return i+j; }
  47. iterator_base<I>& operator++() { return ++i; }
  48. iterator_base<I> operator++(int) { return i++; }
  49. iterator_base<I>& operator+=(int j) { return i+=j; }
  50. iterator_base<I> operator-(int j) const { return i-j; }
  51. iterator_base<I>& operator--() { return --i; }
  52. iterator_base<I> operator--(int) { return i--; }
  53. iterator_base<I>& operator-=(int j) { return i-=j; }
  54. bool operator==(const iterator_base<I>& other) const { return i==other.i; }
  55. };
  56. public:
  57. // It is sufficient to store only one iterator,
  58. // we arbitrarily choose the left one
  59. typedef iterator_base<typename HashL::iterator> iterator;
  60. typedef iterator_base<typename HashL::const_iterator> const_iterator;
  61. public:
  62. iterator begin() { return hashL.begin(); }
  63. const_iterator begin() const { return hashL.begin(); }
  64. int capacity() const { return hashL.capacity(); }
  65. void clear() { hashL.clear(); hashR.clear(); }
  66. const_iterator constBegin() const { return this->begin(); }
  67. const_iterator constEnd() const { return this->end(); }
  68. const_iterator constFind(const KeyL& keyL) const { return findL(keyL); }
  69. const_iterator constFind(const KeyR& keyR) const { return findR(keyR); }
  70. bool contains(const KeyL& keyL) const { return containsL(keyL); }
  71. bool contains(const KeyR& keyR) const { return containsR(keyR); }
  72. bool containsL(const KeyL& keyL) const { return hashL.contains(keyL); }
  73. bool containsR(const KeyR& keyR) const { return hashR.contains(keyR); }
  74. int count(const KeyL& keyL) const { return countL(keyL); }
  75. int count(const KeyR& keyR) const { return countR(keyR); }
  76. int countL(const KeyL& keyL) const { return hashL.count(keyL); }
  77. int countR(const KeyR& keyR) const { return hashR.count(keyR); }
  78. int count() const { return hashL.count(); }
  79. bool empty() const { return hashL.empty(); }
  80. iterator end() { return hashL.end(); }
  81. const_iterator end() const { return hashL.end(); }
  82. iterator erase(iterator pos)
  83. {
  84. hashR.erase(left2right(pos.i));
  85. return hashL.erase(pos.i);
  86. }
  87. iterator find(const KeyL& keyL) { return findL(keyL); }
  88. iterator find(const KeyR& keyR) { return findR(keyR); }
  89. const_iterator find(const KeyL& keyL) const { return findL(keyL); }
  90. const_iterator find(const KeyR& keyR) const { return findR(keyR); }
  91. iterator findL(const KeyL& keyL) { return hashL.find(keyL); }
  92. iterator findR(const KeyR& keyR)
  93. {
  94. typename HashR::iterator ir = hashR.find(keyR);
  95. if (ir == hashR.end()) return hashL.end();
  96. return right2left(ir);
  97. }
  98. const_iterator findL(const KeyL& keyL) const { return hashL.find(keyL); }
  99. const_iterator findR(const KeyR& keyR) const
  100. {
  101. typename HashR::const_iterator ir = hashR.find(keyR);
  102. if (ir == hashR.end()) return hashL.end();
  103. return right2left(ir);
  104. }
  105. iterator insert(const KeyL& keyL, const KeyR& keyR)
  106. {
  107. typename HashL::iterator il = hashL.insert(keyL, 0);
  108. typename HashR::iterator ir = hashR.insert(keyR, il);
  109. il.value() = ir;
  110. return il;
  111. }
  112. iterator insertMulti(const KeyL& keyL, const KeyR& keyR)
  113. {
  114. typename HashL::iterator il = hashL.insertMulti(keyL, 0);
  115. typename HashR::iterator ir = hashR.insertMulti(keyR, il);
  116. il.value() = ir;
  117. return il;
  118. }
  119. bool isEmpty() const { return hashL.isEmpty(); }
  120. const KeyL left(const KeyR& keyR) const
  121. {
  122. typename HashR::const_iterator ir = hashR.find(keyR);
  123. if (ir == hashR.end()) return KeyL();
  124. return right2left(ir).key();
  125. }
  126. const KeyL left(const KeyR& keyR, const KeyL& defaultKeyL) const
  127. {
  128. typename HashR::const_iterator ir = hashR.find(keyR);
  129. if (ir == hashR.end()) return defaultKeyL;
  130. return right2left(ir).key();
  131. }
  132. QList<KeyL> lefts() const { return hashL.keys(); }
  133. QList<KeyL> lefts(const KeyR& keyR) const
  134. {
  135. QList<KeyL> ret;
  136. typename HashR::const_iterator ir = hashR.find(keyR);
  137. while (ir != hashR.end() && ir.key() == keyR)
  138. {
  139. ret.append(right2left(ir).key());
  140. ++ir;
  141. }
  142. return ret;
  143. }
  144. int remove(const KeyL& keyL) { return removeL(keyL); }
  145. int remove(const KeyR& keyR) { return removeR(keyR); }
  146. int removeL(const KeyL& keyL)
  147. {
  148. typename HashL::iterator il = hashL.find(keyL);
  149. while (il != hashL.end() && il.key() == keyL)
  150. {
  151. hashR.erase(left2right(il));
  152. ++il;
  153. }
  154. return hashL.remove(keyL);
  155. }
  156. int removeR(const KeyR& keyR)
  157. {
  158. typename HashR::iterator ir = hashR.find(keyR);
  159. while (ir != hashR.end() && ir.key() == keyR)
  160. {
  161. hashL.erase(right2left(ir));
  162. ++ir;
  163. }
  164. return hashR.remove(keyR);
  165. }
  166. void reserve(int size) { hashL.reserve(size); hashR.reserve(size); }
  167. const KeyR right(const KeyL& keyL) const
  168. {
  169. typename HashL::const_iterator il = hashL.find(keyL);
  170. if (il == hashL.end()) return KeyR();
  171. return left2right(il).key();
  172. }
  173. const KeyR right(const KeyL& keyL, const KeyR& defaultKeyR) const
  174. {
  175. typename HashL::const_iterator il = hashL.find(keyL);
  176. if (il == hashL.end()) return defaultKeyR;
  177. return left2right(il).key();
  178. }
  179. QList<KeyR> rights() const { return hashR.keys(); }
  180. QList<KeyR> rights(const KeyL& keyL) const
  181. {
  182. QList<KeyR> ret;
  183. typename HashL::const_iterator il = hashL.find(keyL);
  184. while (il != hashL.end() && il.key() == keyL)
  185. {
  186. ret.append(left2right(il).key());
  187. ++il;
  188. }
  189. return ret;
  190. }
  191. int size() const { return hashL.size(); }
  192. void squeeze() { hashL.squeeze(); hashR.squeeze(); }
  193. KeyR take(const KeyL& keyL) { return takeL(keyL); }
  194. KeyL take(const KeyR& keyR) { return takeR(keyR); }
  195. KeyR takeL(const KeyL& keyL)
  196. {
  197. typename HashL::iterator il = hashL.find(keyL);
  198. if (il == hashL.end()) return KeyR();
  199. KeyR ret = left2right(il).key();
  200. hashR.erase(left2right(il));
  201. hashL.erase(il);
  202. return ret;
  203. }
  204. KeyL takeR(const KeyR& keyR)
  205. {
  206. typename HashR::iterator ir = hashR.find(keyR);
  207. if (ir == hashR.end()) return KeyL();
  208. KeyL ret = right2left(ir).key();
  209. hashL.erase(right2left(ir));
  210. hashR.erase(ir);
  211. return ret;
  212. }
  213. QList<KeyL> uniqueKeysL() const { return hashL.uniqueKeys(); }
  214. QList<KeyR> uniqueKeysR() const { return hashR.uniqueKeys(); }
  215. /*
  216. * NOT IMPLEMENTED
  217. *
  218. QHash<Key, T> & unite ( const QHash<Key, T> & other )
  219. bool operator!= ( const QHash<Key, T> & other ) const
  220. bool operator== ( const QHash<Key, T> & other ) const
  221. */
  222. };
  223. #endif