commit c57f8cc23ddc0d6e0b81992173dcf2d227251175 Author: tim Date: Fri Aug 23 17:32:51 2013 +0800 2013-08-30 Tim Shen * include/bits/regex_compiler.h: Add _AnyMatcher and _CharMatcher. (_BracketMatcher<>::_M_add_char): Use set instead of vector for _M_char_set. (_BracketMatcher<>::_M_add_collating_element): Likewise. (_BracketMatcher<>::_M_make_range): Likewise. * include/bits/regex_compiler.tcc (_Compiler<>::_M_atom): Use apropriate constructors of matchers above. * testsuite/28_regex/algorithms/regex_match/ecma/string_anymatcher.cc: New. diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h index a1107bb..d45e3e1 100644 --- a/libstdc++-v3/include/bits/regex_compiler.h +++ b/libstdc++-v3/include/bits/regex_compiler.h @@ -131,6 +131,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _FlagT _M_flags; }; + template + struct _AnyMatcher + { + explicit + _AnyMatcher(const _TraitsT& __traits) + : _M_traits(__traits) + { } + + bool + operator()(_CharT __ch) const + { + return _M_traits.translate(__ch) != '\n' + && _M_traits.translate(__ch) != '\r' + && _M_traits.translate(__ch) != u'\u2028' + && _M_traits.translate(__ch) != u'\u2029'; + } + + const _TraitsT& _M_traits; + }; + + template + struct _CharMatcher + { + typedef regex_constants::syntax_option_type _FlagT; + + explicit + _CharMatcher(_CharT __ch, const _TraitsT& __traits, _FlagT __flags) + : _M_ch(_M_translate(__ch)), _M_traits(__traits), _M_flags(__flags) + { } + + bool + operator()(_CharT __ch) const + { return _M_ch == _M_translate(__ch); } + + _CharT + _M_translate(_CharT __ch) const + { + if (_M_flags & regex_constants::icase) + return _M_traits.translate_nocase(__ch); + else + return _M_traits.translate(__ch); + } + + _CharT _M_ch; + const _TraitsT& _M_traits; + _FlagT _M_flags; + }; + /// Matches a character range (bracket expression) template struct _BracketMatcher @@ -141,9 +189,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION explicit _BracketMatcher(bool __is_non_matching, - const _TraitsT& __t, + const _TraitsT& __traits, _FlagT __flags) - : _M_is_non_matching(__is_non_matching), _M_traits(__t), + : _M_is_non_matching(__is_non_matching), _M_traits(__traits), _M_flags(__flags), _M_class_set(0) { } @@ -152,7 +200,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_add_char(_CharT __c) - { _M_char_set.push_back(_M_translate(__c)); } + { _M_char_set.insert(_M_translate(__c)); } void _M_add_collating_element(const _StringT& __s) @@ -162,7 +210,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__st.empty()) __throw_regex_error(regex_constants::error_collate); // TODO: digraph - _M_char_set.push_back(__st[0]); + _M_char_set.insert(_M_translate(__st[0])); } void @@ -186,21 +234,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_make_range(_CharT __l, _CharT __r) { - _M_range_set.push_back( - make_pair(_M_get_str(_M_translate(__l)), - _M_get_str(_M_translate(__r)))); + if (_M_flags & regex_constants::collate) + _M_range_set.insert( + make_pair(_M_get_str(_M_translate(__l)), + _M_get_str(_M_translate(__r)))); + else + _M_range_set.insert(make_pair(_M_get_str(__l), _M_get_str(__r))); } _CharT _M_translate(_CharT __c) const { - if (_M_flags & regex_constants::collate) - if (_M_is_icase()) - return _M_traits.translate_nocase(__c); - else - return _M_traits.translate(__c); + if (_M_is_icase()) + return _M_traits.translate_nocase(__c); else - return __c; + return _M_traits.translate(__c); } bool @@ -214,12 +262,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _M_traits.transform(__s.begin(), __s.end()); } - const _TraitsT& _M_traits; - _FlagT _M_flags; - bool _M_is_non_matching; - std::vector<_CharT> _M_char_set; - std::vector> _M_range_set; - _CharClassT _M_class_set; + const _TraitsT& _M_traits; + _FlagT _M_flags; + bool _M_is_non_matching; + std::set<_CharT> _M_char_set; + std::set> _M_range_set; + _CharClassT _M_class_set; }; //@} regex-detail diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc index bed091a..e41b251 100644 --- a/libstdc++-v3/include/bits/regex_compiler.tcc +++ b/libstdc++-v3/include/bits/regex_compiler.tcc @@ -204,32 +204,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (_M_match_token(_ScannerT::_S_token_anychar)) { - const static auto& - __any_matcher = [](_CharT __ch) -> bool - { return true; }; - _M_stack.push(_StateSeqT(_M_state_store, _M_state_store._M_insert_matcher - (__any_matcher))); + (_AnyMatcher<_CharT, _TraitsT>(_M_traits)))); return true; } if (_M_try_char()) { - _CharT __c = _M_value[0]; - __detail::_Matcher<_CharT> f; - if (_M_flags & regex_constants::icase) - { - auto __traits = this->_M_traits; - __c = __traits.translate_nocase(__c); - f = [__traits, __c](_CharT __ch) -> bool - { return __traits.translate_nocase(__ch) == __c; }; - } - else - f = [__c](_CharT __ch) -> bool - { return __ch == __c; }; - _M_stack.push(_StateSeqT(_M_state_store, - _M_state_store._M_insert_matcher(f))); + _M_state_store._M_insert_matcher + (_CharMatcher<_CharT, _TraitsT>(_M_value[0], + _M_traits, + _M_flags)))); return true; } if (_M_match_token(_ScannerT::_S_token_backref)) @@ -374,26 +360,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool __ret = false; if (_M_traits.isctype(__ch, _M_class_set)) __ret = true; + else if (_M_char_set.count(_M_translate(__ch))) + __ret = true; else { - __ch = _M_translate(__ch); - - for (auto __c : _M_char_set) - if (__c == __ch) + _StringT __s = _M_get_str(_M_flags & regex_constants::collate + ? _M_translate(__ch) : __ch); + for (auto& __it : _M_range_set) + if (__it.first <= __s && __s <= __it.second) { __ret = true; break; } - if (!__ret) - { - _StringT __s = _M_get_str(__ch); - for (auto& __it : _M_range_set) - if (__it.first <= __s && __s <= __it.second) - { - __ret = true; - break; - } - } } if (_M_is_non_matching) return !__ret; diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/string_anymatcher.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/string_anymatcher.cc new file mode 100644 index 0000000..5380d92 --- /dev/null +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/string_anymatcher.cc @@ -0,0 +1,60 @@ +// { dg-options "-std=gnu++11" } + +// +// 2013-08-30 Tim Shen +// +// Copyright (C) 2013 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 28.11.2 regex_match +// Tests ECMAScript "." against a std::string. + +#include +#include + +using namespace std; + +void +test01() +{ + bool test __attribute__((unused)) = true; + +#define TEST(res, s) \ + {\ + regex re(res);\ + string st(s);\ + VERIFY(!regex_match(st, re));\ + } +#define TESTL(res, s) \ + {\ + wregex re(res);\ + wstring st(s);\ + VERIFY(!regex_match(st, re));\ + } + TEST(".", "\0"); + TEST(".", "\n"); + TEST(".", "\r"); + TESTL(L".", L"\u2028"); + TESTL(L".", L"\u2029"); +} + +int +main() +{ + test01(); + return 0; +}