QxCollection.inl 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /****************************************************************************
  2. **
  3. ** https://www.qxorm.com/
  4. ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com)
  5. **
  6. ** This file is part of the QxOrm library
  7. **
  8. ** This software is provided 'as-is', without any express or implied
  9. ** warranty. In no event will the authors be held liable for any
  10. ** damages arising from the use of this software
  11. **
  12. ** Commercial Usage
  13. ** Licensees holding valid commercial QxOrm licenses may use this file in
  14. ** accordance with the commercial license agreement provided with the
  15. ** Software or, alternatively, in accordance with the terms contained in
  16. ** a written agreement between you and Lionel Marty
  17. **
  18. ** GNU General Public License Usage
  19. ** Alternatively, this file may be used under the terms of the GNU
  20. ** General Public License version 3.0 as published by the Free Software
  21. ** Foundation and appearing in the file 'license.gpl3.txt' included in the
  22. ** packaging of this file. Please review the following information to
  23. ** ensure the GNU General Public License version 3.0 requirements will be
  24. ** met : http://www.gnu.org/copyleft/gpl.html
  25. **
  26. ** If you are unsure which license is appropriate for your use, or
  27. ** if you have questions regarding the use of this file, please contact :
  28. ** contact@qxorm.com
  29. **
  30. ****************************************************************************/
  31. namespace qx {
  32. template <typename Key, typename Value>
  33. QxCollection<Key, Value>::QxCollection() : IxCollection(), m_batch(false)
  34. {
  35. }
  36. template <typename Key, typename Value>
  37. QxCollection<Key, Value>::QxCollection(const QxCollection<Key, Value> & other) : IxCollection(), m_batch(false)
  38. {
  39. cloneCollection(this, other);
  40. }
  41. template <typename Key, typename Value>
  42. QxCollection<Key, Value>::~QxCollection()
  43. {
  44. }
  45. template <typename Key, typename Value>
  46. QxCollection<Key, Value> & QxCollection<Key, Value>::operator= (const QxCollection<Key, Value> & other)
  47. {
  48. if (this != (& other)) { cloneCollection(this, other); }
  49. return (* this);
  50. }
  51. template <typename Key, typename Value>
  52. bool QxCollection<Key, Value>::operator== (const QxCollection<Key, Value> & other) const
  53. {
  54. return isSameCollection(this, other);
  55. }
  56. template <typename Key, typename Value>
  57. bool QxCollection<Key, Value>::operator!= (const QxCollection<Key, Value> & other) const
  58. {
  59. return (! isSameCollection(this, other));
  60. }
  61. template <typename Key, typename Value>
  62. void QxCollection<Key, Value>::cloneCollection(QxCollection<Key, Value> * pClone, const QxCollection<Key, Value> & pRef)
  63. {
  64. if (! pClone) { return; }
  65. if (pClone == (& pRef)) { return; }
  66. QMutexLocker locker1(& pRef.m_mutex);
  67. QMutexLocker locker2(& pClone->m_mutex);
  68. qAssert(pRef.m_list.size() == pRef.m_hash.size());
  69. pClone->m_list = pRef.m_list;
  70. pClone->m_hash = pRef.m_hash;
  71. }
  72. template <typename Key, typename Value>
  73. bool QxCollection<Key, Value>::isSameCollection(const QxCollection<Key, Value> * p1, const QxCollection<Key, Value> & p2) const
  74. {
  75. if (! p1) { return false; }
  76. if (p1 == (& p2)) { return true; }
  77. if (p1->size() != p2.size()) { return false; }
  78. QMutexLocker locker1(& p2.m_mutex);
  79. QMutexLocker locker2(& p1->m_mutex);
  80. qAssert(p2.m_list.size() == p2.m_hash.size());
  81. return ((p1->m_list == p2.m_list) && (p1->m_hash == p2.m_hash));
  82. }
  83. template <typename Key, typename Value>
  84. void QxCollection<Key, Value>::updateHashPosition(long from /* = 0 */, long to /* = -1 */, bool check /* = false */)
  85. {
  86. if (m_batch) { return; }
  87. QMutexLocker locker(& m_mutex);
  88. qAssert(m_list.size() == m_hash.size());
  89. if (to == -1) { to = (m_list.size() - 1); }
  90. if ((from < 0) || (to >= m_list.size()) || (from > to)) { return; }
  91. for (long idx = from; idx <= to; idx++)
  92. {
  93. const Key & key = m_list.at(idx).first;
  94. m_hash.insert(key, idx);
  95. }
  96. if (check) { qAssert(m_list.size() == m_hash.size()); }
  97. }
  98. template <typename Key, typename Value>
  99. typename QxCollection<Key, Value>::iterator QxCollection<Key, Value>::begin()
  100. {
  101. QMutexLocker locker(& m_mutex);
  102. return m_list.begin();
  103. }
  104. template <typename Key, typename Value>
  105. typename QxCollection<Key, Value>::iterator QxCollection<Key, Value>::end()
  106. {
  107. QMutexLocker locker(& m_mutex);
  108. return m_list.end();
  109. }
  110. template <typename Key, typename Value>
  111. typename QxCollection<Key, Value>::const_iterator QxCollection<Key, Value>::begin() const
  112. {
  113. QMutexLocker locker(& m_mutex);
  114. return m_list.begin();
  115. }
  116. template <typename Key, typename Value>
  117. typename QxCollection<Key, Value>::const_iterator QxCollection<Key, Value>::end() const
  118. {
  119. QMutexLocker locker(& m_mutex);
  120. return m_list.end();
  121. }
  122. #if (QT_VERSION >= 0x050600)
  123. template <typename Key, typename Value>
  124. typename QxCollection<Key, Value>::reverse_iterator QxCollection<Key, Value>::rbegin()
  125. {
  126. QMutexLocker locker(& m_mutex);
  127. return m_list.rbegin();
  128. }
  129. template <typename Key, typename Value>
  130. typename QxCollection<Key, Value>::reverse_iterator QxCollection<Key, Value>::rend()
  131. {
  132. QMutexLocker locker(& m_mutex);
  133. return m_list.rend();
  134. }
  135. template <typename Key, typename Value>
  136. typename QxCollection<Key, Value>::const_reverse_iterator QxCollection<Key, Value>::rbegin() const
  137. {
  138. QMutexLocker locker(& m_mutex);
  139. return m_list.rbegin();
  140. }
  141. template <typename Key, typename Value>
  142. typename QxCollection<Key, Value>::const_reverse_iterator QxCollection<Key, Value>::rend() const
  143. {
  144. QMutexLocker locker(& m_mutex);
  145. return m_list.rend();
  146. }
  147. #endif // (QT_VERSION >= 0x050600)
  148. template <typename Key, typename Value>
  149. void QxCollection<Key, Value>::reserve(long size)
  150. {
  151. if (size <= 0) { return; }
  152. QMutexLocker locker(& m_mutex);
  153. qAssert(m_list.size() == m_hash.size());
  154. m_list.reserve(size);
  155. m_hash.reserve(size);
  156. }
  157. template <typename Key, typename Value>
  158. void QxCollection<Key, Value>::reverse()
  159. {
  160. {
  161. QMutexLocker locker(& m_mutex);
  162. qAssert(m_list.size() == m_hash.size());
  163. std::reverse(m_list.begin(), m_list.end());
  164. }
  165. updateHashPosition();
  166. }
  167. template <typename Key, typename Value>
  168. void QxCollection<Key, Value>::clear()
  169. {
  170. QMutexLocker locker(& m_mutex);
  171. m_hash.clear();
  172. m_list.clear();
  173. }
  174. template <typename Key, typename Value>
  175. long QxCollection<Key, Value>::count() const
  176. {
  177. QMutexLocker locker(& m_mutex);
  178. qAssert(m_list.size() == m_hash.size());
  179. return static_cast<long>(m_list.size());
  180. }
  181. template <typename Key, typename Value>
  182. long QxCollection<Key, Value>::size() const
  183. {
  184. return this->count();
  185. }
  186. template <typename Key, typename Value>
  187. bool QxCollection<Key, Value>::contains(const Key & key) const
  188. {
  189. QMutexLocker locker(& m_mutex);
  190. qAssert(m_list.size() == m_hash.size());
  191. return (m_hash.contains(key));
  192. }
  193. template <typename Key, typename Value>
  194. bool QxCollection<Key, Value>::exist(const Key & key) const
  195. {
  196. return this->contains(key);
  197. }
  198. template <typename Key, typename Value>
  199. bool QxCollection<Key, Value>::empty() const
  200. {
  201. QMutexLocker locker(& m_mutex);
  202. qAssert(m_list.size() == m_hash.size());
  203. return m_list.isEmpty();
  204. }
  205. template <typename Key, typename Value>
  206. bool QxCollection<Key, Value>::push_back(const Key & key, const Value & value)
  207. {
  208. return this->insert(key, value);
  209. }
  210. template <typename Key, typename Value>
  211. bool QxCollection<Key, Value>::push_front(const Key & key, const Value & value)
  212. {
  213. return this->insert(0, key, value);
  214. }
  215. template <typename Key, typename Value>
  216. bool QxCollection<Key, Value>::insert(const Key & key, const Value & value)
  217. {
  218. qAssert(! exist(key));
  219. QMutexLocker locker(& m_mutex);
  220. qAssert(m_list.size() == m_hash.size());
  221. m_list.append(qMakePair(key, value));
  222. m_hash.insert(key, (m_list.size() - 1));
  223. return true;
  224. }
  225. template <typename Key, typename Value>
  226. bool QxCollection<Key, Value>::insert(long index, const Key & key, const Value & value)
  227. {
  228. qAssert(! exist(key));
  229. if (index < 0) { index = 0; }
  230. if (index >= size()) { return this->insert(key, value); }
  231. {
  232. QMutexLocker locker(& m_mutex);
  233. qAssert(m_list.size() == m_hash.size());
  234. m_list.insert(index, qMakePair(key, value));
  235. m_hash.insert(key, index);
  236. }
  237. updateHashPosition(index);
  238. return true;
  239. }
  240. template <typename Key, typename Value>
  241. bool QxCollection<Key, Value>::insert(const QxCollection<Key, Value> & other)
  242. {
  243. {
  244. if (this == (& other)) { return false; }
  245. QMutexLocker locker1(& m_mutex);
  246. QMutexLocker locker2(& other.m_mutex);
  247. m_list.append(other.m_list);
  248. m_hash.unite(other.m_hash);
  249. }
  250. updateHashPosition(0, -1, true);
  251. return true;
  252. }
  253. template <typename Key, typename Value>
  254. bool QxCollection<Key, Value>::insert(long index, const QxCollection<Key, Value> & other)
  255. {
  256. if (index < 0) { index = 0; }
  257. if ((index >= size()) && (index != 0)) { index = (size() - 1); }
  258. if (this == (& other)) { return false; }
  259. QMutexLocker locker1(& other.m_mutex);
  260. {
  261. QMutexLocker locker2(& m_mutex);
  262. qAssert(m_list.size() == m_hash.size());
  263. m_batch = true;
  264. }
  265. for (long l = 0; l < other.size(); l++)
  266. {
  267. const type_pair_key_value & pair = other.m_list.at(l);
  268. this->insert((index + l), pair.first, pair.second);
  269. }
  270. { QMutexLocker locker3(& m_mutex); m_batch = false; }
  271. updateHashPosition(index);
  272. return true;
  273. }
  274. template <typename Key, typename Value>
  275. bool QxCollection<Key, Value>::replace(long index, const Key & key, const Value & value)
  276. {
  277. qAssert(! exist(key));
  278. QMutexLocker locker(& m_mutex);
  279. m_hash.remove(m_list.at(index).first);
  280. m_list.replace(index, qMakePair(key, value));
  281. m_hash.insert(key, index);
  282. qAssert(m_list.size() == m_hash.size());
  283. return true;
  284. }
  285. template <typename Key, typename Value>
  286. bool QxCollection<Key, Value>::swap(long index1, long index2)
  287. {
  288. if (index1 < 0 || index1 >= size()) { return false; }
  289. if (index2 < 0 || index2 >= size()) { return false; }
  290. if (index1 == index2) { return true; }
  291. QMutexLocker locker(& m_mutex);
  292. const Key & key1 = m_list.at(index1).first;
  293. const Key & key2 = m_list.at(index2).first;
  294. m_hash.insert(key1, index2);
  295. m_hash.insert(key2, index1);
  296. m_list.swap(index1, index2);
  297. qAssert(m_list.size() == m_hash.size());
  298. return true;
  299. }
  300. template <typename Key, typename Value>
  301. bool QxCollection<Key, Value>::move(long indexFrom, long indexTo)
  302. {
  303. return swap(indexFrom, indexTo);
  304. }
  305. template <typename Key, typename Value>
  306. bool QxCollection<Key, Value>::removeByKey(const Key & key)
  307. {
  308. qAssert(exist(key));
  309. long pos = 0;
  310. {
  311. QMutexLocker locker(& m_mutex);
  312. pos = m_hash.value(key, -1);
  313. if ((pos < 0) || (pos >= m_list.size())) { return false; }
  314. qAssert(m_list.at(pos).first == key);
  315. m_hash.remove(key);
  316. m_list.removeAt(pos);
  317. }
  318. updateHashPosition(pos, -1, true);
  319. return true;
  320. }
  321. template <typename Key, typename Value>
  322. bool QxCollection<Key, Value>::removeByIndex(long index)
  323. {
  324. if (index < 0 || index >= size()) { return false; }
  325. {
  326. QMutexLocker locker(& m_mutex);
  327. const Key & key = m_list.at(index).first;
  328. qAssert(m_hash.value(key, -1) == index);
  329. m_hash.remove(key);
  330. m_list.removeAt(index);
  331. }
  332. updateHashPosition(index, -1, true);
  333. return true;
  334. }
  335. template <typename Key, typename Value>
  336. bool QxCollection<Key, Value>::removeByIndex(long first, long last)
  337. {
  338. if (first < 0 || first >= size()) { return false; }
  339. if (last < 0 || last >= size()) { return false; }
  340. if (first > last) { return false; }
  341. { QMutexLocker locker(& m_mutex); m_batch = true; }
  342. for (long idx = first; idx <= last; idx++) { removeByIndex(idx); }
  343. { QMutexLocker locker(& m_mutex); m_batch = false; }
  344. updateHashPosition(first);
  345. return true;
  346. }
  347. template <typename Key, typename Value>
  348. bool QxCollection<Key, Value>::removeFirst()
  349. {
  350. return this->removeByIndex(0);
  351. }
  352. template <typename Key, typename Value>
  353. bool QxCollection<Key, Value>::removeLast()
  354. {
  355. return this->removeByIndex(size() - 1);
  356. }
  357. template <typename Key, typename Value>
  358. typename QxCollection<Key, Value>::const_reference_value QxCollection<Key, Value>::getByKey(const Key & key) const
  359. {
  360. qAssert(exist(key));
  361. QMutexLocker locker(& m_mutex);
  362. qAssert(m_list.size() == m_hash.size());
  363. const type_pair_key_value & pair = m_list.at(m_hash.value(key, -1));
  364. qAssert(pair.first == key);
  365. return pair.second;
  366. }
  367. template <typename Key, typename Value>
  368. typename QxCollection<Key, Value>::const_reference_value QxCollection<Key, Value>::getByIndex(long index) const
  369. {
  370. QMutexLocker locker(& m_mutex);
  371. qAssert(m_list.size() == m_hash.size());
  372. qAssert((index >= 0) && (index < static_cast<long>(m_list.size())));
  373. qAssert(m_hash.value(m_list.at(index).first, -1) == index);
  374. return m_list.at(index).second;
  375. }
  376. template <typename Key, typename Value>
  377. typename QxCollection<Key, Value>::const_reference_value QxCollection<Key, Value>::getFirst() const
  378. {
  379. qAssert(! empty());
  380. QMutexLocker locker(& m_mutex);
  381. qAssert(m_list.size() == m_hash.size());
  382. return m_list.at(0).second;
  383. }
  384. template <typename Key, typename Value>
  385. typename QxCollection<Key, Value>::const_reference_value QxCollection<Key, Value>::getLast() const
  386. {
  387. qAssert(! empty());
  388. QMutexLocker locker(& m_mutex);
  389. qAssert(m_list.size() == m_hash.size());
  390. return m_list.at(m_list.size() - 1).second;
  391. }
  392. template <typename Key, typename Value>
  393. typename QxCollection<Key, Value>::const_reference_key QxCollection<Key, Value>::getKeyByIndex(long index) const
  394. {
  395. QMutexLocker locker(& m_mutex);
  396. qAssert(m_list.size() == m_hash.size());
  397. qAssert((index >= 0) && (index < static_cast<long>(m_list.size())));
  398. qAssert(m_hash.value(m_list.at(index).first, -1) == index);
  399. return m_list.at(index).first;
  400. }
  401. template <typename Key, typename Value>
  402. void QxCollection<Key, Value>::sortByKey(bool bAscending /* = true */)
  403. {
  404. if (bAscending) { QMutexLocker locker(& m_mutex); std::sort(m_list.begin(), m_list.end(), (& compareKeyValue<std::is_pointer<Key>::value || qx::trait::is_smart_ptr<Key>::value, 0>::compareByKeyAscending)); }
  405. else { QMutexLocker locker(& m_mutex); std::sort(m_list.begin(), m_list.end(), (& compareKeyValue<std::is_pointer<Key>::value || qx::trait::is_smart_ptr<Key>::value, 0>::compareByKeyDescending)); }
  406. updateHashPosition(0, -1, true);
  407. }
  408. template <typename Key, typename Value>
  409. void QxCollection<Key, Value>::sortByValue(bool bAscending /* = true */)
  410. {
  411. if (bAscending) { QMutexLocker locker(& m_mutex); std::sort(m_list.begin(), m_list.end(), (& compareKeyValue<std::is_pointer<Value>::value || qx::trait::is_smart_ptr<Value>::value, 0>::compareByValueAscending)); }
  412. else { QMutexLocker locker(& m_mutex); std::sort(m_list.begin(), m_list.end(), (& compareKeyValue<std::is_pointer<Value>::value || qx::trait::is_smart_ptr<Value>::value, 0>::compareByValueDescending)); }
  413. updateHashPosition(0, -1, true);
  414. }
  415. } // namespace qx
  416. template <typename Key, typename Value>
  417. QDataStream & operator<< (QDataStream & stream, const qx::QxCollection<Key, Value> & t)
  418. {
  419. long lCount = t.count();
  420. stream << (qint32)(lCount);
  421. for (long l = 0; l < lCount; l++)
  422. {
  423. stream << t.getKeyByIndex(l);
  424. stream << t.getByIndex(l);
  425. }
  426. return stream;
  427. }
  428. template <typename Key, typename Value>
  429. QDataStream & operator>> (QDataStream & stream, qx::QxCollection<Key, Value> & t)
  430. {
  431. qint32 lCount = 0;
  432. stream >> lCount;
  433. t.clear();
  434. t.reserve(lCount);
  435. for (qint32 l = 0; l < lCount; l++)
  436. {
  437. Key key; stream >> key;
  438. Value value; stream >> value;
  439. t.insert(key, value);
  440. }
  441. return stream;
  442. }