| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- // Copyright (C) 2020 T. Zachary Laine
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_PARSER_DETAIL_TEXT_UNPACK_HPP
- #define BOOST_PARSER_DETAIL_TEXT_UNPACK_HPP
- #include <boost/parser/detail/text/transcode_iterator_fwd.hpp>
- #include <type_traits>
- #include <optional>
- namespace boost::parser::detail { namespace text {
- struct no_op_repacker
- {
- template<class T>
- T operator()(T x) const
- {
- return x;
- }
- };
- namespace detail {
- // Using this custom template is quite a bit faster than using lambdas.
- // Unexpected.
- template<
- typename RepackedIterator,
- typename I,
- typename S,
- typename Then,
- bool Bidi>
- struct repacker
- {
- repacker() = default;
- #if !BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- template<bool Enable = Bidi, typename = std::enable_if_t<Enable>>
- #endif
- repacker(I first, S last, Then then)
- #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- requires Bidi
- #endif
- : first{first},
- last{last},
- then{then}
- {}
- #if !BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- template<bool Enable = !Bidi, typename = std::enable_if_t<Enable>>
- #endif
- repacker(S last, Then then)
- #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- requires(!Bidi)
- #endif
- :
- last{last}, then{then}
- {}
- auto operator()(I it) const
- {
- if constexpr (Bidi) {
- return then(RepackedIterator(*first, it, last));
- } else {
- return then(RepackedIterator(it, last));
- }
- }
- std::optional<I> first;
- [[no_unique_address]] S last;
- [[no_unique_address]] Then then;
- };
- template<typename I, typename S, typename Repack>
- constexpr auto
- unpack_iterator_and_sentinel_impl(I first, S last, Repack repack);
- template<
- format FromFormat,
- format ToFormat,
- typename I,
- typename S,
- typename ErrorHandler,
- typename Repack>
- constexpr auto unpack_iterator_and_sentinel_impl(
- utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> first,
- utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> last,
- Repack repack);
- template<
- format FromFormat,
- format ToFormat,
- typename I,
- typename S,
- typename ErrorHandler,
- typename Repack>
- constexpr auto unpack_iterator_and_sentinel_impl(
- utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> first,
- S last,
- Repack repack);
- template<typename I, typename S, typename Repack>
- constexpr auto
- unpack_iterator_and_sentinel(I first, S last, Repack repack)
- {
- return detail::unpack_iterator_and_sentinel_impl(
- first, last, repack);
- }
- struct unpack_iterator_and_sentinel_cpo
- {
- #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- template<
- utf_iter I,
- std::sentinel_for<I> S,
- typename Repack = no_op_repacker>
- requires std::forward_iterator<I>
- #else
- template<typename I, typename S, typename Repack = no_op_repacker>
- #endif
- constexpr auto
- operator()(I first, S last, Repack repack = Repack()) const
- {
- return unpack_iterator_and_sentinel(first, last, repack);
- }
- };
- }
- inline namespace cpo {
- inline constexpr detail::unpack_iterator_and_sentinel_cpo
- unpack_iterator_and_sentinel{};
- }
- #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- template<format FormatTag, utf_iter I, std::sentinel_for<I> S, class Repack>
- #else
- template<format FormatTag, typename I, typename S, class Repack>
- #endif
- struct unpack_result
- {
- static constexpr format format_tag = FormatTag;
- I first;
- [[no_unique_address]] S last;
- [[no_unique_address]] Repack repack;
- };
- namespace detail {
- struct no_such_type
- {};
- template<typename I, typename S, typename Repack>
- constexpr auto
- unpack_iterator_and_sentinel_impl(I first, S last, Repack repack)
- {
- using value_type = detail::iter_value_t<I>;
- if constexpr (
- std::is_same_v<value_type, char>
- #if defined(__cpp_char8_t)
- || std::is_same_v<value_type, char8_t>
- #endif
- ) {
- return unpack_result<format::utf8, I, S, Repack>{
- first, last, repack};
- } else if constexpr (
- #if defined(_MSC_VER)
- std::is_same_v<value_type, wchar_t> ||
- #endif
- std::is_same_v<value_type, char16_t>) {
- return unpack_result<format::utf16, I, S, Repack>{
- first, last, repack};
- } else if constexpr (
- #if !defined(_MSC_VER)
- std::is_same_v<value_type, wchar_t> ||
- #endif
- std::is_same_v<value_type, char32_t>) {
- return unpack_result<format::utf32, I, S, Repack>{
- first, last, repack};
- } else {
- static_assert(
- std::is_same_v<Repack, no_such_type>,
- "Unpacked iterator is not a utf_iter!");
- return 0;
- }
- }
- }
- }}
- #include <boost/parser/detail/text/transcode_iterator.hpp>
- namespace boost::parser::detail { namespace text { namespace detail {
- template<
- format FromFormat,
- format ToFormat,
- typename I,
- typename S,
- typename ErrorHandler,
- typename Repack>
- constexpr auto unpack_iterator_and_sentinel_impl(
- utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> first,
- utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> last,
- Repack repack)
- {
- using iterator = utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler>;
- if constexpr (
- #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- std::bidirectional_iterator<I>
- #else
- std::is_base_of_v<
- std::bidirectional_iterator_tag,
- typename std::iterator_traits<I>::iterator_category>
- #endif
- ) {
- return boost::parser::detail::text::unpack_iterator_and_sentinel(
- first.base(),
- last.base(),
- repacker<
- iterator,
- decltype(first.begin()),
- decltype(first.end()),
- Repack,
- true>(first.begin(), first.end(), repack));
- } else {
- return boost::parser::detail::text::unpack_iterator_and_sentinel(
- first.base(),
- last.base(),
- repacker<iterator, int, decltype(first.end()), Repack, false>(
- first.end(), repack));
- }
- }
- template<
- format FromFormat,
- format ToFormat,
- typename I,
- typename S,
- typename ErrorHandler,
- typename Repack>
- constexpr auto unpack_iterator_and_sentinel_impl(
- utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> first,
- S last,
- Repack repack)
- {
- using iterator = utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler>;
- if constexpr (
- #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- std::bidirectional_iterator<I>
- #else
- std::is_base_of_v<
- std::bidirectional_iterator_tag,
- typename std::iterator_traits<I>::iterator_category>
- #endif
- ) {
- return boost::parser::detail::text::unpack_iterator_and_sentinel(
- first.base(),
- last,
- repacker<
- iterator,
- decltype(first.begin()),
- decltype(first.end()),
- Repack,
- true>(first.begin(), first.end(), repack));
- } else {
- return boost::parser::detail::text::unpack_iterator_and_sentinel(
- first.base(),
- last,
- repacker<iterator, int, S, Repack, false>(last, repack));
- }
- }
- }}}
- #endif
|