mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-25 03:55:32 +08:00
f5a2d78072
The std::regex code uses std::map and std::vector, which means that when _GLIBCXX_DEBUG is defined it uses the debug versions of those containers. That no longer compiles, because I changed <regex> to include <bits/stl_map.h> and <bits/stl_vector.h> instead of <map> and <vector>, so the debug versions aren't defined, and std::map doesn't compile. There is also a use of std::stack, which defaults to std::deque which is the debug deque when _GLIBCXX_DEBUG is defined. Using std::map, std::vector, and std::deque is probably a mistake, and we should qualify them with _GLIBCXX_STD_C instead so that the debug versions aren't used. We do not need the overhead of checking our own uses of those containers, which should be correct anyway. The exception is the vector base class of std::match_results, which exposes iterators to users, so can benefit from debug mode checks for its iterators. For other accesses to the vector elements, match_results already does its own checks, so can access the _GLIBCXX_STD_C::vector base class directly. Signed-off-by: Jonathan Wakely <jwakely@redhat.com> libstdc++-v3/ChangeLog: * include/bits/regex.h (basic_regex::transform_primary): Use _GLIBCXX_STD_C::vector for local variable. * include/bits/regex.tcc (__regex_algo_impl): Use reference to _GLIBCXX_STD_C::vector base class of match_results. * include/bits/regex_automaton.tcc (_StateSeq:_M_clone): Use _GLIBCXX_STD_C::map and _GLIBCXX_STD_C::deque for local variables. * include/bits/regex_compiler.h (_BracketMatcher): Use _GLIBCXX_STD_C::vector for data members. * include/bits/regex_executor.h (_Executor): Likewise. * include/std/regex [_GLIBCXX_DEBUG]: Include <debug/vector>.
264 lines
7.5 KiB
C++
264 lines
7.5 KiB
C++
// class template regex -*- C++ -*-
|
|
|
|
// Copyright (C) 2013-2021 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.
|
|
|
|
// Under Section 7 of GPL version 3, you are granted additional
|
|
// permissions described in the GCC Runtime Library Exception, version
|
|
// 3.1, as published by the Free Software Foundation.
|
|
|
|
// You should have received a copy of the GNU General Public License and
|
|
// a copy of the GCC Runtime Library Exception along with this program;
|
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
* @file bits/regex_executor.h
|
|
* This is an internal header file, included by other library headers.
|
|
* Do not attempt to use it directly. @headername{regex}
|
|
*/
|
|
|
|
// FIXME convert comments to doxygen format.
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
|
|
namespace __detail
|
|
{
|
|
/**
|
|
* @addtogroup regex-detail
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Takes a regex and an input string and does the matching.
|
|
*
|
|
* The %_Executor class has two modes: DFS mode and BFS mode, controlled
|
|
* by the template parameter %__dfs_mode.
|
|
*/
|
|
template<typename _BiIter, typename _Alloc, typename _TraitsT,
|
|
bool __dfs_mode>
|
|
class _Executor
|
|
{
|
|
using __search_mode = integral_constant<bool, __dfs_mode>;
|
|
using __dfs = true_type;
|
|
using __bfs = false_type;
|
|
|
|
enum class _Match_mode : unsigned char { _Exact, _Prefix };
|
|
|
|
public:
|
|
typedef typename iterator_traits<_BiIter>::value_type _CharT;
|
|
typedef basic_regex<_CharT, _TraitsT> _RegexT;
|
|
typedef _GLIBCXX_STD_C::vector<sub_match<_BiIter>, _Alloc> _ResultsVec;
|
|
typedef regex_constants::match_flag_type _FlagT;
|
|
typedef typename _TraitsT::char_class_type _ClassT;
|
|
typedef _NFA<_TraitsT> _NFAT;
|
|
|
|
public:
|
|
_Executor(_BiIter __begin,
|
|
_BiIter __end,
|
|
_ResultsVec& __results,
|
|
const _RegexT& __re,
|
|
_FlagT __flags)
|
|
: _M_begin(__begin),
|
|
_M_end(__end),
|
|
_M_re(__re),
|
|
_M_nfa(*__re._M_automaton),
|
|
_M_results(__results),
|
|
_M_rep_count(_M_nfa.size()),
|
|
_M_states(_M_nfa._M_start(), _M_nfa.size()),
|
|
_M_flags((__flags & regex_constants::match_prev_avail)
|
|
? (__flags
|
|
& ~regex_constants::match_not_bol
|
|
& ~regex_constants::match_not_bow)
|
|
: __flags)
|
|
{ }
|
|
|
|
// Set matched when string exactly matches the pattern.
|
|
bool
|
|
_M_match()
|
|
{
|
|
_M_current = _M_begin;
|
|
return _M_main(_Match_mode::_Exact);
|
|
}
|
|
|
|
// Set matched when some prefix of the string matches the pattern.
|
|
bool
|
|
_M_search_from_first()
|
|
{
|
|
_M_current = _M_begin;
|
|
return _M_main(_Match_mode::_Prefix);
|
|
}
|
|
|
|
bool
|
|
_M_search();
|
|
|
|
private:
|
|
void
|
|
_M_rep_once_more(_Match_mode __match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_repeat(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_subexpr_begin(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_subexpr_end(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_line_begin_assertion(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_line_end_assertion(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_word_boundary(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_subexpr_lookahead(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_match(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_backref(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_accept(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_handle_alternative(_Match_mode, _StateIdT);
|
|
|
|
void
|
|
_M_dfs(_Match_mode __match_mode, _StateIdT __start);
|
|
|
|
bool
|
|
_M_main(_Match_mode __match_mode)
|
|
{ return _M_main_dispatch(__match_mode, __search_mode{}); }
|
|
|
|
bool
|
|
_M_main_dispatch(_Match_mode __match_mode, __dfs);
|
|
|
|
bool
|
|
_M_main_dispatch(_Match_mode __match_mode, __bfs);
|
|
|
|
bool
|
|
_M_is_word(_CharT __ch) const
|
|
{
|
|
static const _CharT __s[2] = { 'w' };
|
|
return _M_re._M_automaton->_M_traits.isctype
|
|
(__ch, _M_re._M_automaton->_M_traits.lookup_classname(__s, __s+1));
|
|
}
|
|
|
|
bool
|
|
_M_at_begin() const
|
|
{
|
|
return _M_current == _M_begin
|
|
&& !(_M_flags & (regex_constants::match_not_bol
|
|
| regex_constants::match_prev_avail));
|
|
}
|
|
|
|
bool
|
|
_M_at_end() const
|
|
{
|
|
return _M_current == _M_end
|
|
&& !(_M_flags & regex_constants::match_not_eol);
|
|
}
|
|
|
|
bool
|
|
_M_word_boundary() const;
|
|
|
|
bool
|
|
_M_lookahead(_StateIdT __next);
|
|
|
|
// Holds additional information used in BFS-mode.
|
|
template<typename _SearchMode, typename _ResultsVec>
|
|
struct _State_info;
|
|
|
|
template<typename _ResultsVec>
|
|
struct _State_info<__bfs, _ResultsVec>
|
|
{
|
|
explicit
|
|
_State_info(_StateIdT __start, size_t __n)
|
|
: _M_visited_states(new bool[__n]()), _M_start(__start)
|
|
{ }
|
|
|
|
~_State_info() { delete[] _M_visited_states; }
|
|
|
|
_State_info(const _State_info&) = delete;
|
|
_State_info& operator=(const _State_info&) = delete;
|
|
|
|
bool _M_visited(_StateIdT __i)
|
|
{
|
|
if (_M_visited_states[__i])
|
|
return true;
|
|
_M_visited_states[__i] = true;
|
|
return false;
|
|
}
|
|
|
|
void _M_queue(_StateIdT __i, const _ResultsVec& __res)
|
|
{ _M_match_queue.emplace_back(__i, __res); }
|
|
|
|
// Dummy implementations for BFS mode.
|
|
_BiIter* _M_get_sol_pos() { return nullptr; }
|
|
|
|
// Saves states that need to be considered for the next character.
|
|
_GLIBCXX_STD_C::vector<pair<_StateIdT, _ResultsVec>> _M_match_queue;
|
|
// Indicates which states are already visited.
|
|
bool* _M_visited_states;
|
|
// To record current solution.
|
|
_StateIdT _M_start;
|
|
};
|
|
|
|
template<typename _ResultsVec>
|
|
struct _State_info<__dfs, _ResultsVec>
|
|
{
|
|
explicit
|
|
_State_info(_StateIdT __start, size_t) : _M_start(__start)
|
|
{ }
|
|
|
|
// Dummy implementations for DFS mode.
|
|
bool _M_visited(_StateIdT) const { return false; }
|
|
void _M_queue(_StateIdT, const _ResultsVec&) { }
|
|
|
|
_BiIter* _M_get_sol_pos() { return &_M_sol_pos; }
|
|
|
|
// To record current solution.
|
|
_StateIdT _M_start;
|
|
_BiIter _M_sol_pos;
|
|
};
|
|
|
|
public:
|
|
_ResultsVec _M_cur_results;
|
|
_BiIter _M_current;
|
|
_BiIter _M_begin;
|
|
const _BiIter _M_end;
|
|
const _RegexT& _M_re;
|
|
const _NFAT& _M_nfa;
|
|
_ResultsVec& _M_results;
|
|
_GLIBCXX_STD_C::vector<pair<_BiIter, int>> _M_rep_count;
|
|
_State_info<__search_mode, _ResultsVec> _M_states;
|
|
_FlagT _M_flags;
|
|
// Do we have a solution so far?
|
|
bool _M_has_sol;
|
|
};
|
|
|
|
///@} regex-detail
|
|
} // namespace __detail
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace std
|
|
|
|
#include <bits/regex_executor.tcc>
|