algorithm.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. // Copyright (C) 2020 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_PARSER_DETAIL_TEXT_DETAIL_ALGORITHM_HPP
  7. #define BOOST_PARSER_DETAIL_TEXT_DETAIL_ALGORITHM_HPP
  8. #include <boost/parser/detail/text/concepts.hpp>
  9. #include <boost/parser/detail/detection.hpp>
  10. #include <boost/parser/detail/text/detail/iterator.hpp>
  11. #include <iterator>
  12. #include <numeric>
  13. #include <type_traits>
  14. #include <utility>
  15. #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
  16. #include <ranges>
  17. #endif
  18. #include <cstdint>
  19. namespace boost::parser::detail { namespace text { namespace detail {
  20. template<typename I>
  21. auto prev(I it)
  22. {
  23. #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
  24. return std::ranges::prev(it);
  25. #else
  26. return std::prev(it);
  27. #endif
  28. }
  29. template<typename I>
  30. auto next(I it)
  31. {
  32. #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
  33. return std::ranges::next(it);
  34. #else
  35. return std::next(it);
  36. #endif
  37. }
  38. template<typename T>
  39. using remove_cv_ref_t =
  40. typename std::remove_cv<typename std::remove_reference<T>::type>::type;
  41. #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
  42. // A grapheme_range that has a sentinel type that is not an iterator, but
  43. // that is comparable with T's interator type.
  44. template<typename T>
  45. concept cp_sentinel_gr_rng =
  46. grapheme_range<T> && !grapheme_iter<sentinel_t<T>> &&
  47. requires(iterator_t<T> first, sentinel_t<T> last) {
  48. { first.base() == last } -> std::convertible_to<bool>;
  49. };
  50. template<typename T>
  51. using gr_rng_cp_iter_t = decltype(std::declval<iterator_t<T>>().base());
  52. template<typename T>
  53. using gr_rng_cp_sent_t = std::conditional_t<
  54. cp_sentinel_gr_rng<T>,
  55. sentinel_t<T>,
  56. gr_rng_cp_iter_t<T>>;
  57. #else
  58. template<typename T>
  59. using has_base = decltype(std::declval<T>().base());
  60. template<typename T>
  61. using sentinel_comparable_to_iter_base =
  62. decltype(std::declval<T>().begin().base() == std::declval<T>().end());
  63. // A grapheme_range that has a sentinel type that is not an iterator, but
  64. // that is comparable with T's interator type.
  65. template<
  66. typename T,
  67. bool IsIt = is_detected_v<has_base, iterator_t<T>> &&
  68. !is_detected_v<has_base, sentinel_t<T>> &&
  69. is_detected_v<sentinel_comparable_to_iter_base, T>>
  70. constexpr bool is_cp_sentinel_gr_rng_v = false;
  71. template<typename T>
  72. constexpr bool is_cp_sentinel_gr_rng_v<T, true> = true;
  73. template<typename T>
  74. using gr_rng_cp_iter_t =
  75. decltype(detail::begin(std::declval<T &>()).base());
  76. template<typename T>
  77. using gr_rng_cp_sent_t = std::conditional_t<
  78. is_cp_sentinel_gr_rng_v<T>,
  79. sentinel_t<T>,
  80. gr_rng_cp_iter_t<T>>;
  81. #endif
  82. template<typename T>
  83. using has_begin = decltype(*detail::begin(std::declval<T &>()));
  84. template<typename T>
  85. using has_end = decltype(*detail::end(std::declval<T &>()));
  86. template<typename T>
  87. using value_type_ = typename std::remove_cv<
  88. typename std::remove_reference<typename T::value_type>::type>::type;
  89. template<typename T>
  90. using nonpointer_iterator_category_ =
  91. typename T::iterator::iterator_category;
  92. template<typename T>
  93. using iterator_pointer_expr = std::is_pointer<typename T::iterator>;
  94. template<typename T>
  95. using iterator_category_ = typename std::conditional<
  96. detected_or_t<std::false_type, iterator_pointer_expr>::value,
  97. std::random_access_iterator_tag,
  98. detected_t<nonpointer_iterator_category_, T>>::type;
  99. template<typename T, typename U, int N>
  100. constexpr bool
  101. is_convertible_and_n_bytes_v = std::is_convertible<T, U>::value &&
  102. sizeof(T) == N;
  103. template<typename T>
  104. constexpr bool is_char_iter_v =
  105. std::is_same<char *, typename std::remove_cv<T>::type>::value ||
  106. std::is_same<char const *, typename std::remove_cv<T>::type>::value ||
  107. #if defined(__cpp_char8_t)
  108. std::is_same<char8_t *, typename std::remove_cv<T>::type>::value ||
  109. std::is_same<char8_t const *, typename std::remove_cv<T>::type>::
  110. value ||
  111. #endif
  112. is_convertible_and_n_bytes_v<detected_t<value_type_, T>, char, 1>;
  113. // Needed for detected_or_t.
  114. template<typename T>
  115. using is_char_iter = std::integral_constant<bool, is_char_iter_v<T>>;
  116. template<typename T>
  117. constexpr bool is_char_range_v =
  118. (is_convertible_and_n_bytes_v<
  119. remove_cv_ref_t<detected_t<has_begin, T>>,
  120. char,
  121. 1> &&
  122. is_convertible_and_n_bytes_v<
  123. remove_cv_ref_t<detected_t<has_end, T>>,
  124. char,
  125. 1>);
  126. template<
  127. typename T,
  128. typename R1,
  129. typename Exclude,
  130. bool R1IsCharRange =
  131. is_char_range_v<R1> && !std::is_same<R1, Exclude>::value>
  132. struct rng_alg_ret
  133. {
  134. };
  135. template<typename T, typename R1, typename Exclude>
  136. struct rng_alg_ret<T, R1, Exclude, true>
  137. {
  138. using type = T;
  139. };
  140. template<typename T, typename R1, typename Exclude = void>
  141. using rng_alg_ret_t = typename rng_alg_ret<T, R1, Exclude>::type;
  142. template<
  143. typename T,
  144. typename R1,
  145. typename R2,
  146. bool R1IsCharRange = is_char_range_v<R1>,
  147. bool R2IsCharRange = is_char_range_v<R2>>
  148. struct rngs_alg_ret
  149. {
  150. };
  151. template<typename T, typename R1, typename R2>
  152. struct rngs_alg_ret<T, R1, R2, true, true>
  153. {
  154. using type = T;
  155. };
  156. template<typename T, typename R1, typename R2>
  157. using rngs_alg_ret_t = typename rngs_alg_ret<T, R1, R2>::type;
  158. template<typename T>
  159. using has_contig_begin = decltype(&*detail::begin(std::declval<T &>()));
  160. template<typename T>
  161. using has_contig_end = decltype(&*detail::end(std::declval<T &>()));
  162. template<typename T>
  163. constexpr bool is_contig_char_range_v =
  164. ((std::is_same<
  165. fixup_ptr_t<detected_t<has_contig_begin, T>>,
  166. char const *>::value &&
  167. std::is_same<
  168. fixup_ptr_t<detected_t<has_contig_end, T>>,
  169. char const *>::value)
  170. #if defined(__cpp_char8_t)
  171. || (std::is_same<
  172. fixup_ptr_t<detected_t<has_contig_begin, T>>,
  173. char8_t const *>::value &&
  174. std::is_same<
  175. fixup_ptr_t<detected_t<has_contig_end, T>>,
  176. char8_t const *>::value)
  177. #endif
  178. ) &&
  179. std::is_convertible<
  180. iterator_category_<T>,
  181. std::random_access_iterator_tag>::value;
  182. template<
  183. typename T,
  184. typename R1,
  185. bool R1IsContigCharRange = is_contig_char_range_v<R1>>
  186. struct contig_rng_alg_ret
  187. {
  188. };
  189. template<typename T, typename R1>
  190. struct contig_rng_alg_ret<T, R1, true>
  191. {
  192. using type = T;
  193. };
  194. template<typename T, typename R1>
  195. using contig_rng_alg_ret_t = typename contig_rng_alg_ret<T, R1>::type;
  196. template<
  197. typename T,
  198. typename R1,
  199. typename R2,
  200. bool R1IsContigCharRange = is_contig_char_range_v<R1>,
  201. bool R2IsContigCharRange = is_contig_char_range_v<R2>>
  202. struct contig_rngs_alg_ret
  203. {
  204. };
  205. template<typename T, typename R1, typename R2>
  206. struct contig_rngs_alg_ret<T, R1, R2, true, true>
  207. {
  208. using type = T;
  209. };
  210. template<typename T, typename R1, typename R2>
  211. using contig_rngs_alg_ret_t = typename contig_rngs_alg_ret<T, R1, R2>::type;
  212. template<typename T>
  213. constexpr bool is_char16_range_v =
  214. (is_convertible_and_n_bytes_v<
  215. remove_cv_ref_t<detected_t<has_begin, T>>,
  216. uint16_t,
  217. 2> &&
  218. is_convertible_and_n_bytes_v<
  219. remove_cv_ref_t<detected_t<has_end, T>>,
  220. uint16_t,
  221. 2>);
  222. template<
  223. typename T,
  224. typename R1,
  225. bool R1IsChar16Range = is_char16_range_v<R1>>
  226. struct rng16_alg_ret
  227. {
  228. };
  229. template<typename T, typename R1>
  230. struct rng16_alg_ret<T, R1, true>
  231. {
  232. using type = T;
  233. };
  234. template<typename T, typename R1>
  235. using rng16_alg_ret_t = typename rng16_alg_ret<T, R1>::type;
  236. template<typename T, typename R1, bool R1IsCharRange = is_char_iter_v<R1>>
  237. struct char_iter_ret
  238. {
  239. };
  240. template<typename T, typename R1>
  241. struct char_iter_ret<T, R1, true>
  242. {
  243. using type = T;
  244. };
  245. template<typename T, typename R1>
  246. using char_iter_ret_t = typename char_iter_ret<T, R1>::type;
  247. template<typename T>
  248. constexpr bool is_code_point_v = std::is_integral<T>::value &&
  249. sizeof(T) == 4;
  250. template<typename T>
  251. using has_deref_and_incr =
  252. std::pair<decltype(*std::declval<T>()), decltype(++std::declval<T>())>;
  253. template<typename T>
  254. constexpr bool is_cp_iter_v =
  255. ((std::is_pointer<T>::value &&
  256. is_code_point_v<typename std::remove_cv<
  257. typename std::remove_pointer<T>::type>::type>) ||
  258. (is_detected_v<has_deref_and_incr, T> &&
  259. is_code_point_v<
  260. typename std::remove_cv<detected_t<value_type_, T>>::type>));
  261. template<typename T, typename R1, bool R1IsCPRange = is_cp_iter_v<R1>>
  262. struct cp_iter_ret
  263. {
  264. };
  265. template<typename T, typename R1>
  266. struct cp_iter_ret<T, R1, true>
  267. {
  268. using type = T;
  269. };
  270. template<typename T, typename R1>
  271. using cp_iter_ret_t = typename cp_iter_ret<T, R1>::type;
  272. template<
  273. typename T,
  274. typename R1,
  275. typename R2,
  276. bool R1R2AreCPRanges = is_cp_iter_v<R1> && is_cp_iter_v<R2>>
  277. struct cp_iters_ret
  278. {
  279. };
  280. template<typename T, typename R1, typename R2>
  281. struct cp_iters_ret<T, R1, R2, true>
  282. {
  283. using type = T;
  284. };
  285. template<typename T, typename R1, typename R2>
  286. using cp_iters_ret_t = typename cp_iters_ret<T, R1, R2>::type;
  287. template<typename T>
  288. constexpr bool is_16_code_unit_v = std::is_integral<T>::value &&
  289. sizeof(T) == 2;
  290. template<typename T>
  291. constexpr bool is_16_iter_v =
  292. ((std::is_pointer<T>::value &&
  293. is_16_code_unit_v<typename std::remove_cv<
  294. typename std::remove_pointer<T>::type>::type>) ||
  295. (is_detected_v<has_deref_and_incr, T> &&
  296. is_16_code_unit_v<
  297. typename std::remove_cv<detected_t<value_type_, T>>::type>));
  298. template<typename T, typename R1, bool R1IsCPRange = is_16_iter_v<R1>>
  299. struct _16_iter_ret
  300. {
  301. };
  302. template<typename T, typename R1>
  303. struct _16_iter_ret<T, R1, true>
  304. {
  305. using type = T;
  306. };
  307. template<typename T, typename R1>
  308. using _16_iter_ret_t = typename _16_iter_ret<T, R1>::type;
  309. template<typename T>
  310. constexpr bool is_8_code_unit_v = std::is_integral<T>::value &&
  311. sizeof(T) == 1;
  312. template<typename T>
  313. constexpr bool is_8_iter_v =
  314. ((std::is_pointer<T>::value &&
  315. is_8_code_unit_v<typename std::remove_cv<
  316. typename std::remove_pointer<T>::type>::type>) ||
  317. (is_detected_v<has_deref_and_incr, T> &&
  318. is_8_code_unit_v<
  319. typename std::remove_cv<detected_t<value_type_, T>>::type>));
  320. template<typename T, typename R1, bool R1IsCPRange = is_8_iter_v<R1>>
  321. struct _8_iter_ret
  322. {
  323. };
  324. template<typename T, typename R1>
  325. struct _8_iter_ret<T, R1, true>
  326. {
  327. using type = T;
  328. };
  329. template<typename T, typename R1>
  330. using _8_iter_ret_t = typename _8_iter_ret<T, R1>::type;
  331. template<typename T, typename U>
  332. using comparable_ = decltype(std::declval<T>() == std::declval<U>());
  333. template<
  334. typename T,
  335. typename CPIter,
  336. typename Sentinel,
  337. bool FIsWordPropFunc = is_cp_iter_v<CPIter> &&
  338. is_detected_v<comparable_, CPIter, Sentinel>>
  339. struct cp_iter_sntl_ret
  340. {
  341. };
  342. template<typename T, typename CPIter, typename Sentinel>
  343. struct cp_iter_sntl_ret<T, CPIter, Sentinel, true>
  344. {
  345. using type = T;
  346. };
  347. template<typename T, typename CPIter, typename Sentinel>
  348. using cp_iter_sntl_ret_t =
  349. typename cp_iter_sntl_ret<T, CPIter, Sentinel>::type;
  350. template<typename T, typename R>
  351. using cp_rng_alg_ret_t =
  352. cp_iter_sntl_ret_t<T, iterator_t<R>, sentinel_t<R>>;
  353. template<
  354. typename T,
  355. typename CPIter1,
  356. typename Sentinel1,
  357. typename CPIter2,
  358. typename Sentinel2,
  359. bool AreCPRanges = is_cp_iter_v<CPIter1> && is_cp_iter_v<CPIter2> &&
  360. is_detected_v<comparable_, CPIter1, Sentinel1> &&
  361. is_detected_v<comparable_, CPIter2, Sentinel2>>
  362. struct cp_iters_sntls_ret
  363. {
  364. };
  365. template<
  366. typename T,
  367. typename CPIter1,
  368. typename Sentinel1,
  369. typename CPIter2,
  370. typename Sentinel2>
  371. struct cp_iters_sntls_ret<T, CPIter1, Sentinel1, CPIter2, Sentinel2, true>
  372. {
  373. using type = T;
  374. };
  375. template<
  376. typename T,
  377. typename CPIter1,
  378. typename Sentinel1,
  379. typename CPIter2,
  380. typename Sentinel2>
  381. using cp_iters_sntls_ret_t =
  382. typename cp_iters_sntls_ret<T, CPIter1, Sentinel1, CPIter2, Sentinel2>::
  383. type;
  384. template<typename T, typename R1, typename R2>
  385. using cp_rngs_alg_ret_t = cp_iters_sntls_ret_t<
  386. T,
  387. iterator_t<R1>,
  388. sentinel_t<R1>,
  389. iterator_t<R2>,
  390. sentinel_t<R2>>;
  391. template<int Size, typename T>
  392. constexpr bool is_cu_iter_v =
  393. Size == 1 ? is_char_iter_v<T> : is_16_iter_v<T>;
  394. template<
  395. int Size,
  396. typename T,
  397. typename U,
  398. bool UIsCUIter = is_cu_iter_v<Size, U>>
  399. struct cu_iter_ret
  400. {
  401. };
  402. template<int Size, typename T, typename U>
  403. struct cu_iter_ret<Size, T, U, true>
  404. {
  405. using type = T;
  406. };
  407. template<int Size, typename T, typename U>
  408. using cu_iter_ret_t = typename cu_iter_ret<Size, T, U>::type;
  409. template<int Size, typename T>
  410. constexpr bool is_cu_range_v =
  411. Size == 1 ? is_char_range_v<T> : is_char16_range_v<T>;
  412. template<
  413. int Size,
  414. typename T,
  415. typename U,
  416. typename Exclude,
  417. bool UIsCURange =
  418. is_cu_range_v<Size, U> && !std::is_same<U, Exclude>::value>
  419. struct cu_rng_alg_ret
  420. {
  421. };
  422. template<int Size, typename T, typename U, typename Exclude>
  423. struct cu_rng_alg_ret<Size, T, U, Exclude, true>
  424. {
  425. using type = T;
  426. };
  427. template<int Size, typename T, typename U, typename Exclude = void>
  428. using cu_rng_alg_ret_t = typename cu_rng_alg_ret<Size, T, U, Exclude>::type;
  429. template<typename T>
  430. using is_grapheme_iter_expr = std::integral_constant<
  431. bool,
  432. is_cp_iter_v<
  433. remove_cv_ref_t<decltype(std::declval<const T>().base())>>>;
  434. template<typename T>
  435. using is_grapheme_iter =
  436. detected_or_t<std::false_type, is_grapheme_iter_expr, T>;
  437. template<
  438. typename T,
  439. typename Iter,
  440. bool R1IsGraphemeIter = is_grapheme_iter<Iter>::value>
  441. struct graph_iter_alg_ret
  442. {};
  443. template<typename T, typename Iter>
  444. struct graph_iter_alg_ret<T, Iter, true>
  445. {
  446. using type = T;
  447. };
  448. template<typename T, typename Iter>
  449. using graph_iter_alg_ret_t = typename graph_iter_alg_ret<T, Iter>::type;
  450. template<
  451. typename T,
  452. typename Iter1,
  453. typename Iter2,
  454. bool Iter1Iter2AreGraphemeIter =
  455. is_grapheme_iter<Iter1>::value && is_grapheme_iter<Iter2>::value>
  456. struct graph_iters_alg_ret
  457. {};
  458. template<typename T, typename Iter1, typename Iter2>
  459. struct graph_iters_alg_ret<T, Iter1, Iter2, true>
  460. {
  461. using type = T;
  462. };
  463. template<typename T, typename Iter1, typename Iter2>
  464. using graph_iters_alg_ret_t =
  465. typename graph_iters_alg_ret<T, Iter1, Iter2>::type;
  466. template<typename Size, typename T>
  467. using is_grapheme_cu_iter_expr = std::integral_constant<
  468. bool,
  469. is_cp_iter_v<
  470. remove_cv_ref_t<decltype(std::declval<const T>().base())>> &&
  471. is_cu_iter_v<
  472. Size::value,
  473. remove_cv_ref_t<
  474. decltype(std::declval<const T>().base().base())>>>;
  475. template<int Size, typename T>
  476. using is_grapheme_cu_iter = detected_or_t<
  477. std::false_type,
  478. is_grapheme_cu_iter_expr,
  479. std::integral_constant<int, Size>,
  480. T>;
  481. template<
  482. int Size,
  483. typename T,
  484. typename R1,
  485. bool R1IsGraphemeIter = is_grapheme_cu_iter<Size, R1>::value>
  486. struct graph_iter_cu_alg_ret
  487. {};
  488. template<int Size, typename T, typename R1>
  489. struct graph_iter_cu_alg_ret<Size, T, R1, true>
  490. {
  491. using type = T;
  492. };
  493. template<int Size, typename T, typename R1>
  494. using graph_iter_alg_cu_ret_t =
  495. typename graph_iter_cu_alg_ret<Size, T, R1>::type;
  496. template<typename T>
  497. using is_grapheme_range_expr = std::integral_constant<
  498. bool,
  499. is_cp_iter_v<remove_cv_ref_t<
  500. decltype(std::declval<const T>().begin().base())>> &&
  501. is_cp_iter_v<remove_cv_ref_t<
  502. decltype(std::declval<const T>().end().base())>> &&
  503. void_<
  504. decltype(std::declval<const T>().begin().base().base()),
  505. decltype(std::declval<const T>().end().base().base())>::value>;
  506. template<typename T>
  507. using is_grapheme_range =
  508. detected_or_t<std::false_type, is_grapheme_range_expr, T>;
  509. template<
  510. typename T,
  511. typename R1,
  512. bool R1IsGraphemeRange = is_grapheme_range<R1>::value>
  513. struct graph_rng_alg_ret
  514. {};
  515. template<typename T, typename R1>
  516. struct graph_rng_alg_ret<T, R1, true>
  517. {
  518. using type = T;
  519. };
  520. template<typename T, typename R1>
  521. using graph_rng_alg_ret_t = typename graph_rng_alg_ret<T, R1>::type;
  522. template<typename T>
  523. using is_cp_grapheme_range_expr = std::integral_constant<
  524. bool,
  525. is_cp_iter_v<remove_cv_ref_t<
  526. decltype(std::declval<const T>().begin().base())>> &&
  527. is_cp_iter_v<remove_cv_ref_t<
  528. decltype(std::declval<const T>().end().base())>>>;
  529. template<typename T>
  530. using is_cp_grapheme_range =
  531. detected_or_t<std::false_type, is_cp_grapheme_range_expr, T>;
  532. template<
  533. typename T,
  534. typename R1,
  535. bool R1IsGraphemeRange = is_grapheme_range<R1>::value>
  536. struct cp_graph_rng_alg_ret
  537. {};
  538. template<typename T, typename R1>
  539. struct cp_graph_rng_alg_ret<T, R1, true>
  540. {
  541. using type = T;
  542. };
  543. template<typename T, typename R1>
  544. using cp_graph_rng_alg_ret_t = typename cp_graph_rng_alg_ret<T, R1>::type;
  545. template<
  546. typename T,
  547. typename R1,
  548. typename R2,
  549. bool R1R2AreGraphemeRanges =
  550. is_cp_grapheme_range<R1>::value && is_cp_grapheme_range<R2>::value>
  551. struct graph_rngs_alg_ret
  552. {};
  553. template<typename T, typename R1, typename R2>
  554. struct graph_rngs_alg_ret<T, R1, R2, true>
  555. {
  556. using type = T;
  557. };
  558. template<typename T, typename R1, typename R2>
  559. using graph_rngs_alg_ret_t = typename graph_rngs_alg_ret<T, R1, R2>::type;
  560. template<
  561. typename T,
  562. typename R1,
  563. typename R2,
  564. bool R1IsGraphemeRangeButNotR2 =
  565. is_cp_grapheme_range<R1>::value && !is_cp_grapheme_range<R2>::value>
  566. struct lazy_graph_rng_and_non_alg_ret
  567. {};
  568. template<typename T, typename R1, typename R2>
  569. struct lazy_graph_rng_and_non_alg_ret<T, R1, R2, true>
  570. {
  571. using type = typename T::type;
  572. };
  573. template<typename T, typename R1, typename R2>
  574. using lazy_graph_rng_and_non_alg_ret_t =
  575. typename lazy_graph_rng_and_non_alg_ret<T, R1, R2>::type;
  576. template<
  577. typename T,
  578. typename R1,
  579. typename R2,
  580. bool R1IsGraphemeRangeButNotR2 =
  581. is_cp_grapheme_range<R1>::value && !is_cp_grapheme_range<R2>::value>
  582. struct graph_rng_and_non_alg_ret
  583. {};
  584. template<typename T, typename R1, typename R2>
  585. struct graph_rng_and_non_alg_ret<T, R1, R2, true>
  586. {
  587. using type = T;
  588. };
  589. template<typename T, typename R1, typename R2>
  590. using graph_rng_and_non_alg_ret_t =
  591. typename graph_rng_and_non_alg_ret<T, R1, R2>::type;
  592. template<
  593. typename T,
  594. typename R1,
  595. typename R2,
  596. bool R1R2AreNotGraphemeRanges = !is_cp_grapheme_range<R1>::value &&
  597. !is_cp_grapheme_range<R2>::value>
  598. struct non_graph_rngs_alg_ret
  599. {};
  600. template<typename T, typename R1, typename R2>
  601. struct non_graph_rngs_alg_ret<T, R1, R2, true>
  602. {
  603. using type = T;
  604. };
  605. template<typename T, typename R1, typename R2>
  606. using non_graph_rngs_alg_ret_t =
  607. typename non_graph_rngs_alg_ret<T, R1, R2>::type;
  608. template<
  609. typename T,
  610. typename R1,
  611. typename R2,
  612. bool R1R2AreNotGraphemeRanges = !is_cp_grapheme_range<R1>::value &&
  613. !is_cp_grapheme_range<R2>::value>
  614. struct lazy_non_graph_rngs_alg_ret
  615. {};
  616. template<typename T, typename R1, typename R2>
  617. struct lazy_non_graph_rngs_alg_ret<T, R1, R2, true>
  618. {
  619. using type = typename T::type;
  620. };
  621. template<typename T, typename R1, typename R2>
  622. using lazy_non_graph_rngs_alg_ret_t =
  623. typename lazy_non_graph_rngs_alg_ret<T, R1, R2>::type;
  624. template<typename T>
  625. using is_contig_grapheme_range_expr = std::integral_constant<
  626. bool,
  627. (std::is_same<
  628. decltype(std::declval<const T>().begin().base().base()),
  629. char const *>::value ||
  630. std::is_same<
  631. decltype(std::declval<const T>().begin().base().base()),
  632. char *>::value) &&
  633. (std::is_same<
  634. decltype(std::declval<const T>().end().base().base()),
  635. char const *>::value ||
  636. std::is_same<
  637. decltype(std::declval<const T>().end().base().base()),
  638. char *>::value)>;
  639. template<typename T>
  640. using is_contig_grapheme_range =
  641. detected_or_t<std::false_type, is_contig_grapheme_range_expr, T>;
  642. template<
  643. typename T,
  644. typename R1,
  645. bool R1IsContigGraphemeRange = is_contig_grapheme_range<R1>::value>
  646. struct contig_graph_rng_alg_ret
  647. {
  648. };
  649. template<typename T, typename R1>
  650. struct contig_graph_rng_alg_ret<T, R1, true>
  651. {
  652. using type = T;
  653. };
  654. template<typename T, typename R1>
  655. using contig_graph_rng_alg_ret_t =
  656. typename contig_graph_rng_alg_ret<T, R1>::type;
  657. inline std::size_t hash_combine_(std::size_t seed, std::size_t value)
  658. {
  659. return seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
  660. }
  661. template<int N>
  662. struct hash_4_more_chars
  663. {
  664. template<typename Iter>
  665. static std::size_t call(std::size_t curr, Iter it)
  666. {
  667. return curr;
  668. }
  669. };
  670. template<>
  671. struct hash_4_more_chars<8>
  672. {
  673. template<typename Iter>
  674. static std::size_t call(std::size_t curr, Iter it)
  675. {
  676. curr <<= 32;
  677. curr += (*(it + 4) << 24) + (*(it + 5) << 16) + (*(it + 2) << 6) +
  678. (*(it + 7) << 0);
  679. return curr;
  680. }
  681. };
  682. template<typename CharRange>
  683. std::size_t hash_char_range(CharRange const & r)
  684. {
  685. auto first = r.begin();
  686. auto last = r.end();
  687. auto const size = last - first;
  688. auto const remainder = size % sizeof(std::size_t);
  689. last -= remainder;
  690. std::size_t retval = size;
  691. for (; first != last; first += sizeof(std::size_t)) {
  692. std::size_t curr = (*(first + 0) << 24) + (*(first + 1) << 16) +
  693. (*(first + 2) << 8) + (*(first + 3) << 0);
  694. curr = hash_4_more_chars<sizeof(std::size_t)>::call(curr, first);
  695. retval = detail::hash_combine_(retval, curr);
  696. }
  697. first = last;
  698. last += remainder;
  699. for (; first != last; ++first) {
  700. retval = detail::hash_combine_(retval, *first);
  701. }
  702. return retval;
  703. }
  704. template<typename GraphemeRange>
  705. std::size_t hash_grapheme_range(GraphemeRange const & r)
  706. {
  707. std::size_t cps = 0;
  708. std::size_t retval = std::accumulate(
  709. r.begin().base(),
  710. r.end().base(),
  711. std::size_t(0),
  712. [&cps](std::size_t seed, std::size_t value) {
  713. ++cps;
  714. return detail::hash_combine_(seed, value);
  715. });
  716. return detail::hash_combine_(retval, cps);
  717. }
  718. template<typename Iter>
  719. using char_value_expr = std::integral_constant<
  720. bool,
  721. std::is_integral<
  722. typename std::iterator_traits<Iter>::value_type>::value &&
  723. sizeof(typename std::iterator_traits<Iter>::value_type) == 1>;
  724. template<typename Iter>
  725. constexpr bool is_char_ptr_v = std::is_pointer<Iter>::value &&
  726. detected_or_t<std::false_type, char_value_expr, Iter>::value;
  727. template<typename Iter>
  728. using _16_value_expr = std::integral_constant<
  729. bool,
  730. std::is_integral<
  731. typename std::iterator_traits<Iter>::value_type>::value &&
  732. sizeof(typename std::iterator_traits<Iter>::value_type) == 2>;
  733. template<typename Iter>
  734. constexpr bool is_16_ptr_v = std::is_pointer<Iter>::value &&
  735. detected_or_t<std::false_type, _16_value_expr, Iter>::value;
  736. template<typename Iter>
  737. using cp_value_expr = std::integral_constant<
  738. bool,
  739. std::is_integral<
  740. typename std::iterator_traits<Iter>::value_type>::value &&
  741. sizeof(typename std::iterator_traits<Iter>::value_type) == 4>;
  742. template<typename Iter>
  743. constexpr bool is_cp_ptr_v = std::is_pointer<Iter>::value &&
  744. detected_or_t<std::false_type, cp_value_expr, Iter>::value;
  745. }}}
  746. #endif