diff --git a/sprout/weed/detail/c_str_as_string.hpp b/sprout/weed/detail/c_str_as_string.hpp index fffe3725..dd0cb62a 100644 --- a/sprout/weed/detail/c_str_as_string.hpp +++ b/sprout/weed/detail/c_str_as_string.hpp @@ -5,12 +5,15 @@ #include #include #include +#include namespace sprout { namespace weed { namespace detail { template - struct c_str_as_string; + struct c_str_as_string + : public sprout::identity + {}; template struct c_str_as_string : public sprout::weed::detail::c_str_as_string diff --git a/sprout/weed/detail/find_character_set.hpp b/sprout/weed/detail/find_character_set.hpp new file mode 100644 index 00000000..a5b7e7a8 --- /dev/null +++ b/sprout/weed/detail/find_character_set.hpp @@ -0,0 +1,112 @@ +#ifndef SPROUT_WEED_DETAIL_FIND_CHARACTER_SET_HPP +#define SPROUT_WEED_DETAIL_FIND_CHARACTER_SET_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace weed { + namespace detail { + template + inline SPROUT_CONSTEXPR RandomAccessIterator + find_character_set_impl_ra( + RandomAccessIterator first, RandomAccessIterator last, T const& value, + typename std::iterator_traits::difference_type pivot, RandomAccessIterator found + ) + { + return found != first ? found + : pivot == 0 ? ( + *first == T('-') ? *sprout::prev(first) <= value && *sprout::next(first) >= value + : *first == value + ) ? first : last + : sprout::weed::detail::find_character_set_impl_ra( + sprout::next(first, pivot), last, value, + (sprout::distance(first, last) - pivot) / 2, + sprout::weed::detail::find_character_set_impl_ra( + first, sprout::next(first, pivot), value, + pivot / 2, + first + ) + ) + ; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_constant_distance_iterator::value, + RandomAccessIterator + >::type + find_character_set( + RandomAccessIterator first, RandomAccessIterator last, T const& value, + std::random_access_iterator_tag* + ) + { + return first == last ? last + : sprout::weed::detail::find_character_set_impl_ra(first, last, value, sprout::distance(first, last) / 2, first) + ; + } + + template + inline SPROUT_CONSTEXPR sprout::pair + find_character_set_impl_1( + sprout::pair const& current, + BidirectionalIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + typedef sprout::pair type; + return current.second || current.first == last ? current + : n == 1 ? ( + *current.first == T('-') ? *sprout::prev(current.first) <= value && *sprout::next(current.first) >= value + : *current.first == value + ) ? type(current.first, true) : type(sprout::next(current.first), false) + : sprout::weed::detail::find_character_set_impl_1( + sprout::weed::detail::find_character_set_impl_1( + current, + last, value, n / 2 + ), + last, value, n - n / 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR sprout::pair + find_character_set_impl( + sprout::pair const& current, + BidirectionalIterator last, T const& value, typename std::iterator_traits::difference_type n + ) + { + return current.second || current.first == last ? current + : sprout::weed::detail::find_character_set_impl( + sprout::weed::detail::find_character_set_impl_1( + current, + last, value, n + ), + last, value, n * 2 + ) + ; + } + template + inline SPROUT_CONSTEXPR BidirectionalIterator + find_character_set( + BidirectionalIterator first, BidirectionalIterator last, T const& value, + std::input_iterator_tag* + ) + { + typedef sprout::pair type; + return sprout::weed::detail::find_character_set_impl(type(first, false), last, value, 1).first; + } + + template + inline SPROUT_CONSTEXPR BidirectionalIterator + find_character_set(BidirectionalIterator first, BidirectionalIterator last, T const& value) { + typedef typename std::iterator_traits::iterator_category* category; + return sprout::weed::detail::find_character_set(first, last, value, category()); + } + } // namespace detail + } // namespace weed +} // namespace sprout + +#endif // #ifndef SPROUT_WEED_DETAIL_FIND_CHARACTER_SET_HPP diff --git a/sprout/weed/parser/char/char.hpp b/sprout/weed/parser/char/char.hpp index e1e9bf42..2c55a4de 100644 --- a/sprout/weed/parser/char/char.hpp +++ b/sprout/weed/parser/char/char.hpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -11,6 +14,10 @@ #include #include #include +#include +#include +#include +#include namespace sprout { namespace weed { @@ -152,6 +159,45 @@ namespace sprout { } }; + // + // char_set_p + // + template + struct char_set_p + : public sprout::weed::parser_base + { + public: + template + struct attribute + : public sprout::identity::value_type> + {}; + template + struct result + : public sprout::identity::type> > + {}; + private: + T t_; + public: + char_set_p() = default; + explicit SPROUT_CONSTEXPR char_set_p(T const& t) + : t_(t) + {} + template + SPROUT_CONSTEXPR typename result::type operator()( + Iterator first, + Iterator last, + Context const& + ) const + { + typedef typename result::type result_type; + typedef typename attribute::type attribute_type; + return first != last && sprout::weed::detail::find_character_set(sprout::begin(t_), sprout::end(t_), *first) != sprout::end(t_) + ? result_type(true, sprout::next(first), *first) + : result_type(false, first, attribute_type()) + ; + } + }; + // // any_char_p // @@ -198,6 +244,26 @@ namespace sprout { operator()(T const& f, T const& l) const { return sprout::weed::char_range_p(f, l); } + template + SPROUT_CONSTEXPR typename std::enable_if< + sprout::weed::traits::is_c_str::value, + sprout::weed::char_set_p< + typename sprout::weed::detail::c_str_as_string::type + > + >::type + operator()(T const& t) const { + return sprout::weed::char_set_p< + typename sprout::weed::detail::c_str_as_string::type + >(sprout::to_string(t)); + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sprout::weed::traits::is_string::value, + sprout::weed::char_set_p + >::type + operator()(T const& t) const { + return sprout::weed::char_set_p(t); + } }; // // char_ diff --git a/sprout/weed/parser/string/string.hpp b/sprout/weed/parser/string/string.hpp index faf20225..d13063c6 100644 --- a/sprout/weed/parser/string/string.hpp +++ b/sprout/weed/parser/string/string.hpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace sprout { namespace weed {