File indexing completed on 2025-09-17 08:40:22
0001
0002
0003
0004
0005
0006 #ifndef BOOST_PARSER_DETAIL_TEXT_TRANSCODE_VIEW_HPP
0007 #define BOOST_PARSER_DETAIL_TEXT_TRANSCODE_VIEW_HPP
0008
0009 #include <boost/parser/detail/text/transcode_algorithm.hpp>
0010 #include <boost/parser/detail/text/transcode_iterator.hpp>
0011 #include <boost/parser/detail/text/detail/all_t.hpp>
0012
0013 #include <boost/parser/detail/stl_interfaces/view_interface.hpp>
0014 #include <boost/parser/detail/stl_interfaces/view_adaptor.hpp>
0015
0016 #include <climits>
0017
0018
0019 namespace boost::parser::detail { namespace text {
0020
0021 namespace detail {
0022 template<class I>
0023 constexpr auto iterator_to_tag()
0024 {
0025 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0026 if constexpr (std::random_access_iterator<I>) {
0027 return std::random_access_iterator_tag{};
0028 } else if constexpr (std::bidirectional_iterator<I>) {
0029 return std::bidirectional_iterator_tag{};
0030 } else if constexpr (std::forward_iterator<I>) {
0031 #else
0032 if constexpr (detail::random_access_iterator_v<I>) {
0033 return std::random_access_iterator_tag{};
0034 } else if constexpr (detail::bidirectional_iterator_v<I>) {
0035 return std::bidirectional_iterator_tag{};
0036 } else if constexpr (detail::forward_iterator_v<I>) {
0037 #endif
0038 return std::forward_iterator_tag{};
0039 } else {
0040 return std::input_iterator_tag{};
0041 }
0042 }
0043 template<class I>
0044 using iterator_to_tag_t = decltype(iterator_to_tag<I>());
0045
0046 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0047 template<class T>
0048 using with_reference = T &;
0049 template<typename T>
0050 concept can_reference = requires { typename with_reference<T>; };
0051 #endif
0052
0053 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0054 template<class Char>
0055 struct cast_to_charn {
0056 constexpr Char operator()(Char c) const { return c; }
0057 };
0058 #else
0059 struct cast_to_char8;
0060 struct cast_to_char16;
0061 struct cast_to_char32;
0062 template<typename Tag, typename Arg>
0063 auto function_for_tag(Arg arg)
0064 {
0065 #if defined(__cpp_char8_t)
0066 if constexpr (std::is_same_v<Tag, cast_to_char8>) {
0067 return (char8_t)arg;
0068 } else
0069 #endif
0070 if constexpr (std::is_same_v<Tag, cast_to_char16>) {
0071 return (char16_t)arg;
0072 } else if constexpr (std::is_same_v<Tag, cast_to_char32>) {
0073 return (char32_t)arg;
0074 }
0075 }
0076 #endif
0077 }
0078
0079 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0080 template<std::ranges::input_range V, auto F>
0081 requires std::ranges::view<V> &&
0082 std::regular_invocable<decltype(F)&, std::ranges::range_reference_t<V>> &&
0083 detail::can_reference<std::invoke_result_t<decltype(F)&, std::ranges::range_reference_t<V>>>
0084 #else
0085 template<typename V, typename F>
0086 #endif
0087 class project_view : public stl_interfaces::view_interface<project_view<V, F>>
0088 {
0089 V base_ = V();
0090
0091 template<bool Const>
0092 class iterator;
0093 template<bool Const>
0094 class sentinel;
0095
0096 public:
0097 constexpr project_view()
0098 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0099 requires std::default_initializable<V>
0100 #endif
0101 = default;
0102 constexpr explicit project_view(V base) : base_(std::move(base)) {}
0103
0104 constexpr V& base() & { return base_; }
0105 constexpr const V& base() const& { return base_; }
0106 constexpr V base() && { return std::move(base_); }
0107
0108 constexpr iterator<false> begin() { return iterator<false>{detail::begin(base_)}; }
0109 constexpr iterator<true> begin() const
0110 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0111 requires std::ranges::range<const V>
0112 #endif
0113 { return iterator<true>{detail::begin(base_)}; }
0114
0115 constexpr sentinel<false> end() { return sentinel<false>{detail::end(base_)}; }
0116 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0117 constexpr iterator<false> end() requires std::ranges::common_range<V>
0118 { return iterator<false>{detail::end(base_)}; }
0119 #endif
0120 constexpr sentinel<true> end() const
0121 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0122 requires std::ranges::range<const V>
0123 { return sentinel<true>{detail::end(base_)}; }
0124 constexpr iterator<true> end() const
0125 requires std::ranges::common_range<const V>
0126 #endif
0127 { return iterator<true>{detail::end(base_)}; }
0128
0129 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0130 constexpr auto size() requires std::ranges::sized_range<V> { return std::ranges::size(base_); }
0131 constexpr auto size() const requires std::ranges::sized_range<const V> { return std::ranges::size(base_); }
0132 #endif
0133 };
0134
0135 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0136 template<std::ranges::input_range V, auto F>
0137 requires std::ranges::view<V> &&
0138 std::regular_invocable<decltype(F)&, std::ranges::range_reference_t<V>> &&
0139 detail::can_reference<std::invoke_result_t<decltype(F)&, std::ranges::range_reference_t<V>>>
0140 #else
0141 template<typename V, typename F>
0142 #endif
0143 template<bool Const>
0144 class project_view<V, F>::iterator
0145 : public boost::parser::detail::stl_interfaces::proxy_iterator_interface<
0146 iterator<Const>,
0147 detail::iterator_to_tag_t<detail::iterator_t<detail::maybe_const<Const, V>>>,
0148 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0149 std::invoke_result_t<decltype(F)&, detail::range_reference_t<V>>
0150 #else
0151 decltype(detail::function_for_tag<F>(0))
0152 #endif
0153 >
0154 {
0155 using iterator_type = detail::iterator_t<detail::maybe_const<Const, V>>;
0156 using sentinel_type = detail::sentinel_t<detail::maybe_const<Const, V>>;
0157 using reference_type =
0158 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0159 std::invoke_result_t<decltype(F) &, detail::range_reference_t<V>>
0160 #else
0161 decltype(detail::function_for_tag<F>(0))
0162 #endif
0163 ;
0164 using sentinel = project_view<V, F>::sentinel<Const>;
0165
0166 friend boost::parser::detail::stl_interfaces::access;
0167 iterator_type & base_reference() noexcept { return it_; }
0168 iterator_type base_reference() const { return it_; }
0169
0170 iterator_type it_ = iterator_type();
0171
0172 friend project_view<V, F>::sentinel<Const>;
0173
0174 template<bool OtherConst>
0175 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0176 requires std::sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
0177 #endif
0178 friend constexpr bool operator==(const iterator<OtherConst> & x,
0179 const sentinel & y)
0180 { return x.it_ == y.end_; }
0181
0182 template<bool OtherConst>
0183 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0184 requires std::sized_sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
0185 #endif
0186 friend constexpr detail::range_difference_t<detail::maybe_const<OtherConst, V>>
0187 operator-(const iterator<OtherConst> & x, const sentinel & y)
0188 { return x.it_ - y.end_; }
0189
0190 template<bool OtherConst>
0191 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0192 requires std::sized_sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
0193 #endif
0194 friend constexpr detail::range_difference_t<detail::maybe_const<OtherConst, V>>
0195 operator-(const sentinel & y, const iterator<OtherConst> & x)
0196 { return y.end_ - x.it_; }
0197
0198 public:
0199 constexpr iterator() = default;
0200 constexpr iterator(iterator_type it) : it_(std::move(it)) {}
0201
0202 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0203 constexpr reference_type operator*() const { return F(*it_); }
0204 #else
0205 constexpr reference_type operator*() const
0206 {
0207 return detail::function_for_tag<F>(*it_);
0208 }
0209 #endif
0210 };
0211
0212 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0213 template<std::ranges::input_range V, auto F>
0214 requires std::ranges::view<V> &&
0215 std::regular_invocable<decltype(F)&, std::ranges::range_reference_t<V>> &&
0216 detail::can_reference<std::invoke_result_t<decltype(F)&, std::ranges::range_reference_t<V>>>
0217 #else
0218 template<typename V, typename F>
0219 #endif
0220 template<bool Const>
0221 class project_view<V, F>::sentinel
0222 {
0223 using Base = detail::maybe_const<Const, V>;
0224 using sentinel_type = detail::sentinel_t<Base>;
0225
0226 sentinel_type end_ = sentinel_type();
0227
0228 public:
0229 constexpr sentinel() = default;
0230 constexpr explicit sentinel(sentinel_type end) : end_(std::move(end)) {}
0231 #if !BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0232 template<bool Enable = Const, class = std::enable_if_t<Enable>>
0233 #endif
0234 constexpr sentinel(sentinel<!Const> i)
0235 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0236 requires Const &&
0237 std::convertible_to<detail::sentinel_t<V>, detail::sentinel_t<Base>>
0238 #endif
0239 : end_(std::move(i.end_))
0240 {}
0241
0242 constexpr sentinel_type base() const { return end_; }
0243
0244 template<bool OtherConst>
0245 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0246 requires std::sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
0247 #endif
0248 friend constexpr bool operator==(const iterator<OtherConst> & x,
0249 const sentinel & y)
0250 { return x.it_ == y.end_; }
0251
0252 template<bool OtherConst>
0253 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0254 requires std::sized_sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
0255 #endif
0256 friend constexpr detail::range_difference_t<detail::maybe_const<OtherConst, V>>
0257 operator-(const iterator<OtherConst> & x, const sentinel & y)
0258 { return x.it_ - y.end_; }
0259
0260 template<bool OtherConst>
0261 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0262 requires std::sized_sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
0263 #endif
0264 friend constexpr detail::range_difference_t<detail::maybe_const<OtherConst, V>>
0265 operator-(const sentinel & y, const iterator<OtherConst> & x)
0266 { return y.end_ - x.it_; }
0267 };
0268
0269 namespace detail {
0270 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0271 template<auto F>
0272 #else
0273 template<typename F>
0274 #endif
0275 struct project_impl : stl_interfaces::range_adaptor_closure<project_impl<F>>
0276 {
0277 template<class R>
0278 using project_view_type = project_view<R, F>;
0279
0280 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0281 template<class R>
0282 requires std::ranges::viewable_range<R> &&
0283 std::ranges::input_range<R> &&
0284 std::regular_invocable<decltype(F)&, std::ranges::range_reference_t<R>> &&
0285 detail::can_reference<std::invoke_result_t<decltype(F)&, std::ranges::range_reference_t<R>>>
0286 #else
0287 template<class R>
0288 #endif
0289 [[nodiscard]] constexpr auto operator()(R && r) const
0290 {
0291 return project_view_type<R>(std::forward<R>(r));
0292 }
0293 };
0294 }
0295
0296 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0297 template<auto F>
0298 #else
0299 template<typename F>
0300 #endif
0301 constexpr detail::project_impl<F> project{};
0302
0303 #if defined(__cpp_char8_t)
0304 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0305 template<std::ranges::input_range V>
0306 requires std::ranges::view<V> && std::convertible_to<std::ranges::range_reference_t<V>, char8_t>
0307 class char8_view : public project_view<V, detail::cast_to_charn<char8_type>{}>
0308 #else
0309 template<typename V>
0310 class char8_view : public project_view<V, detail::cast_to_char8>
0311 #endif
0312 {
0313 public:
0314 constexpr char8_view()
0315 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0316 requires std::default_initializable<V>
0317 #endif
0318 = default;
0319 constexpr char8_view(V base) :
0320 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0321 project_view<V, detail::cast_to_charn<char8_t>{}>{std::move(base)}
0322 #else
0323 project_view<V, detail::cast_to_char8>{std::move(base)}
0324 #endif
0325 {}
0326 };
0327 #endif
0328 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0329 template<std::ranges::input_range V>
0330 requires std::ranges::view<V> && std::convertible_to<std::ranges::range_reference_t<V>, char16_t>
0331 class char16_view : public project_view<V, detail::cast_to_charn<char16_t>{}>
0332 #else
0333 template<typename V>
0334 class char16_view : public project_view<V, detail::cast_to_char16>
0335 #endif
0336 {
0337 public:
0338 constexpr char16_view()
0339 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0340 requires std::default_initializable<V>
0341 #endif
0342 = default;
0343 constexpr char16_view(V base) :
0344 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0345 project_view<V, detail::cast_to_charn<char16_t>{}>{std::move(base)}
0346 #else
0347 project_view<V, detail::cast_to_char16>{std::move(base)}
0348 #endif
0349 {}
0350 };
0351 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0352 template<std::ranges::input_range V>
0353 requires std::ranges::view<V> && std::convertible_to<std::ranges::range_reference_t<V>, char32_t>
0354 class char32_view : public project_view<V, detail::cast_to_charn<char32_t>{}>
0355 #else
0356 template<typename V>
0357 class char32_view : public project_view<V, detail::cast_to_char32>
0358 #endif
0359 {
0360 public:
0361 constexpr char32_view()
0362 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0363 requires std::default_initializable<V>
0364 #endif
0365 = default;
0366 constexpr char32_view(V base) :
0367 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0368 project_view<V, detail::cast_to_charn<char32_t>{}>{std::move(base)}
0369 #else
0370 project_view<V, detail::cast_to_char32>{std::move(base)}
0371 #endif
0372 {}
0373 };
0374
0375 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0376 template<class R>
0377 char8_view(R &&) -> char8_view<detail::all_t<R>>;
0378 template<class R>
0379 char16_view(R &&) -> char16_view<detail::all_t<R>>;
0380 template<class R>
0381 char32_view(R &&) -> char32_view<detail::all_t<R>>;
0382 #endif
0383
0384 namespace detail {
0385 template<template<class> class View, format Format>
0386 struct as_charn_impl : stl_interfaces::range_adaptor_closure<as_charn_impl<View, Format>>
0387 {
0388 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0389 template<class R>
0390 requires (std::ranges::viewable_range<R> &&
0391 std::ranges::input_range<R> &&
0392 std::convertible_to<std::ranges::range_reference_t<R>, format_to_type_t<Format>>)
0393 #else
0394 template<class R>
0395 #endif
0396 [[nodiscard]] constexpr auto operator()(R && r) const
0397 {
0398 using T = remove_cv_ref_t<R>;
0399 if constexpr (detail::is_empty_view<T>) {
0400 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0401 return std::ranges::empty_view<format_to_type_t<Format>>{};
0402 #else
0403 return 42;
0404 #endif
0405 } else {
0406 return View(std::forward<R>(r));
0407 }
0408 }
0409 };
0410
0411 template<class T>
0412 constexpr bool is_charn_view = false;
0413 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0414 template<class V>
0415 constexpr bool is_charn_view<char8_view<V>> = true;
0416 #endif
0417 template<class V>
0418 constexpr bool is_charn_view<char16_view<V>> = true;
0419 template<class V>
0420 constexpr bool is_charn_view<char32_view<V>> = true;
0421 }
0422
0423 #if defined(__cpp_char8_t)
0424 inline constexpr detail::as_charn_impl<char8_view, format::utf8> as_char8_t;
0425 #endif
0426 inline constexpr detail::as_charn_impl<char16_view, format::utf16>
0427 as_char16_t;
0428 inline constexpr detail::as_charn_impl<char32_view, format::utf32>
0429 as_char32_t;
0430
0431 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0432 template<utf_range V>
0433 requires std::ranges::view<V> && std::ranges::forward_range<V>
0434 #else
0435 template<typename V>
0436 #endif
0437 class unpacking_view
0438 : public stl_interfaces::view_interface<unpacking_view<V>>
0439 {
0440 V base_ = V();
0441
0442 public:
0443 constexpr unpacking_view()
0444 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0445 requires std::default_initializable<V>
0446 #endif
0447 = default;
0448 constexpr unpacking_view(V base) : base_(std::move(base)) {}
0449
0450 constexpr V base() const &
0451 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0452 requires std::copy_constructible<V>
0453 #endif
0454 {
0455 return base_;
0456 }
0457 constexpr V base() && { return std::move(base_); }
0458
0459 constexpr auto code_units() const noexcept
0460 {
0461 auto unpacked =
0462 boost::parser::detail::text::unpack_iterator_and_sentinel(
0463 detail::begin(base_), detail::end(base_));
0464 return BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
0465 unpacked.first, unpacked.last);
0466 }
0467
0468 constexpr auto begin() { return code_units().begin(); }
0469 constexpr auto begin() const { return code_units().begin(); }
0470
0471 constexpr auto end() { return code_units().end(); }
0472 constexpr auto end() const { return code_units().end(); }
0473 };
0474
0475 template<class R>
0476 unpacking_view(R &&) -> unpacking_view<detail::all_t<R>>;
0477
0478 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0479 template<format Format, utf_range V>
0480 requires std::ranges::view<V>
0481 #else
0482 template<format Format, typename V>
0483 #endif
0484 class utf_view : public stl_interfaces::view_interface<utf_view<Format, V>>
0485 {
0486 V base_ = V();
0487
0488 template<format FromFormat, class I, class S>
0489 static constexpr auto make_begin(I first, S last)
0490 {
0491 if constexpr (detail::bidirectional_iterator_v<I>) {
0492 return utf_iterator<FromFormat, Format, I, S>{first, first, last};
0493 } else {
0494 return utf_iterator<FromFormat, Format, I, S>{first, last};
0495 }
0496 }
0497 template<format FromFormat, class I, class S>
0498 static constexpr auto make_end(I first, S last)
0499 {
0500 if constexpr (!std::is_same_v<I, S>) {
0501 return last;
0502 } else if constexpr (detail::bidirectional_iterator_v<I>) {
0503 return utf_iterator<FromFormat, Format, I, S>{first, last, last};
0504 } else {
0505 return utf_iterator<FromFormat, Format, I, S>{last, last};
0506 }
0507 }
0508
0509 public:
0510 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0511 constexpr utf_view() requires std::default_initializable<V> = default;
0512 #endif
0513 constexpr utf_view(V base) : base_{std::move(base)} {}
0514
0515 constexpr V base() const &
0516 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0517 requires std::copy_constructible<V>
0518 #endif
0519 { return base_; }
0520 constexpr V base() && { return std::move(base_); }
0521
0522 constexpr auto begin()
0523 {
0524 constexpr format from_format = detail::format_of<detail::range_value_t<V>>();
0525 if constexpr(detail::is_charn_view<V>) {
0526 return make_begin<from_format>(detail::begin(base_.base()), detail::end(base_.base()));
0527 } else {
0528 return make_begin<from_format>(detail::begin(base_), detail::end(base_));
0529 }
0530 }
0531 constexpr auto begin() const
0532 {
0533 constexpr format from_format = detail::format_of<detail::range_value_t<const V>>();
0534 if constexpr(detail::is_charn_view<V>) {
0535 return make_begin<from_format>(detail::begin(base_.base()), detail::end(base_.base()));
0536 } else {
0537 return make_begin<from_format>(detail::begin(base_), detail::end(base_));
0538 }
0539 }
0540
0541 constexpr auto end()
0542 {
0543 constexpr format from_format = detail::format_of<detail::range_value_t<V>>();
0544 if constexpr(detail::is_charn_view<V>) {
0545 return make_end<from_format>(detail::begin(base_.base()), detail::end(base_.base()));
0546 } else {
0547 return make_end<from_format>(detail::begin(base_), detail::end(base_));
0548 }
0549 }
0550 constexpr auto end() const
0551 {
0552 constexpr format from_format = detail::format_of<detail::range_value_t<const V>>();
0553 if constexpr(detail::is_charn_view<V>) {
0554 return make_end<from_format>(detail::begin(base_.base()), detail::end(base_.base()));
0555 } else {
0556 return make_end<from_format>(detail::begin(base_), detail::end(base_));
0557 }
0558 }
0559
0560
0561
0562 friend std::ostream & operator<<(std::ostream & os, utf_view v)
0563 {
0564 if constexpr (Format == format::utf8) {
0565 auto out = std::ostreambuf_iterator<char>(os);
0566 for (auto it = v.begin(); it != v.end(); ++it, ++out) {
0567 *out = *it;
0568 }
0569 } else {
0570 boost::parser::detail::text::transcode_to_utf8(
0571 v.begin(), v.end(), std::ostreambuf_iterator<char>(os));
0572 }
0573 return os;
0574 }
0575 #if defined(BOOST_TEXT_DOXYGEN) || defined(_MSC_VER)
0576
0577
0578 friend std::wostream & operator<<(std::wostream & os, utf_view v)
0579 {
0580 if constexpr (Format == format::utf16) {
0581 auto out = std::ostreambuf_iterator<wchar_t>(os);
0582 for (auto it = v.begin(); it != v.end(); ++it, ++out) {
0583 *out = *it;
0584 }
0585 } else {
0586 boost::parser::detail::text::transcode_to_utf16(
0587 v.begin(), v.end(), std::ostreambuf_iterator<wchar_t>(os));
0588 }
0589 return os;
0590 }
0591 #endif
0592 };
0593
0594
0595 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0596 template<utf_range V>
0597 requires std::ranges::view<V>
0598 #else
0599 template<typename V>
0600 #endif
0601 class utf8_view : public utf_view<format::utf8, V>
0602 {
0603 public:
0604 constexpr utf8_view()
0605 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0606 requires std::default_initializable<V>
0607 #endif
0608 = default;
0609 constexpr utf8_view(V base) :
0610 utf_view<format::utf8, V>{std::move(base)}
0611 {}
0612 };
0613 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0614 template<utf_range V>
0615 requires std::ranges::view<V>
0616 #else
0617 template<typename V>
0618 #endif
0619 class utf16_view : public utf_view<format::utf16, V>
0620 {
0621 public:
0622 constexpr utf16_view()
0623 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0624 requires std::default_initializable<V>
0625 #endif
0626 = default;
0627 constexpr utf16_view(V base) :
0628 utf_view<format::utf16, V>{std::move(base)}
0629 {}
0630 };
0631 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0632 template<utf_range V>
0633 requires std::ranges::view<V>
0634 #else
0635 template<typename V>
0636 #endif
0637 class utf32_view : public utf_view<format::utf32, V>
0638 {
0639 public:
0640 constexpr utf32_view()
0641 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0642 requires std::default_initializable<V>
0643 #endif
0644 = default;
0645 constexpr utf32_view(V base) :
0646 utf_view<format::utf32, V>{std::move(base)}
0647 {}
0648 };
0649
0650 template<class R>
0651 utf8_view(R &&) -> utf8_view<detail::all_t<R>>;
0652 template<class R>
0653 utf16_view(R &&) -> utf16_view<detail::all_t<R>>;
0654 template<class R>
0655 utf32_view(R &&) -> utf32_view<detail::all_t<R>>;
0656
0657 #if defined(BOOST_TEXT_DOXYGEN)
0658
0659
0660 constexpr detail::unspecified as_utf8;
0661
0662
0663 constexpr detail::unspecified as_utf16;
0664
0665
0666 constexpr detail::unspecified as_utf32;
0667
0668 #endif
0669
0670 namespace detail {
0671 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0672 template<class R, template<class> class View>
0673 concept can_utf_view = requires(R && r) { View((R &&)r); };
0674 #else
0675 template<class R, class View>
0676 using can_utf_view_expr = decltype(View(std::declval<R>()));
0677 template<class R, template<class> class View>
0678 constexpr bool can_utf_view =
0679 is_detected_v<can_utf_view_expr, R, View<R>>;
0680 #endif
0681
0682 template<class T>
0683 constexpr bool is_utf_view = false;
0684 template<class T>
0685 constexpr bool is_utf_view<utf8_view<T>> = true;
0686 template<class T>
0687 constexpr bool is_utf_view<utf16_view<T>> = true;
0688 template<class T>
0689 constexpr bool is_utf_view<utf32_view<T>> = true;
0690 template<format F, class T>
0691 constexpr bool is_utf_view<utf_view<F, T>> = true;
0692
0693 template<typename T>
0694 constexpr bool is_bounded_array_v = false;
0695 template<typename T, int N>
0696 constexpr bool is_bounded_array_v<T[N]> = true;
0697
0698 template<class R>
0699 constexpr decltype(auto) unpack_range(R && r)
0700 {
0701 using T = detail::remove_cv_ref_t<R>;
0702 if constexpr (forward_range_v<T>) {
0703 auto unpacked =
0704 boost::parser::detail::text::unpack_iterator_and_sentinel(detail::begin(r), detail::end(r));
0705 if constexpr (is_bounded_array_v<T>) {
0706 constexpr auto n = std::extent_v<T>;
0707 if (n && !r[n - 1])
0708 --unpacked.last;
0709 return BOOST_PARSER_DETAIL_TEXT_SUBRANGE(unpacked.first, unpacked.last);
0710 } else if constexpr (
0711 !std::is_same_v<decltype(unpacked.first), iterator_t<R>> ||
0712 !std::is_same_v<decltype(unpacked.last), sentinel_t<R>>) {
0713 return unpacking_view(std::forward<R>(r));
0714 } else {
0715 return std::forward<R>(r);
0716 }
0717 } else {
0718 return std::forward<R>(r);
0719 }
0720 }
0721
0722 template<class R>
0723 using unpacked_range = decltype(detail::unpack_range(std::declval<R>()));
0724
0725 template<template<class> class View, format Format>
0726 struct as_utf_impl : stl_interfaces::range_adaptor_closure<as_utf_impl<View, Format>>
0727 {
0728 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0729 template<class R>
0730 requires is_utf_view<std::remove_cvref_t<R>> ||
0731 (std::ranges::viewable_range<R> &&
0732 can_utf_view<unpacked_range<R>, View>)
0733 #else
0734 template<typename R>
0735 #endif
0736 [[nodiscard]] constexpr auto operator()(R && r) const
0737 {
0738 using T = detail::remove_cv_ref_t<R>;
0739 if constexpr (detail::is_empty_view<T>) {
0740 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0741 return std::ranges::empty_view<format_to_type_t<Format>>{};
0742 #else
0743 return 42;
0744 #endif
0745 } else if constexpr (is_utf_view<T>) {
0746 return View(std::forward<R>(r).base());
0747 } else if constexpr (detail::is_charn_view<T>) {
0748 return View(std::forward<R>(r));
0749 } else {
0750 return View(detail::unpack_range(std::forward<R>(r)));
0751 }
0752 }
0753 };
0754
0755 template<class T>
0756 constexpr bool is_utf32_view = false;
0757 template<class V>
0758 constexpr bool is_utf32_view<utf_view<format::utf32, V>> = true;
0759 }
0760
0761 inline constexpr detail::as_utf_impl<utf8_view, format::utf8> as_utf8;
0762 inline constexpr detail::as_utf_impl<utf16_view, format::utf16> as_utf16;
0763 inline constexpr detail::as_utf_impl<utf32_view, format::utf32> as_utf32;
0764
0765 }}
0766
0767 #if BOOST_PARSER_USE_CONCEPTS && defined(__cpp_lib_ranges)
0768
0769 namespace std::ranges {
0770 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0771 template<class V, auto F>
0772 inline constexpr bool enable_borrowed_range<boost::parser::detail::text::project_view<V, F>> =
0773 enable_borrowed_range<V>;
0774 #endif
0775
0776 template<class V>
0777 inline constexpr bool enable_borrowed_range<boost::parser::detail::text::unpacking_view<V>> =
0778 enable_borrowed_range<V>;
0779
0780 template<boost::parser::detail::text::format Format, class V>
0781 inline constexpr bool enable_borrowed_range<boost::parser::detail::text::utf_view<Format, V>> =
0782 enable_borrowed_range<V>;
0783
0784 template<class V>
0785 inline constexpr bool enable_borrowed_range<boost::parser::detail::text::utf8_view<V>> =
0786 enable_borrowed_range<V>;
0787 template<class V>
0788 inline constexpr bool enable_borrowed_range<boost::parser::detail::text::utf16_view<V>> =
0789 enable_borrowed_range<V>;
0790 template<class V>
0791 inline constexpr bool enable_borrowed_range<boost::parser::detail::text::utf32_view<V>> =
0792 enable_borrowed_range<V>;
0793 }
0794
0795 #endif
0796
0797 #endif