diff --git a/include/regex b/include/regex index ca15864f..b13a7733 100644 --- a/include/regex +++ b/include/regex @@ -1225,7 +1225,7 @@ class __state int __state_; enum { - __1_not_tried = 0, + __not_tried = 0, __1_succeded = 1, __1_failed = 2, __2_not_tried = 0, @@ -1240,9 +1240,11 @@ public: : __t1_(), __t2_(), __state_() {} ~__state(); - const __state* operator()(_CharT __c); + __state* operator()(_CharT __c); void __add_one(__transition* __t) {__t1_ = __t;} + + void __reset_state(); }; template @@ -1253,10 +1255,10 @@ __state<_CharT>::~__state() } template -const __state<_CharT>* +__state<_CharT>* __state<_CharT>::operator()(_CharT __c) { - const __state* __r = nullptr; + __state* __r = nullptr; if ((__state_ & 3) == 0) { if (__t1_) @@ -1286,6 +1288,17 @@ __state<_CharT>::operator()(_CharT __c) return __r; } +template +void +__state<_CharT>::__reset_state() +{ + __state_ = __not_tried; + if (__t1_) + __t1_->__reset_state(); + if (__t2_) + __t2_->__reset_state(); +} + template class __transition { @@ -1305,9 +1318,19 @@ public: : __sptr_(__st, __owns ? &__delete_state : &__ignore_state) {} virtual ~__transition() {} - virtual const __state* operator()(_CharT) const {return __sptr_.get();} + virtual __state* operator()(_CharT) const {return __sptr_.get();} + + void __reset_state(); }; +template +void +__transition<_CharT>::__reset_state() +{ + if (__sptr_.get_deleter() == &__delete_state) + __sptr_->__reset_state(); +} + template class __match_char : public __transition<_CharT> @@ -1318,10 +1341,12 @@ public: __match_char(_CharT __c, bool __owns, __state<_CharT>* __st) : base(__owns, __st), __c_(__c) {} - virtual const __state<_CharT>* operator()(_CharT __c) const + virtual __state<_CharT>* operator()(_CharT __c) const {return __c == __c_ ? base::__sptr_.get() : nullptr;} }; +template class match_results; + template > class basic_regex { @@ -1518,6 +1543,18 @@ private: void __push_class_type(typename _Traits::char_class_type) {} void __push_back_ref(int __i) {} void __push_alternation() {} + + template + bool + __search(_BidirectionalIterator __first, _BidirectionalIterator __last, + match_results<_BidirectionalIterator, _Allocator>& __m, + regex_constants::match_flag_type __flags) const; + + template + friend + bool + regex_search(_B, _B, match_results<_B, _A>&, const basic_regex<_C, _T>&, + regex_constants::match_flag_type); }; template @@ -2852,6 +2889,12 @@ public: // swap: void swap(match_results& __m); +private: + void __init(unsigned __s, + _BidirectionalIterator __f, _BidirectionalIterator __l); + + template friend class basic_regex; + template friend bool @@ -2869,6 +2912,29 @@ match_results<_BidirectionalIterator, _Allocator>::match_results( { } +template +void +match_results<_BidirectionalIterator, _Allocator>::__init(unsigned __s, + _BidirectionalIterator __f, _BidirectionalIterator __l) +{ + __matches_.resize(__s); + for (unsigned __i = 0; __i < __s; ++__i) + { + __matches_[__i].first = __l; + __matches_[__i].second = __l; + __matches_[__i].matched = false; + } + __unmatched_.first = __l; + __unmatched_.second = __l; + __unmatched_.matched = false; + __prefix_.first = __f; + __prefix_.second = __f; + __prefix_.matched = false; + __suffix_.first = __l; + __suffix_.second = __l; + __suffix_.matched = false; +} + typedef match_results cmatch; typedef match_results wcmatch; typedef match_results smatch; @@ -2891,12 +2957,59 @@ template // regex_search +template +template +bool +basic_regex<_CharT, _Traits>::__search( + _BidirectionalIterator __first, _BidirectionalIterator __last, + match_results<_BidirectionalIterator, _Allocator>& __m, + regex_constants::match_flag_type __flags) const +{ + bool __r = false; + if (__start_) + { + __m.__init(1 + mark_count(), __first, __last); + for (; __first != __last; ++__first) + { + __start_->__reset_state(); + __state<_CharT>* __st = (*__start_)(*__first); + if (__st) + { + _BidirectionalIterator& __f = __m.__matches_[0].first; + _BidirectionalIterator& __l = __m.__matches_[0].second; + __m.__matches_[0].matched = false; + __f = __l = __first; + ++__l; + for (; __l != __last && __st != nullptr && __st != __end_; ++__l) + __st = (*__st)(*__l); + if (__st == __end_) + { + __r = __m.__matches_[0].matched = true; + __m.__prefix_.second = __first; + __m.__prefix_.matched = __m.__prefix_.first != __m.__prefix_.second; + __m.__suffix_.first = __l; + __m.__suffix_.matched = __m.__suffix_.first != __m.__suffix_.second; + } + } + if (__flags & regex_constants::match_continuous) + break; + } + } + if (!__r) + __m.__matches_.clear(); + return __r; +} + template +inline _LIBCPP_INLINE_VISIBILITY bool regex_search(_BidirectionalIterator __first, _BidirectionalIterator __last, match_results<_BidirectionalIterator, _Allocator>& __m, const basic_regex<_CharT, _Traits>& __e, - regex_constants::match_flag_type __flags = regex_constants::match_default); + regex_constants::match_flag_type __flags = regex_constants::match_default) +{ + return __e.__search(__first, __last, __m, __flags); +} template inline _LIBCPP_INLINE_VISIBILITY diff --git a/test/re/re.alg/re.alg.search/basic.pass.cpp b/test/re/re.alg/re.alg.search/basic.pass.cpp new file mode 100644 index 00000000..f437c287 --- /dev/null +++ b/test/re/re.alg/re.alg.search/basic.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template +// bool +// regex_search(BidirectionalIterator first, BidirectionalIterator last, +// match_results& m, +// const basic_regex& e, +// regex_constants::match_flag_type flags = regex_constants::match_default); + +#include +#include + +int main() +{ + { + std::cmatch m; + assert(!std::regex_search("a", m, std::regex())); + assert(m.size() == 0); + assert(m.empty()); + } + { + std::cmatch m; + const char s[] = "a"; + assert(std::regex_search(s, m, std::regex("a", std::regex_constants::basic))); + assert(m.size() == 1); + assert(!m.empty()); + 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 == s+1); + assert(m.length(0) == 1); + assert(m.position(0) == 0); + assert(m.str(0) == "a"); + } + { + std::cmatch m; + const char s[] = "ab"; + assert(std::regex_search(s, m, std::regex("ab", std::regex_constants::basic))); + assert(m.size() == 1); + 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 == s+2); + assert(m.length(0) == 2); + assert(m.position(0) == 0); + assert(m.str(0) == "ab"); + } + { + std::cmatch m; + const char s[] = "ab"; + assert(!std::regex_search(s, m, std::regex("ba", std::regex_constants::basic))); + assert(m.size() == 0); + assert(m.empty()); + } + { + std::cmatch m; + const char s[] = "aab"; + assert(std::regex_search(s, m, std::regex("ab", std::regex_constants::basic))); + assert(m.size() == 1); + 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 == s+3); + assert(m.length(0) == 2); + assert(m.position(0) == 1); + assert(m.str(0) == "ab"); + } +}