concepts.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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_CONCEPTS_HPP
  7. #define BOOST_PARSER_DETAIL_TEXT_CONCEPTS_HPP
  8. #include <boost/parser/detail/text/config.hpp>
  9. #include <boost/parser/detail/text/utf.hpp>
  10. #include <boost/parser/detail/text/detail/begin_end.hpp>
  11. #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
  12. #include <ranges>
  13. #include <string_view>
  14. namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 {
  15. //[ concepts_concepts
  16. #ifdef _MSC_VER
  17. inline constexpr format wchar_t_format = format::utf16;
  18. #else
  19. inline constexpr format wchar_t_format = format::utf32;
  20. #endif
  21. template<typename T, format F>
  22. concept code_unit = (std::same_as<T, char8_t> && F == format::utf8) ||
  23. (std::same_as<T, char16_t> && F == format::utf16) ||
  24. (std::same_as<T, char32_t> && F == format::utf32) ||
  25. (std::same_as<T, char> && F == format::utf8) ||
  26. (std::same_as<T, wchar_t> && F == wchar_t_format);
  27. template<typename T>
  28. concept utf8_code_unit = code_unit<T, format::utf8>;
  29. template<typename T>
  30. concept utf16_code_unit = code_unit<T, format::utf16>;
  31. template<typename T>
  32. concept utf32_code_unit = code_unit<T, format::utf32>;
  33. template<typename T, format F>
  34. concept code_unit_iter =
  35. std::input_iterator<T> && code_unit<std::iter_value_t<T>, F>;
  36. template<typename T>
  37. concept utf_code_unit =
  38. utf8_code_unit<T> || utf16_code_unit<T> || utf32_code_unit<T>;
  39. template<typename T, format F>
  40. concept code_unit_range = std::ranges::input_range<T> &&
  41. code_unit<std::ranges::range_value_t<T>, F>;
  42. template<typename T, format F>
  43. concept contiguous_code_unit_range = std::ranges::contiguous_range<T> &&
  44. code_unit<std::ranges::range_value_t<T>, F>;
  45. template<typename T>
  46. concept utf8_iter = code_unit_iter<T, format::utf8>;
  47. template<typename T>
  48. concept utf8_range = code_unit_range<T, format::utf8>;
  49. template<typename T>
  50. concept contiguous_utf8_range = contiguous_code_unit_range<T, format::utf8>;
  51. template<typename T>
  52. concept utf16_iter = code_unit_iter<T, format::utf16>;
  53. template<typename T>
  54. concept utf16_range = code_unit_range<T, format::utf16>;
  55. template<typename T>
  56. concept contiguous_utf16_range =
  57. contiguous_code_unit_range<T, format::utf16>;
  58. template<typename T>
  59. concept utf32_iter = code_unit_iter<T, format::utf32>;
  60. template<typename T>
  61. concept utf32_range = code_unit_range<T, format::utf32>;
  62. template<typename T>
  63. concept contiguous_utf32_range =
  64. contiguous_code_unit_range<T, format::utf32>;
  65. template<typename T>
  66. concept code_point = utf32_code_unit<T>;
  67. template<typename T>
  68. concept code_point_iter = utf32_iter<T>;
  69. template<typename T>
  70. concept code_point_range = utf32_range<T>;
  71. template<typename T>
  72. concept utf_iter = utf8_iter<T> || utf16_iter<T> || utf32_iter<T>;
  73. template<typename T>
  74. concept utf_range = utf8_range<T> || utf16_range<T> || utf32_range<T>;
  75. template<typename T>
  76. concept grapheme_iter =
  77. std::input_iterator<T> && code_point_range<std::iter_reference_t<T>> &&
  78. requires(T t) {
  79. { t.base() } -> code_point_iter;
  80. };
  81. template<typename T>
  82. concept grapheme_range = std::ranges::input_range<T> &&
  83. grapheme_iter<std::ranges::iterator_t<T>>;
  84. template<typename R>
  85. using code_point_iterator_t = decltype(std::declval<R>().begin().base());
  86. template<typename R>
  87. using code_point_sentinel_t = decltype(std::declval<R>().end().base());
  88. template<typename T, format F>
  89. concept grapheme_iter_code_unit = grapheme_iter<T> && requires(T t) {
  90. { t.base().base() } -> code_unit_iter<F>;
  91. };
  92. template<typename T, format F>
  93. concept grapheme_range_code_unit =
  94. grapheme_range<T> &&
  95. grapheme_iter_code_unit<std::ranges::iterator_t<T>, F>;
  96. namespace dtl {
  97. template<typename T, class CodeUnit>
  98. concept eraseable_insertable_sized_bidi_range =
  99. std::ranges::sized_range<T> && std::ranges::input_range<T> &&
  100. requires(T t, CodeUnit const * it) {
  101. {
  102. t.erase(t.begin(), t.end())
  103. } -> std::same_as<std::ranges::iterator_t<T>>;
  104. {
  105. t.insert(t.end(), it, it)
  106. } -> std::same_as<std::ranges::iterator_t<T>>;
  107. };
  108. }
  109. template<typename T>
  110. concept utf8_string = utf8_code_unit<std::ranges::range_value_t<T>> &&
  111. dtl::eraseable_insertable_sized_bidi_range<
  112. T,
  113. std::ranges::range_value_t<T>>;
  114. template<typename T>
  115. concept utf16_string = utf16_code_unit<std::ranges::range_value_t<T>> &&
  116. dtl::eraseable_insertable_sized_bidi_range<
  117. T,
  118. std::ranges::range_value_t<T>>;
  119. template<typename T>
  120. concept utf_string = utf8_string<T> || utf16_string<T>;
  121. template<typename T>
  122. concept transcoding_error_handler = requires(T t, std::string_view msg) {
  123. { t(msg) } -> std::same_as<char32_t>;
  124. };
  125. //]
  126. // Clang 13 defines __cpp_lib_concepts but not std::indirectly copyable.
  127. #if defined(__clang_major__) && __clang_major__ <= 13
  128. template<typename In, typename Out>
  129. concept indirectly_copyable =
  130. std::indirectly_readable<In> &&
  131. std::indirectly_writable<Out, std::iter_reference_t<In>>;
  132. #else
  133. template<typename In, typename Out>
  134. concept indirectly_copyable = std::indirectly_copyable<In, Out>;
  135. #endif
  136. }
  137. }}
  138. #endif
  139. namespace boost::parser::detail { namespace text { namespace detail {
  140. #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
  141. template<typename T>
  142. using iterator_t = std::ranges::iterator_t<T>;
  143. template<typename T>
  144. using sentinel_t = std::ranges::sentinel_t<T>;
  145. template<typename T>
  146. using iter_value_t = std::iter_value_t<T>;
  147. template<typename T>
  148. using iter_reference_t = std::iter_reference_t<T>;
  149. template<typename T>
  150. using range_value_t = std::ranges::range_value_t<T>;
  151. template<typename T>
  152. using range_reference_t = std::ranges::range_reference_t<T>;
  153. template<typename T>
  154. using range_difference_t = std::ranges::range_difference_t<T>;
  155. #else
  156. template<typename T>
  157. using iterator_t = decltype(detail::begin(std::declval<T &>()));
  158. template<typename T>
  159. using sentinel_t = decltype(detail::end(std::declval<T &>()));
  160. template<typename T>
  161. using iter_value_t = typename std::iterator_traits<T>::value_type;
  162. template<typename T>
  163. using iter_reference_t = decltype(*std::declval<T &>());
  164. template<typename T>
  165. using range_value_t = iter_value_t<iterator_t<T>>;
  166. template<typename T>
  167. using range_reference_t = iter_reference_t<iterator_t<T>>;
  168. template<typename T>
  169. using range_difference_t = std::ptrdiff_t;
  170. template<typename T>
  171. constexpr bool code_unit_v =
  172. #if defined(__cpp_char8_t)
  173. std::is_same_v<T, char8_t> ||
  174. #endif
  175. std::is_same_v<T, char16_t> || std::is_same_v<T, char32_t> ||
  176. std::is_same_v<T, char> || std::is_same_v<T, wchar_t>;
  177. #endif
  178. }}}
  179. #endif