/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // // Use, modification and distribution is subject to 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) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_VIEW_TOKENIZE_HPP #define RANGES_V3_VIEW_TOKENIZE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-views /// @{ template struct tokenize_view : view_interface, is_finite::value ? finite : range_cardinality::value> { private: CPP_assert(bidirectional_range && view_ && common_range); CPP_assert(semiregular); CPP_assert(semiregular); Rng rng_; Regex rex_; SubMatchRange subs_; std::regex_constants::match_flag_type flags_; template using iterator_t = std::regex_token_iterator>>; public: tokenize_view() = default; tokenize_view(Rng rng, Regex rex, SubMatchRange subs, std::regex_constants::match_flag_type flags) : rng_(std::move(rng)) , rex_(std::move(rex)) , subs_(std::move(subs)) , flags_(flags) {} iterator_t()> begin() { meta::const_if_c(), Rng> & rng = rng_; return {ranges::begin(rng), ranges::end(rng), rex_, subs_, flags_}; } template auto begin() const -> CPP_ret(iterator_t)( // requires range) { return {ranges::begin(rng_), ranges::end(rng_), rex_, subs_, flags_}; } iterator_t()> end() { return {}; } template auto end() const -> CPP_ret(iterator_t)( // requires range) { return {}; } Rng base() const { return rng_; } }; #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17 CPP_template(typename Rng, typename Regex, typename SubMatchRange)( requires copy_constructible && copy_constructible) tokenize_view(Rng &&, Regex, SubMatchRange) ->tokenize_view, Regex, SubMatchRange>; #endif namespace views { struct tokenizer_impl_fn { template tokenize_view, detail::decay_t, int> operator()( Rng && rng, Regex && rex, int sub = 0, std::regex_constants::match_flag_type flags = std::regex_constants::match_default) const { CPP_assert(bidirectional_range); CPP_assert(common_range); static_assert( RANGES_IS_SAME(range_value_t, typename detail::decay_t::value_type), "The character range and the regex have different character types"); return {all(static_cast(rng)), static_cast(rex), sub, flags}; } template tokenize_view, detail::decay_t, std::vector> operator()(Rng && rng, Regex && rex, std::vector subs, std::regex_constants::match_flag_type flags = std::regex_constants::match_default) const { CPP_assert(bidirectional_range); CPP_assert(common_range); static_assert( RANGES_IS_SAME(range_value_t, typename detail::decay_t::value_type), "The character range and the regex have different character types"); return {all(static_cast(rng)), static_cast(rex), std::move(subs), flags}; } template tokenize_view, detail::decay_t, std::initializer_list> operator()(Rng && rng, Regex && rex, std::initializer_list subs, std::regex_constants::match_flag_type flags = std::regex_constants::match_default) const { CPP_assert(bidirectional_range); CPP_assert(common_range); static_assert( RANGES_IS_SAME(range_value_t, typename detail::decay_t::value_type), "The character range and the regex have different character types"); return {all(static_cast(rng)), static_cast(rex), std::move(subs), flags}; } template auto operator()(Regex && rex, int sub = 0, std::regex_constants::match_flag_type flags = std::regex_constants::match_default) const { return make_pipeable( bind_back(*this, static_cast(rex), sub, flags)); } template auto operator()(Regex && rex, std::vector subs, std::regex_constants::match_flag_type flags = std::regex_constants::match_default) const { return make_pipeable( bind_back(*this, static_cast(rex), std::move(subs), flags)); } template auto operator()(Regex && rex, std::initializer_list subs, std::regex_constants::match_flag_type flags = std::regex_constants::match_default) const { return make_pipeable( bind_back(*this, static_cast(rex), subs, flags)); } }; // Damn C++ and its imperfect forwarding of initializer_list. struct tokenize_fn : tokenizer_impl_fn { private: tokenizer_impl_fn const & base() const { return *this; } public: template auto operator()(Args &&... args) const -> decltype(base()(static_cast(args)...)) { return base()(static_cast(args)...); } template auto operator()(Arg0 && arg0, std::initializer_list subs, Args &&... args) const -> decltype(base()(static_cast(arg0), std::move(subs), static_cast(args)...)) { return base()(static_cast(arg0), std::move(subs), static_cast(args)...); } template auto operator()(Arg0 && arg0, Arg1 && arg1, std::initializer_list subs, Args &&... args) const -> decltype(base()(static_cast(arg0), static_cast(arg1), std::move(subs), static_cast(args)...)) { return base()(static_cast(arg0), static_cast(arg1), std::move(subs), static_cast(args)...); } }; /// \relates tokenize_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(tokenize_fn, tokenize) } // namespace views /// @} } // namespace ranges #include RANGES_SATISFY_BOOST_RANGE(::ranges::tokenize_view) #endif