diff --git a/include/regex b/include/regex index 7a640519..ad79f066 100644 --- a/include/regex +++ b/include/regex @@ -1680,6 +1680,128 @@ __back_ref<_CharT>::__exec(__state& __s) const } } +// __back_ref_icase + +template +class __back_ref_icase + : public __owns_one_state<_CharT> +{ + typedef __owns_one_state<_CharT> base; + + _Traits __traits_; + unsigned __mexp_; +public: + typedef _STD::__state<_CharT> __state; + + explicit __back_ref_icase(const _Traits& __traits, unsigned __mexp, + __node<_CharT>* __s) + : base(__s), __traits_(__traits), __mexp_(__mexp) {} + + virtual void __exec(__state&) const; + + virtual string speak() const + { + ostringstream os; + os << "__back_ref_icase " << __mexp_; + return os.str(); + } +}; + +template +void +__back_ref_icase<_CharT, _Traits>::__exec(__state& __s) const +{ + sub_match& __sm = __s.__sub_matches_[__mexp_-1]; + if (__sm.matched) + { + ptrdiff_t __len = __sm.second - __sm.first; + if (__s.__last_ - __s.__current_ >= __len) + { + for (ptrdiff_t __i = 0; __i < __len; ++__i) + { + if (__traits_.translate_nocase(__sm.first[__i]) != + __traits_.translate_nocase(__s.__current_[__i])) + goto __not_equal; + } + __s.__do_ = __state::__accept_but_not_consume; + __s.__current_ += __len; + __s.__node_ = this->first(); + } + else + { + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } + } + else + { +__not_equal: + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } +} + +// __back_ref_collate + +template +class __back_ref_collate + : public __owns_one_state<_CharT> +{ + typedef __owns_one_state<_CharT> base; + + _Traits __traits_; + unsigned __mexp_; +public: + typedef _STD::__state<_CharT> __state; + + explicit __back_ref_collate(const _Traits& __traits, unsigned __mexp, + __node<_CharT>* __s) + : base(__s), __traits_(__traits), __mexp_(__mexp) {} + + virtual void __exec(__state&) const; + + virtual string speak() const + { + ostringstream os; + os << "__back_ref_collate " << __mexp_; + return os.str(); + } +}; + +template +void +__back_ref_collate<_CharT, _Traits>::__exec(__state& __s) const +{ + sub_match& __sm = __s.__sub_matches_[__mexp_-1]; + if (__sm.matched) + { + ptrdiff_t __len = __sm.second - __sm.first; + if (__s.__last_ - __s.__current_ >= __len) + { + for (ptrdiff_t __i = 0; __i < __len; ++__i) + { + if (__traits_.translate(__sm.first[__i]) != + __traits_.translate(__s.__current_[__i])) + goto __not_equal; + } + __s.__do_ = __state::__accept_but_not_consume; + __s.__current_ += __len; + __s.__node_ = this->first(); + } + else + { + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } + } + else + { +__not_equal: + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } +} + // __r_anchor template @@ -1806,6 +1928,100 @@ __match_char<_CharT>::__exec(__state& __s) const } } +// __match_char_icase + +template +class __match_char_icase + : public __owns_one_state<_CharT> +{ + typedef __owns_one_state<_CharT> base; + + _Traits __traits_; + _CharT __c_; + + __match_char_icase(const __match_char_icase&); + __match_char_icase& operator=(const __match_char_icase&); +public: + typedef _STD::__state<_CharT> __state; + + __match_char_icase(const _Traits& __traits, _CharT __c, __node<_CharT>* __s) + : base(__s), __traits_(__traits), __c_(__traits.translate_nocase(__c)) {} + + virtual void __exec(__state&) const; + + virtual string speak() const + { + ostringstream os; + os << "match char icase " << __c_; + return os.str(); + } +}; + +template +void +__match_char_icase<_CharT, _Traits>::__exec(__state& __s) const +{ + if (__s.__current_ != __s.__last_ && + __traits_.translate_nocase(*__s.__current_) == __c_) + { + __s.__do_ = __state::__accept_and_consume; + ++__s.__current_; + __s.__node_ = this->first(); + } + else + { + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } +} + +// __match_char_collate + +template +class __match_char_collate + : public __owns_one_state<_CharT> +{ + typedef __owns_one_state<_CharT> base; + + _Traits __traits_; + _CharT __c_; + + __match_char_collate(const __match_char_collate&); + __match_char_collate& operator=(const __match_char_collate&); +public: + typedef _STD::__state<_CharT> __state; + + __match_char_collate(const _Traits& __traits, _CharT __c, __node<_CharT>* __s) + : base(__s), __traits_(__traits), __c_(__traits.translate(__c)) {} + + virtual void __exec(__state&) const; + + virtual string speak() const + { + ostringstream os; + os << "match char icase " << __c_; + return os.str(); + } +}; + +template +void +__match_char_collate<_CharT, _Traits>::__exec(__state& __s) const +{ + if (__s.__current_ != __s.__last_ && + __traits_.translate(*__s.__current_) == __c_) + { + __s.__do_ = __state::__accept_and_consume; + ++__s.__current_; + __s.__node_ = this->first(); + } + else + { + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } +} + template class match_results; template > @@ -2913,7 +3129,14 @@ template void basic_regex<_CharT, _Traits>::__push_char(value_type __c) { - __end_->first() = new __match_char<_CharT>(__c, __end_->first()); + if (flags() & regex_constants::icase) + __end_->first() = new __match_char_icase<_CharT, _Traits> + (__traits_, __c, __end_->first()); + else if (flags() & regex_constants::collate) + __end_->first() = new __match_char_collate<_CharT, _Traits> + (__traits_, __c, __end_->first()); + else + __end_->first() = new __match_char<_CharT>(__c, __end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } @@ -2955,7 +3178,14 @@ template void basic_regex<_CharT, _Traits>::__push_back_ref(int __i) { - __end_->first() = new __back_ref<_CharT>(__i, __end_->first()); + if (flags() & regex_constants::icase) + __end_->first() = new __back_ref_icase<_CharT, _Traits> + (__traits_, __i, __end_->first()); + else if (flags() & regex_constants::collate) + __end_->first() = new __back_ref_collate<_CharT, _Traits> + (__traits_, __i, __end_->first()); + else + __end_->first() = new __back_ref<_CharT>(__i, __end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } diff --git a/test/re/re.alg/re.alg.search/basic.pass.cpp b/test/re/re.alg/re.alg.search/basic.pass.cpp index 72dfa426..df591ed5 100644 --- a/test/re/re.alg/re.alg.search/basic.pass.cpp +++ b/test/re/re.alg/re.alg.search/basic.pass.cpp @@ -472,4 +472,30 @@ int main() assert(!std::regex_search(s, m, std::regex("^\\(ab*\\)*\\1$", std::regex_constants::basic))); assert(m.size() == 0); } + { + std::cmatch m; + const char s[] = "aBAbbAbB"; + assert(std::regex_search(s, m, std::regex("^\\(Ab*\\)*\\1$", + std::regex_constants::basic | std::regex_constants::icase))); + assert(m.size() == 2); + assert(!m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(!m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == m[0].second); + assert(m.length(0) == std::char_traits::length(s)); + assert(m.position(0) == 0); + assert(m.str(0) == s); + assert(m.length(1) == 3); + assert(m.position(1) == 2); + assert(m.str(1) == "Abb"); + } + { + std::cmatch m; + const char s[] = "aBAbbAbB"; + assert(!std::regex_search(s, m, std::regex("^\\(Ab*\\)*\\1$", + std::regex_constants::basic))); + assert(m.size() == 0); + } }