Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:53:51

0001 // Copyright (C) 2018 Robert N. Steagall
0002 // Copyright (C) 2019 T. Zachary Laine
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See
0005 // accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 #ifndef BOOST_PARSER_DETAIL_TEXT_TRANSCODE_ALGORITHM_HPP
0008 #define BOOST_PARSER_DETAIL_TEXT_TRANSCODE_ALGORITHM_HPP
0009 
0010 #include <boost/parser/detail/text/in_out_result.hpp>
0011 #include <boost/parser/detail/text/transcode_iterator.hpp>
0012 #include <boost/parser/detail/text/unpack.hpp>
0013 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0014 #include <algorithm>
0015 #endif
0016 
0017 #include <boost/parser/config.hpp>
0018 
0019 
0020 namespace boost::parser::detail { namespace text {
0021 
0022     /** An alias for `in_out_result` returned by algorithms that perform a
0023         transcoding copy. */
0024     template<typename Iter, typename OutIter>
0025     using transcode_result = in_out_result<Iter, OutIter>;
0026 
0027     namespace detail {
0028         template<typename OutIter>
0029         constexpr OutIter read_into_utf8_iter(uint32_t cp, OutIter out)
0030         {
0031             if (cp < 0x80) {
0032                 *out = static_cast<char>(cp);
0033                 ++out;
0034             } else if (cp < 0x800) {
0035                 *out = static_cast<char>(0xC0 + (cp >> 6));
0036                 ++out;
0037                 *out = static_cast<char>(0x80 + (cp & 0x3f));
0038                 ++out;
0039             } else if (cp < 0x10000) {
0040                 *out = static_cast<char>(0xe0 + (cp >> 12));
0041                 ++out;
0042                 *out = static_cast<char>(0x80 + ((cp >> 6) & 0x3f));
0043                 ++out;
0044                 *out = static_cast<char>(0x80 + (cp & 0x3f));
0045                 ++out;
0046             } else {
0047                 *out = static_cast<char>(0xf0 + (cp >> 18));
0048                 ++out;
0049                 *out = static_cast<char>(0x80 + ((cp >> 12) & 0x3f));
0050                 ++out;
0051                 *out = static_cast<char>(0x80 + ((cp >> 6) & 0x3f));
0052                 ++out;
0053                 *out = static_cast<char>(0x80 + (cp & 0x3f));
0054                 ++out;
0055             }
0056             return out;
0057         }
0058 
0059         template<typename OutIter>
0060         constexpr OutIter read_into_utf16_iter(uint32_t cp, OutIter out)
0061         {
0062             uint16_t const high_surrogate_base = 0xd7c0;
0063             uint16_t const low_surrogate_base = 0xdc00;
0064 
0065             if (cp < 0x10000) {
0066                 *out = static_cast<uint16_t>(cp);
0067                 ++out;
0068             } else {
0069                 *out = static_cast<uint16_t>(cp >> 10) + high_surrogate_base;
0070                 ++out;
0071                 *out = static_cast<uint16_t>(cp & 0x3ff) + low_surrogate_base;
0072                 ++out;
0073             }
0074             return out;
0075         }
0076 
0077         template<
0078             bool UseN,
0079             typename InputIter,
0080             typename Sentinel,
0081             typename OutIter>
0082         transcode_result<InputIter, OutIter> transcode_utf_8_to_16(
0083             InputIter first,
0084             Sentinel last,
0085             std::ptrdiff_t n,
0086             OutIter out,
0087             std::input_iterator_tag)
0088         {
0089             for (; first != last && (!UseN || n); --n) {
0090                 unsigned char const c = *first;
0091                 if (c < 0x80) {
0092                     *out = *first;
0093                     ++first;
0094                     ++out;
0095                 } else {
0096                     auto const cp = detail::advance(first, last);
0097                     out = detail::read_into_utf16_iter(cp, out);
0098                 }
0099             }
0100             return {first, out};
0101         }
0102 
0103         template<bool UseN, typename Iter, typename OutIter>
0104         transcode_result<Iter, OutIter> transcode_utf_8_to_16(
0105             Iter first,
0106             Iter last,
0107             std::ptrdiff_t n,
0108             OutIter out,
0109             std::random_access_iterator_tag)
0110         {
0111             return transcode_utf_8_to_16<UseN>(
0112                 first, last, n, out, std::input_iterator_tag{});
0113         }
0114 
0115         template<
0116             bool UseN,
0117             typename InputIter,
0118             typename Sentinel,
0119             typename OutIter>
0120         transcode_result<InputIter, OutIter> transcode_utf_8_to_32(
0121             InputIter first,
0122             Sentinel last,
0123             std::ptrdiff_t n,
0124             OutIter out,
0125             std::input_iterator_tag)
0126         {
0127             for (; first != last && (!UseN || n); --n) {
0128                 unsigned char const c = *first;
0129                 if (c < 0x80) {
0130                     *out = *first;
0131                     ++first;
0132                     ++out;
0133                 } else {
0134                     *out = detail::advance(first, last);
0135                     ++out;
0136                 }
0137             }
0138             return {first, out};
0139         }
0140 
0141         template<bool UseN, typename Iter, typename OutIter>
0142         transcode_result<Iter, OutIter> transcode_utf_8_to_32(
0143             Iter first,
0144             Iter last,
0145             std::ptrdiff_t n,
0146             OutIter out,
0147             std::random_access_iterator_tag)
0148         {
0149             return transcode_utf_8_to_32<UseN>(
0150                 first, last, n, out, std::input_iterator_tag{});
0151         }
0152 
0153         template<format Tag>
0154         struct tag_t
0155         {};
0156 
0157         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0158         transcode_result<Iter, OutIter> transcode_to_8(
0159             tag_t<format::utf8>,
0160             Iter first,
0161             Sentinel last,
0162             std::ptrdiff_t n,
0163             OutIter out)
0164         {
0165             for (; first != last && (!UseN || n); ++first, ++out) {
0166                 *out = *first;
0167                 --n;
0168             }
0169             return {first, out};
0170         }
0171 
0172         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0173         transcode_result<Iter, OutIter> transcode_to_16(
0174             tag_t<format::utf8>,
0175             Iter first,
0176             Sentinel last,
0177             std::ptrdiff_t n,
0178             OutIter out)
0179         {
0180             return detail::transcode_utf_8_to_16<UseN>(
0181                 first,
0182                 last,
0183                 n,
0184                 out,
0185                 typename std::iterator_traits<Iter>::iterator_category{});
0186         }
0187 
0188         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0189         transcode_result<Iter, OutIter> transcode_to_32(
0190             tag_t<format::utf8>,
0191             Iter first,
0192             Sentinel last,
0193             std::ptrdiff_t n,
0194             OutIter out)
0195         {
0196             return detail::transcode_utf_8_to_32<UseN>(
0197                 first,
0198                 last,
0199                 n,
0200                 out,
0201                 typename std::iterator_traits<Iter>::iterator_category{});
0202         }
0203 
0204         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0205         transcode_result<Iter, OutIter> transcode_to_8(
0206             tag_t<format::utf16>,
0207             Iter first,
0208             Sentinel last,
0209             std::ptrdiff_t n,
0210             OutIter out)
0211         {
0212             uint32_t const high_surrogate_max = 0xdbff;
0213             uint16_t const high_surrogate_base = 0xd7c0;
0214             uint16_t const low_surrogate_base = 0xdc00;
0215 
0216             for (; first != last && (!UseN || n); ++first, --n) {
0217                 uint32_t const hi = *first;
0218                 if (surrogate(hi)) {
0219                     if (hi <= high_surrogate_max) {
0220                         ++first;
0221                         if (first == last) {
0222                             uint32_t const cp = replacement_character;
0223                             out = detail::read_into_utf8_iter(cp, out);
0224                             ++out;
0225                             return {first, out};
0226                         }
0227                         uint32_t const lo = *first;
0228                         if (low_surrogate(lo)) {
0229                             uint32_t const cp =
0230                                 ((hi - high_surrogate_base) << 10) +
0231                                 (lo - low_surrogate_base);
0232                             out = detail::read_into_utf8_iter(cp, out);
0233                             continue;
0234                         }
0235                     }
0236                     out = detail::read_into_utf8_iter(
0237                         replacement_character, out);
0238                 } else {
0239                     out = detail::read_into_utf8_iter(hi, out);
0240                 }
0241             }
0242 
0243             return {first, out};
0244         }
0245 
0246         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0247         transcode_result<Iter, OutIter> transcode_to_16(
0248             tag_t<format::utf16>,
0249             Iter first,
0250             Sentinel last,
0251             std::ptrdiff_t n,
0252             OutIter out)
0253         {
0254             for (; first != last && (!UseN || n); ++first, ++out, --n) {
0255                 *out = *first;
0256             }
0257             return {first, out};
0258         }
0259 
0260         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0261         transcode_result<Iter, OutIter> transcode_to_32(
0262             tag_t<format::utf16>,
0263             Iter first,
0264             Sentinel last,
0265             std::ptrdiff_t n,
0266             OutIter out)
0267         {
0268             uint32_t const high_surrogate_max = 0xdbff;
0269             uint16_t const high_surrogate_base = 0xd7c0;
0270             uint16_t const low_surrogate_base = 0xdc00;
0271 
0272             for (; first != last && (!UseN || n); ++first, --n) {
0273                 uint32_t const hi = *first;
0274                 if (surrogate(hi)) {
0275                     if (hi <= high_surrogate_max) {
0276                         ++first;
0277                         if (first == last) {
0278                             *out = replacement_character;
0279                             ++out;
0280                             return {first, out};
0281                         }
0282                         uint32_t const lo = *first;
0283                         if (low_surrogate(lo)) {
0284                             uint32_t const cp =
0285                                 ((hi - high_surrogate_base) << 10) +
0286                                 (lo - low_surrogate_base);
0287                             *out = cp;
0288                             ++out;
0289                             continue;
0290                         }
0291                     }
0292                     *out = replacement_character;
0293                     ++out;
0294                 } else {
0295                     *out = hi;
0296                     ++out;
0297                 }
0298             }
0299 
0300             return {first, out};
0301         }
0302 
0303         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0304         transcode_result<Iter, OutIter> transcode_to_8(
0305             tag_t<format::utf32>,
0306             Iter first,
0307             Sentinel last,
0308             std::ptrdiff_t n,
0309             OutIter out)
0310         {
0311             for (; first != last && (!UseN || n); ++first, --n) {
0312                 out = detail::read_into_utf8_iter(*first, out);
0313             }
0314             return {first, out};
0315         }
0316 
0317         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0318         transcode_result<Iter, OutIter> transcode_to_16(
0319             tag_t<format::utf32>,
0320             Iter first,
0321             Sentinel last,
0322             std::ptrdiff_t n,
0323             OutIter out)
0324         {
0325             for (; first != last && (!UseN || n); ++first, --n) {
0326                 out = detail::read_into_utf16_iter(*first, out);
0327             }
0328             return {first, out};
0329         }
0330 
0331         template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
0332         transcode_result<Iter, OutIter> transcode_to_32(
0333             tag_t<format::utf32>,
0334             Iter first,
0335             Sentinel last,
0336             std::ptrdiff_t n,
0337             OutIter out)
0338         {
0339             for (; first != last && (!UseN || n); ++first, ++out, --n) {
0340                 *out = *first;
0341             }
0342             return {first, out};
0343         }
0344     }
0345 
0346 #if 0
0347     /** Copies the code points in the range [first, last) to out, changing the
0348         encoding from UTF-8 to UTF-32.  */
0349     template<typename InputIter, typename Sentinel, typename OutIter>
0350     transcode_result<InputIter, OutIter> transcode_utf_8_to_32_take_n(
0351         InputIter first, Sentinel last, std::ptrdiff_t n, OutIter out)
0352     {
0353         auto const r = detail::unpack_iterator_and_sentinel(first, last);
0354         return detail::transcode_to_32<true>(
0355             detail::tag_t<r.format_tag>{}, r.first, r.last, n, out);
0356     }
0357 
0358     /** Copies the first `n` code points in the range [first, last) to out,
0359         changing the encoding from UTF-8 to UTF-32.  */
0360     template<typename InputIter, typename Sentinel, typename OutIter>
0361     transcode_result<InputIter, OutIter> transcode_utf_8_to_32_take_n(
0362         InputIter first, Sentinel last, std::ptrdiff_t n, OutIter out)
0363     {
0364         auto const r = detail::unpack_iterator_and_sentinel(first, last);
0365         return detail::transcode_to_32<true>(
0366             detail::tag_t<r.format_tag>{}, r.first, r.last, n, out);
0367     }
0368 
0369     /** Copies the first `n` code points in the range [first, last) to out,
0370         changing the encoding from UTF-8 to UTF-32.  */
0371     template<typename InputIter, typename Sentinel, typename OutIter>
0372     transcode_result<InputIter, OutIter>
0373     transcode_utf_8_to_32_take_n(Range && r, std::ptrdiff_t n, OutIter out)
0374     {
0375         return detail::transcode_utf_8_to_32_dispatch<true, Range, OutIter>::
0376             call(r, n, out)
0377                 .out;
0378     }
0379 #endif
0380 
0381 }}
0382 
0383 namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V1 {
0384 
0385 #if defined(BOOST_TEXT_DOXYGEN)
0386 
0387     // -> utf8
0388 
0389     /** Copies the code points in the range `[first, last)` to `out`, changing
0390         the encoding to UTF-8. */
0391     template<
0392         std::input_iterator I,
0393         std::sentinel_for<I> S,
0394         std::output_iterator<uint8_t> O>
0395     requires(
0396         utf16_code_unit<std::iter_value_t<I>> ||
0397         utf32_code_unit<std::iter_value_t<I>>)
0398     transcode_result<I, O> transcode_to_utf8(I first, S last, O out);
0399 
0400     /** Copies the code points in the range `[p, null_sentinel)` to `out`,
0401         changing the encoding to UTF-8.  */
0402     template<typename Ptr, std::output_iterator<uint8_t> O>
0403     requires(utf16_pointer<Ptr> || utf32_pointer<Ptr>)
0404     transcode_result<Ptr, O> transcode_to_utf8(Ptr p, O out);
0405 
0406     /** Copies the code points in the array `arr` to `out`, changing the
0407         encoding to UTF-8.  */
0408     template<std::size_t N, typename Char, std::output_iterator<uint8_t> O>
0409     requires (utf16_code_unit<Char> || utf32_code_unit<Char>)
0410     transcode_result<Char *, O> transcode_to_utf8(Char (&arr)[N], O out);
0411 
0412     /** Copies the code points in the range `r` to `out`, changing the
0413         encoding to UTF-8.  */
0414     template<std::ranges::input_range R, std::output_iterator<uint8_t> O>
0415     requires (utf16_code_unit<std::ranges::range_value_t<R>> ||
0416               utf32_code_unit<std::ranges::range_value_t<R>>)
0417     transcode_result<std::ranges::borrowed_iterator_t<R>, O>
0418     transcode_to_utf8(R && r, O out);
0419 
0420 
0421     // -> utf16
0422 
0423     /** Copies the code points in the range `[first, last)` to `out`, changing
0424         the encoding to UTF-16. */
0425     template<
0426         std::input_iterator I,
0427         std::sentinel_for<I> S,
0428         std::output_iterator<char16_t> O>
0429     requires (utf8_code_unit<std::iter_value_t<I>> ||
0430               utf32_code_unit<std::iter_value_t<I>>)
0431     transcode_result<I, O> transcode_to_utf16(I first, S last, O out);
0432 
0433     /** Copies the code points in the range `[p, null_sentinel)` to `out`,
0434         changing the encoding to UTF-16.  */
0435     template<typename Ptr, std::output_iterator<char16_t> O>
0436     requires (utf8_pointer<Ptr> || utf32_pointer<Ptr>)
0437     transcode_result<Ptr, O> transcode_to_utf16(Ptr p, O out);
0438 
0439     /** Copies the code points in the array `arr` to `out`, changing the
0440         encoding to UTF-16.  */
0441     template<std::size_t N, typename Char, std::output_iterator<char16_t> O>
0442     requires (utf8_code_unit<Char> || utf32_code_unit<Char>)
0443     transcode_result<Char *, O> transcode_to_utf16(Char (&arr)[N], O out);
0444 
0445     /** Copies the code points in the range `r` to `out`, changing the
0446         encoding to UTF-16.  */
0447     template<std::ranges::input_range R, std::output_iterator<cjar16_t> O>
0448     requires (utf8_code_unit<std::ranges::range_value_t<R>> ||
0449               utf32_code_unit<std::ranges::range_value_t<R>>)
0450     transcode_result<std::ranges::borrowed_iterator_t<R>, O>
0451     transcode_to_utf16(R && r, O out);
0452 
0453 
0454     // -> utf32
0455 
0456     /** Copies the code points in the range `[first, last)` to `out`, changing
0457         the encoding to UTF-32. */
0458     template<
0459         std::input_iterator I,
0460         std::sentinel_for<I> S,
0461         std::output_iterator<uint32_t> O>
0462     requires (utf8_code_unit<std::iter_value_t<I>> ||
0463               utf16_code_unit<std::iter_value_t<I>>)
0464     transcode_result<I, O> transcode_to_utf32(I first, S last, O out);
0465 
0466     /** Copies the code points in the range `[p, null_sentinel)` to `out`,
0467         changing the encoding to UTF-32.  */
0468     template<typename Ptr, std::output_iterator<uint32_t> O>
0469     requires (utf8_pointer<Ptr> || utf16_pointer<Ptr>)
0470     transcode_result<Ptr, O> transcode_to_utf32(Ptr p, O out);
0471 
0472     /** Copies the code points in the array `arr` to `out`, changing the
0473         encoding to UTF-32.  */
0474     template<std::size_t N, typename Char, std::output_iterator<uint32_t> O>
0475     requires (utf8_code_unit<Char> || utf16_code_unit<Char>)
0476     transcode_result<Char *, O> transcode_to_utf32(Char (&arr)[N], O out);
0477 
0478     /** Copies the code points in the range `r` to `out`, changing the
0479         encoding to UTF-32.  */
0480     template<std::ranges::input_range R, std::output_iterator<uint32_t> O>
0481     requires (utf8_code_unit<std::ranges::range_value_t<R>> ||
0482               utf16_code_unit<std::ranges::range_value_t<R>>)
0483     transcode_result<std::ranges::borrowed_iterator_t<R>, O>
0484     transcode_to_utf32(R && r, O out);
0485 
0486 #endif
0487 
0488     namespace dtl {
0489         template<
0490             bool UseN,
0491             typename Range,
0492             typename OutIter,
0493             bool _16Ptr = detail::is_16_ptr_v<Range>,
0494             bool CPPtr = detail::is_cp_ptr_v<Range>>
0495         struct transcode_to_8_dispatch
0496         {
0497             static constexpr auto
0498             call(Range && r, std::ptrdiff_t n, OutIter out)
0499                 -> transcode_result<decltype(detail::begin(r)), OutIter>
0500             {
0501                 auto const u = text::unpack_iterator_and_sentinel(
0502                     detail::begin(r), detail::end(r));
0503                 auto unpacked = detail::transcode_to_8<UseN>(
0504                     detail::tag_t<u.format_tag>{}, u.first, u.last, n, out);
0505                 return {u.repack(unpacked.in), unpacked.out};
0506             }
0507         };
0508 
0509         template<bool UseN, typename Ptr, typename OutIter>
0510         struct transcode_to_8_dispatch<UseN, Ptr, OutIter, true, false>
0511         {
0512             static constexpr auto
0513             call(Ptr p, std::ptrdiff_t n, OutIter out)
0514             {
0515                 return detail::transcode_to_8<UseN>(
0516                     detail::tag_t<format::utf16>{}, p, null_sentinel, n, out);
0517             }
0518         };
0519 
0520         template<bool UseN, typename Ptr, typename OutIter>
0521         struct transcode_to_8_dispatch<UseN, Ptr, OutIter, false, true>
0522         {
0523             static constexpr auto
0524             call(Ptr p, std::ptrdiff_t n, OutIter out)
0525             {
0526                 return detail::transcode_to_8<UseN>(
0527                     detail::tag_t<format::utf32>{}, p, null_sentinel, n, out);
0528             }
0529         };
0530 
0531         template<
0532             bool UseN,
0533             typename Range,
0534             typename OutIter,
0535             bool CharPtr = detail::is_char_ptr_v<Range>,
0536             bool CPPtr = detail::is_cp_ptr_v<Range>>
0537         struct transcode_to_16_dispatch
0538         {
0539             static constexpr auto
0540             call(Range && r, std::ptrdiff_t n, OutIter out)
0541                 -> transcode_result<decltype(detail::begin(r)), OutIter>
0542             {
0543                 auto const u = text::unpack_iterator_and_sentinel(
0544                     detail::begin(r), detail::end(r));
0545                 auto unpacked = detail::transcode_to_16<UseN>(
0546                     detail::tag_t<u.format_tag>{}, u.first, u.last, n, out);
0547                 return {u.repack(unpacked.in), unpacked.out};
0548             }
0549         };
0550 
0551         template<bool UseN, typename Ptr, typename OutIter>
0552         struct transcode_to_16_dispatch<UseN, Ptr, OutIter, true, false>
0553         {
0554             static constexpr auto
0555             call(Ptr p, std::ptrdiff_t n, OutIter out)
0556             {
0557                 return detail::transcode_to_16<UseN>(
0558                     detail::tag_t<format::utf8>{}, p, null_sentinel, n, out);
0559             }
0560         };
0561 
0562         template<bool UseN, typename Ptr, typename OutIter>
0563         struct transcode_to_16_dispatch<UseN, Ptr, OutIter, false, true>
0564         {
0565             static constexpr auto
0566             call(Ptr p, std::ptrdiff_t n, OutIter out)
0567             {
0568                 return detail::transcode_to_16<UseN>(
0569                     detail::tag_t<format::utf32>{}, p, null_sentinel, n, out);
0570             }
0571         };
0572 
0573         template<
0574             bool UseN,
0575             typename Range,
0576             typename OutIter,
0577             bool CharPtr = detail::is_char_ptr_v<Range>,
0578             bool _16Ptr = detail::is_16_ptr_v<Range>>
0579         struct transcode_to_32_dispatch
0580         {
0581             static constexpr auto
0582             call(Range && r, std::ptrdiff_t n, OutIter out)
0583                 -> transcode_result<decltype(detail::begin(r)), OutIter>
0584             {
0585                 auto const u = text::unpack_iterator_and_sentinel(
0586                     detail::begin(r), detail::end(r));
0587                 auto unpacked = detail::transcode_to_32<UseN>(
0588                     detail::tag_t<u.format_tag>{}, u.first, u.last, n, out);
0589                 return {u.repack(unpacked.in), unpacked.out};
0590             }
0591         };
0592 
0593         template<bool UseN, typename Ptr, typename OutIter>
0594         struct transcode_to_32_dispatch<UseN, Ptr, OutIter, true, false>
0595         {
0596             static constexpr auto
0597             call(Ptr p, std::ptrdiff_t n, OutIter out)
0598             {
0599                 return detail::transcode_to_32<UseN>(
0600                     detail::tag_t<format::utf8>{}, p, null_sentinel, n, out);
0601             }
0602         };
0603 
0604         template<bool UseN, typename Ptr, typename OutIter>
0605         struct transcode_to_32_dispatch<UseN, Ptr, OutIter, false, true>
0606         {
0607             static constexpr auto
0608             call(Ptr p, std::ptrdiff_t n, OutIter out)
0609             {
0610                 return detail::transcode_to_32<UseN>(
0611                     detail::tag_t<format::utf16>{}, p, null_sentinel, n, out);
0612             }
0613         };
0614     }
0615 
0616     template<typename Iter, typename Sentinel, typename OutIter>
0617     transcode_result<Iter, OutIter> transcode_to_utf8(
0618         Iter first, Sentinel last, OutIter out)
0619     {
0620         auto const r = text::unpack_iterator_and_sentinel(first, last);
0621         auto unpacked = detail::transcode_to_8<false>(
0622             detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
0623         return {r.repack(unpacked.in), unpacked.out};
0624     }
0625 
0626     template<typename Range, typename OutIter>
0627     transcode_result<detail::iterator_t<Range>, OutIter>
0628     transcode_to_utf8(Range && r, OutIter out)
0629     {
0630         return dtl::transcode_to_8_dispatch<false, Range, OutIter>::call(
0631             r, -1, out);
0632     }
0633 
0634     template<typename Iter, typename Sentinel, typename OutIter>
0635     transcode_result<Iter, OutIter> transcode_to_utf16(
0636         Iter first, Sentinel last, OutIter out)
0637     {
0638         auto const r = text::unpack_iterator_and_sentinel(first, last);
0639         auto unpacked = detail::transcode_to_16<false>(
0640             detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
0641         return {r.repack(unpacked.in), unpacked.out};
0642     }
0643 
0644     template<typename Range, typename OutIter>
0645     transcode_result<detail::iterator_t<Range>, OutIter>
0646     transcode_to_utf16(Range && r, OutIter out)
0647     {
0648         return dtl::transcode_to_16_dispatch<false, Range, OutIter>::call(
0649             r, -1, out);
0650     }
0651 
0652     template<typename Iter, typename Sentinel, typename OutIter>
0653     transcode_result<Iter, OutIter> transcode_to_utf32(
0654         Iter first, Sentinel last, OutIter out)
0655     {
0656         auto const r = text::unpack_iterator_and_sentinel(first, last);
0657         auto unpacked = detail::transcode_to_32<false>(
0658             detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
0659         return {r.repack(unpacked.in), unpacked.out};
0660     }
0661 
0662     template<typename Range, typename OutIter>
0663     transcode_result<detail::iterator_t<Range>, OutIter>
0664     transcode_to_utf32(Range && r, OutIter out)
0665     {
0666         return dtl::transcode_to_32_dispatch<false, Range, OutIter>::call(
0667             r, -1, out);
0668     }
0669 
0670 }}}
0671 
0672 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0673 
0674 namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 {
0675 
0676     // -> utf8
0677 
0678     template<
0679         std::input_iterator I,
0680         std::sentinel_for<I> S,
0681         std::output_iterator<uint8_t> O>
0682         requires(
0683             utf16_code_unit<std::iter_value_t<I>> ||
0684             utf32_code_unit<std::iter_value_t<I>>)
0685     transcode_result<I, O> transcode_to_utf8(I first, S last, O out)
0686     {
0687         auto const r = text::unpack_iterator_and_sentinel(first, last);
0688         auto unpacked = detail::transcode_to_8<false>(
0689             detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
0690         return {r.repack(unpacked.in), unpacked.out};
0691     }
0692 
0693     template<typename R, std::output_iterator<uint32_t> O>
0694         requires(utf16_range<R> || utf32_range<R>)
0695     transcode_result<dtl::uc_result_iterator<R>, O> transcode_to_utf8(
0696         R && r, O out)
0697     {
0698         return text::transcode_to_utf8(
0699             std::ranges::begin(r), std::ranges::end(r), out);
0700     }
0701 
0702 
0703     // -> utf16
0704 
0705     template<
0706         std::input_iterator I,
0707         std::sentinel_for<I> S,
0708         std::output_iterator<char16_t> O>
0709         requires(
0710             utf8_code_unit<std::iter_value_t<I>> ||
0711             utf32_code_unit<std::iter_value_t<I>>)
0712     transcode_result<I, O> transcode_to_utf16(I first, S last, O out)
0713     {
0714         auto const r = text::unpack_iterator_and_sentinel(first, last);
0715         auto unpacked = detail::transcode_to_16<false>(
0716             detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
0717         return {r.repack(unpacked.in), unpacked.out};
0718     }
0719 
0720     template<typename R, std::output_iterator<uint32_t> O>
0721         requires(utf8_range<R> || utf32_range<R>)
0722     transcode_result<dtl::uc_result_iterator<R>, O> transcode_to_utf16(
0723         R && r, O out)
0724     {
0725         return text::transcode_to_utf16(
0726             std::ranges::begin(r), std::ranges::end(r), out);
0727     }
0728 
0729 
0730     // -> utf32
0731 
0732     template<
0733         std::input_iterator I,
0734         std::sentinel_for<I> S,
0735         std::output_iterator<uint32_t> O>
0736         requires(
0737             utf8_code_unit<std::iter_value_t<I>> ||
0738             utf16_code_unit<std::iter_value_t<I>>)
0739     transcode_result<I, O> transcode_to_utf32(I first, S last, O out)
0740     {
0741         auto const r = text::unpack_iterator_and_sentinel(first, last);
0742         auto unpacked = detail::transcode_to_32<false>(
0743             detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
0744         return {r.repack(unpacked.in), unpacked.out};
0745     }
0746 
0747     template<typename R, std::output_iterator<uint32_t> O>
0748         requires(utf8_range<R> || utf16_range<R>)
0749     transcode_result<dtl::uc_result_iterator<R>, O> transcode_to_utf32(
0750         R && r, O out)
0751     {
0752         return text::transcode_to_utf32(
0753             std::ranges::begin(r), std::ranges::end(r), out);
0754     }
0755 
0756 }}}
0757 
0758 #endif
0759 
0760 #endif