safe_iterator.tcc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. // Debugging iterator implementation (out of line) -*- C++ -*-
  2. // Copyright (C) 2003-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file debug/safe_iterator.tcc
  21. * This file is a GNU debug extension to the Standard C++ Library.
  22. */
  23. #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_TCC
  24. #define _GLIBCXX_DEBUG_SAFE_ITERATOR_TCC 1
  25. #include <bits/stl_algobase.h>
  26. namespace __gnu_debug
  27. {
  28. template<typename _Iterator, typename _Sequence, typename _Category>
  29. typename _Distance_traits<_Iterator>::__type
  30. _Safe_iterator<_Iterator, _Sequence, _Category>::
  31. _M_get_distance_from_begin() const
  32. {
  33. typedef _Sequence_traits<_Sequence> _SeqTraits;
  34. // No need to consider before_begin as this function is only used in
  35. // _M_can_advance which won't be used for forward_list iterators.
  36. if (_M_is_begin())
  37. return std::make_pair(0, __dp_exact);
  38. if (_M_is_end())
  39. return _SeqTraits::_S_size(*_M_get_sequence());
  40. typename _Distance_traits<_Iterator>::__type __res
  41. = __get_distance(_M_get_sequence()->_M_base().begin(), base());
  42. if (__res.second == __dp_equality)
  43. return std::make_pair(1, __dp_sign);
  44. return __res;
  45. }
  46. template<typename _Iterator, typename _Sequence, typename _Category>
  47. typename _Distance_traits<_Iterator>::__type
  48. _Safe_iterator<_Iterator, _Sequence, _Category>::
  49. _M_get_distance_to_end() const
  50. {
  51. typedef _Sequence_traits<_Sequence> _SeqTraits;
  52. // No need to consider before_begin as this function is only used in
  53. // _M_can_advance which won't be used for forward_list iterators.
  54. if (_M_is_begin())
  55. return _SeqTraits::_S_size(*_M_get_sequence());
  56. if (_M_is_end())
  57. return std::make_pair(0, __dp_exact);
  58. typename _Distance_traits<_Iterator>::__type __res
  59. = __get_distance(base(), _M_get_sequence()->_M_base().end());
  60. if (__res.second == __dp_equality)
  61. return std::make_pair(1, __dp_sign);
  62. return __res;
  63. }
  64. template<typename _Iterator, typename _Sequence, typename _Category>
  65. bool
  66. _Safe_iterator<_Iterator, _Sequence, _Category>::
  67. _M_can_advance(difference_type __n, bool __strict) const
  68. {
  69. if (this->_M_singular())
  70. return false;
  71. if (__n == 0)
  72. return true;
  73. if (__n < 0)
  74. {
  75. std::pair<difference_type, _Distance_precision> __dist =
  76. _M_get_distance_from_begin();
  77. return __dist.second == __dp_exact
  78. ? __dist.first >= -__n
  79. : !__strict && __dist.first > 0;
  80. }
  81. else
  82. {
  83. std::pair<difference_type, _Distance_precision> __dist =
  84. _M_get_distance_to_end();
  85. return __dist.second == __dp_exact
  86. ? __dist.first >= __n
  87. : !__strict && __dist.first > 0;
  88. }
  89. }
  90. template<typename _Iterator, typename _Sequence, typename _Category>
  91. typename _Distance_traits<_Iterator>::__type
  92. _Safe_iterator<_Iterator, _Sequence, _Category>::
  93. _M_get_distance_to(const _Safe_iterator& __rhs) const
  94. {
  95. typedef typename _Distance_traits<_Iterator>::__type _Dist;
  96. typedef _Sequence_traits<_Sequence> _SeqTraits;
  97. _Dist __base_dist = __get_distance(this->base(), __rhs.base());
  98. if (__base_dist.second == __dp_exact)
  99. return __base_dist;
  100. _Dist __seq_dist = _SeqTraits::_S_size(*this->_M_get_sequence());
  101. if (this->_M_is_before_begin())
  102. {
  103. if (__rhs._M_is_begin())
  104. return std::make_pair(1, __dp_exact);
  105. return __seq_dist.second == __dp_exact
  106. ? std::make_pair(__seq_dist.first + 1, __dp_exact)
  107. : __seq_dist;
  108. }
  109. if (this->_M_is_begin())
  110. {
  111. if (__rhs._M_is_before_begin())
  112. return std::make_pair(-1, __dp_exact);
  113. if (__rhs._M_is_end())
  114. return __seq_dist;
  115. return std::make_pair(__seq_dist.first,
  116. __seq_dist.second == __dp_exact
  117. ? __dp_sign_max_size : __seq_dist.second);
  118. }
  119. if (this->_M_is_end())
  120. {
  121. if (__rhs._M_is_before_begin())
  122. return __seq_dist.second == __dp_exact
  123. ? std::make_pair(-__seq_dist.first - 1, __dp_exact)
  124. : std::make_pair(-__seq_dist.first, __dp_sign);
  125. if (__rhs._M_is_begin())
  126. return std::make_pair(-__seq_dist.first, __seq_dist.second);
  127. return std::make_pair(-__seq_dist.first,
  128. __seq_dist.second == __dp_exact
  129. ? __dp_sign_max_size : __seq_dist.second);
  130. }
  131. if (__rhs._M_is_before_begin())
  132. return __seq_dist.second == __dp_exact
  133. ? std::make_pair(__seq_dist.first - 1, __dp_exact)
  134. : std::make_pair(-__seq_dist.first, __dp_sign);
  135. if (__rhs._M_is_begin())
  136. return std::make_pair(-__seq_dist.first,
  137. __seq_dist.second == __dp_exact
  138. ? __dp_sign_max_size : __seq_dist.second);
  139. if (__rhs._M_is_end())
  140. return std::make_pair(__seq_dist.first,
  141. __seq_dist.second == __dp_exact
  142. ? __dp_sign_max_size : __seq_dist.second);
  143. return std::make_pair(1, __dp_equality);
  144. }
  145. template<typename _Iterator, typename _Sequence, typename _Category>
  146. bool
  147. _Safe_iterator<_Iterator, _Sequence, _Category>::
  148. _M_valid_range(const _Safe_iterator& __rhs,
  149. std::pair<difference_type, _Distance_precision>& __dist,
  150. bool __check_dereferenceable) const
  151. {
  152. if (!_M_can_compare(__rhs))
  153. return false;
  154. /* Determine iterators order */
  155. __dist = _M_get_distance_to(__rhs);
  156. switch (__dist.second)
  157. {
  158. case __dp_equality:
  159. if (__dist.first == 0)
  160. return true;
  161. break;
  162. case __dp_sign:
  163. case __dp_exact:
  164. // If range is not empty first iterator must be dereferenceable.
  165. if (__dist.first > 0)
  166. return !__check_dereferenceable || _M_dereferenceable();
  167. return __dist.first == 0;
  168. }
  169. // Assume that this is a valid range; we can't check anything else.
  170. return true;
  171. }
  172. template<typename _Iterator, typename _Sequence>
  173. bool
  174. _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>::
  175. _M_valid_range(const _Safe_iterator& __rhs,
  176. std::pair<difference_type,
  177. _Distance_precision>& __dist) const
  178. {
  179. if (!this->_M_can_compare(__rhs))
  180. return false;
  181. /* Determine iterators order */
  182. __dist = std::make_pair(__rhs.base() - this->base(), __dp_exact);
  183. // If range is not empty first iterator must be dereferenceable.
  184. if (__dist.first > 0)
  185. return this->_M_dereferenceable();
  186. return __dist.first == 0;
  187. }
  188. } // namespace __gnu_debug
  189. namespace std _GLIBCXX_VISIBILITY(default)
  190. {
  191. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  192. template<bool _IsMove,
  193. typename _Ite, typename _Seq, typename _Cat, typename _OI>
  194. _OI
  195. __copy_move_a(
  196. const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first,
  197. const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __last,
  198. _OI __result)
  199. {
  200. typename ::__gnu_debug::_Distance_traits<_Ite>::__type __dist;
  201. __glibcxx_check_valid_range2(__first, __last, __dist);
  202. __glibcxx_check_can_increment(__result, __dist.first);
  203. if (__dist.second > ::__gnu_debug::__dp_equality)
  204. return std::__copy_move_a<_IsMove>(__first.base(), __last.base(),
  205. __result);
  206. return std::__copy_move_a1<_IsMove>(__first, __last, __result);
  207. }
  208. template<bool _IsMove,
  209. typename _II, typename _Ite, typename _Seq, typename _Cat>
  210. __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>
  211. __copy_move_a(_II __first, _II __last,
  212. const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __result)
  213. {
  214. typename ::__gnu_debug::_Distance_traits<_II>::__type __dist;
  215. __glibcxx_check_valid_range2(__first, __last, __dist);
  216. __glibcxx_check_can_increment(__result, __dist.first);
  217. if (__dist.second > ::__gnu_debug::__dp_sign
  218. && __result._M_can_advance(__dist.first, true))
  219. return ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>(
  220. std::__copy_move_a<_IsMove>(__first, __last, __result.base()),
  221. __result._M_sequence);
  222. return std::__copy_move_a1<_IsMove>(__first, __last, __result);
  223. }
  224. template<bool _IsMove,
  225. typename _IIte, typename _ISeq, typename _ICat,
  226. typename _OIte, typename _OSeq, typename _OCat>
  227. ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>
  228. __copy_move_a(
  229. const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __first,
  230. const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __last,
  231. const ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>& __result)
  232. {
  233. typename ::__gnu_debug::_Distance_traits<_IIte>::__type __dist;
  234. __glibcxx_check_valid_range2(__first, __last, __dist);
  235. __glibcxx_check_can_increment(__result, __dist.first);
  236. if (__dist.second > ::__gnu_debug::__dp_equality)
  237. {
  238. if (__dist.second > ::__gnu_debug::__dp_sign
  239. && __result._M_can_advance(__dist.first, true))
  240. return ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>(
  241. std::__copy_move_a<_IsMove>(__first.base(), __last.base(),
  242. __result.base()),
  243. __result._M_sequence);
  244. return std::__copy_move_a<_IsMove>(__first.base(), __last.base(),
  245. __result);
  246. }
  247. return std::__copy_move_a1<_IsMove>(__first, __last, __result);
  248. }
  249. template<bool _IsMove,
  250. typename _Ite, typename _Seq, typename _Cat, typename _OI>
  251. _OI
  252. __copy_move_backward_a(
  253. const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first,
  254. const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __last,
  255. _OI __result)
  256. {
  257. typename ::__gnu_debug::_Distance_traits<_Ite>::__type __dist;
  258. __glibcxx_check_valid_range2(__first, __last, __dist);
  259. __glibcxx_check_can_increment(__result, -__dist.first);
  260. if (__dist.second > ::__gnu_debug::__dp_equality)
  261. return std::__copy_move_backward_a<_IsMove>(
  262. __first.base(), __last.base(), __result);
  263. return std::__copy_move_backward_a1<_IsMove>(__first, __last, __result);
  264. }
  265. template<bool _IsMove,
  266. typename _II, typename _Ite, typename _Seq, typename _Cat>
  267. __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>
  268. __copy_move_backward_a(_II __first, _II __last,
  269. const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __result)
  270. {
  271. typename ::__gnu_debug::_Distance_traits<_II>::__type __dist;
  272. __glibcxx_check_valid_range2(__first, __last, __dist);
  273. __glibcxx_check_can_increment(__result, -__dist.first);
  274. if (__dist.second > ::__gnu_debug::__dp_sign
  275. && __result._M_can_advance(-__dist.first, true))
  276. return ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>(
  277. std::__copy_move_backward_a<_IsMove>(__first, __last,
  278. __result.base()),
  279. __result._M_sequence);
  280. return std::__copy_move_backward_a1<_IsMove>(__first, __last, __result);
  281. }
  282. template<bool _IsMove,
  283. typename _IIte, typename _ISeq, typename _ICat,
  284. typename _OIte, typename _OSeq, typename _OCat>
  285. ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>
  286. __copy_move_backward_a(
  287. const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __first,
  288. const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __last,
  289. const ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>& __result)
  290. {
  291. typename ::__gnu_debug::_Distance_traits<_IIte>::__type __dist;
  292. __glibcxx_check_valid_range2(__first, __last, __dist);
  293. __glibcxx_check_can_increment(__result, -__dist.first);
  294. if (__dist.second > ::__gnu_debug::__dp_equality)
  295. {
  296. if (__dist.second > ::__gnu_debug::__dp_sign
  297. && __result._M_can_advance(-__dist.first, true))
  298. return ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>(
  299. std::__copy_move_backward_a<_IsMove>(__first.base(), __last.base(),
  300. __result.base()),
  301. __result._M_sequence);
  302. return std::__copy_move_backward_a<_IsMove>(
  303. __first.base(), __last.base(), __result);
  304. }
  305. return std::__copy_move_backward_a1<_IsMove>(__first, __last, __result);
  306. }
  307. template<typename _Ite, typename _Seq, typename _Cat, typename _Tp>
  308. void
  309. __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first,
  310. const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __last,
  311. const _Tp& __value)
  312. {
  313. typename ::__gnu_debug::_Distance_traits<_Ite>::__type __dist;
  314. __glibcxx_check_valid_range2(__first, __last, __dist);
  315. if (__dist.second > ::__gnu_debug::__dp_equality)
  316. std::__fill_a(__first.base(), __last.base(), __value);
  317. std::__fill_a1(__first, __last, __value);
  318. }
  319. template<typename _Ite, typename _Seq, typename _Cat, typename _Size,
  320. typename _Tp>
  321. ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>
  322. __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first,
  323. _Size __n, const _Tp& __value,
  324. std::input_iterator_tag)
  325. {
  326. #if __cplusplus >= 201103L
  327. static_assert(is_integral<_Size>{}, "fill_n must pass integral size");
  328. #endif
  329. if (__n <= 0)
  330. return __first;
  331. __glibcxx_check_can_increment(__first, __n);
  332. if (__first._M_can_advance(__n, true))
  333. return ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>(
  334. std::__fill_n_a(__first.base(), __n, __value, _Cat()),
  335. __first._M_sequence);
  336. return std::__fill_n_a1(__first, __n, __value);
  337. }
  338. template<typename _II1, typename _Seq1, typename _Cat1, typename _II2>
  339. bool
  340. __equal_aux(
  341. const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __first1,
  342. const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __last1,
  343. _II2 __first2)
  344. {
  345. typename ::__gnu_debug::_Distance_traits<_II1>::__type __dist;
  346. __glibcxx_check_valid_range2(__first1, __last1, __dist);
  347. __glibcxx_check_can_increment(__first2, __dist.first);
  348. if (__dist.second > ::__gnu_debug::__dp_equality)
  349. return std::__equal_aux(__first1.base(), __last1.base(), __first2);
  350. return std::__equal_aux1(__first1, __last1, __first2);
  351. }
  352. template<typename _II1, typename _II2, typename _Seq2, typename _Cat2>
  353. bool
  354. __equal_aux(_II1 __first1, _II1 __last1,
  355. const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>& __first2)
  356. {
  357. typename ::__gnu_debug::_Distance_traits<_II1>::__type __dist;
  358. __glibcxx_check_valid_range2(__first1, __last1, __dist);
  359. __glibcxx_check_can_increment(__first2, __dist.first);
  360. if (__dist.second > ::__gnu_debug::__dp_sign
  361. && __first2._M_can_advance(__dist.first, true))
  362. return std::__equal_aux(__first1, __last1, __first2.base());
  363. return std::__equal_aux1(__first1, __last1, __first2);
  364. }
  365. template<typename _II1, typename _Seq1, typename _Cat1,
  366. typename _II2, typename _Seq2, typename _Cat2>
  367. bool
  368. __equal_aux(
  369. const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __first1,
  370. const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __last1,
  371. const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>& __first2)
  372. {
  373. typename ::__gnu_debug::_Distance_traits<_II1>::__type __dist;
  374. __glibcxx_check_valid_range2(__first1, __last1, __dist);
  375. __glibcxx_check_can_increment(__first2, __dist.first);
  376. if (__dist.second > ::__gnu_debug::__dp_equality)
  377. {
  378. if (__dist.second > ::__gnu_debug::__dp_sign &&
  379. __first2._M_can_advance(__dist.first, true))
  380. return std::__equal_aux(__first1.base(), __last1.base(),
  381. __first2.base());
  382. return std::__equal_aux(__first1.base(), __last1.base(), __first2);
  383. }
  384. return __equal_aux1(__first1, __last1, __first2);
  385. }
  386. _GLIBCXX_END_NAMESPACE_VERSION
  387. } // namespace std
  388. #endif