1*38fd1498Szrj // class template regex -*- C++ -*-
2*38fd1498Szrj 
3*38fd1498Szrj // Copyright (C) 2010-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj 
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj 
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj 
25*38fd1498Szrj /**
26*38fd1498Szrj  *  @file bits/regex_compiler.h
27*38fd1498Szrj  *  This is an internal header file, included by other library headers.
28*38fd1498Szrj  *  Do not attempt to use it directly. @headername{regex}
29*38fd1498Szrj  */
30*38fd1498Szrj 
_GLIBCXX_VISIBILITY(default)31*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
32*38fd1498Szrj {
33*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
34*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_CXX11
35*38fd1498Szrj 
36*38fd1498Szrj   template<typename>
37*38fd1498Szrj     class regex_traits;
38*38fd1498Szrj 
39*38fd1498Szrj _GLIBCXX_END_NAMESPACE_CXX11
40*38fd1498Szrj 
41*38fd1498Szrj namespace __detail
42*38fd1498Szrj {
43*38fd1498Szrj   /**
44*38fd1498Szrj    * @addtogroup regex-detail
45*38fd1498Szrj    * @{
46*38fd1498Szrj    */
47*38fd1498Szrj 
48*38fd1498Szrj   template<typename, bool, bool>
49*38fd1498Szrj     struct _BracketMatcher;
50*38fd1498Szrj 
51*38fd1498Szrj   /**
52*38fd1498Szrj    * @brief Builds an NFA from an input iterator range.
53*38fd1498Szrj    *
54*38fd1498Szrj    * The %_TraitsT type should fulfill requirements [28.3].
55*38fd1498Szrj    */
56*38fd1498Szrj   template<typename _TraitsT>
57*38fd1498Szrj     class _Compiler
58*38fd1498Szrj     {
59*38fd1498Szrj     public:
60*38fd1498Szrj       typedef typename _TraitsT::char_type        _CharT;
61*38fd1498Szrj       typedef const _CharT*                       _IterT;
62*38fd1498Szrj       typedef _NFA<_TraitsT>              	  _RegexT;
63*38fd1498Szrj       typedef regex_constants::syntax_option_type _FlagT;
64*38fd1498Szrj 
65*38fd1498Szrj       _Compiler(_IterT __b, _IterT __e,
66*38fd1498Szrj 		const typename _TraitsT::locale_type& __traits, _FlagT __flags);
67*38fd1498Szrj 
68*38fd1498Szrj       shared_ptr<const _RegexT>
69*38fd1498Szrj       _M_get_nfa()
70*38fd1498Szrj       { return std::move(_M_nfa); }
71*38fd1498Szrj 
72*38fd1498Szrj     private:
73*38fd1498Szrj       typedef _Scanner<_CharT>               _ScannerT;
74*38fd1498Szrj       typedef typename _TraitsT::string_type _StringT;
75*38fd1498Szrj       typedef typename _ScannerT::_TokenT    _TokenT;
76*38fd1498Szrj       typedef _StateSeq<_TraitsT>            _StateSeqT;
77*38fd1498Szrj       typedef std::stack<_StateSeqT>         _StackT;
78*38fd1498Szrj       typedef std::ctype<_CharT>             _CtypeT;
79*38fd1498Szrj 
80*38fd1498Szrj       // accepts a specific token or returns false.
81*38fd1498Szrj       bool
82*38fd1498Szrj       _M_match_token(_TokenT __token);
83*38fd1498Szrj 
84*38fd1498Szrj       void
85*38fd1498Szrj       _M_disjunction();
86*38fd1498Szrj 
87*38fd1498Szrj       void
88*38fd1498Szrj       _M_alternative();
89*38fd1498Szrj 
90*38fd1498Szrj       bool
91*38fd1498Szrj       _M_term();
92*38fd1498Szrj 
93*38fd1498Szrj       bool
94*38fd1498Szrj       _M_assertion();
95*38fd1498Szrj 
96*38fd1498Szrj       bool
97*38fd1498Szrj       _M_quantifier();
98*38fd1498Szrj 
99*38fd1498Szrj       bool
100*38fd1498Szrj       _M_atom();
101*38fd1498Szrj 
102*38fd1498Szrj       bool
103*38fd1498Szrj       _M_bracket_expression();
104*38fd1498Szrj 
105*38fd1498Szrj       template<bool __icase, bool __collate>
106*38fd1498Szrj 	void
107*38fd1498Szrj 	_M_insert_any_matcher_ecma();
108*38fd1498Szrj 
109*38fd1498Szrj       template<bool __icase, bool __collate>
110*38fd1498Szrj 	void
111*38fd1498Szrj 	_M_insert_any_matcher_posix();
112*38fd1498Szrj 
113*38fd1498Szrj       template<bool __icase, bool __collate>
114*38fd1498Szrj 	void
115*38fd1498Szrj 	_M_insert_char_matcher();
116*38fd1498Szrj 
117*38fd1498Szrj       template<bool __icase, bool __collate>
118*38fd1498Szrj 	void
119*38fd1498Szrj 	_M_insert_character_class_matcher();
120*38fd1498Szrj 
121*38fd1498Szrj       template<bool __icase, bool __collate>
122*38fd1498Szrj 	void
123*38fd1498Szrj 	_M_insert_bracket_matcher(bool __neg);
124*38fd1498Szrj 
125*38fd1498Szrj       // Returns true if successfully matched one term and should continue.
126*38fd1498Szrj       // Returns false if the compiler should move on.
127*38fd1498Szrj       template<bool __icase, bool __collate>
128*38fd1498Szrj 	bool
129*38fd1498Szrj 	_M_expression_term(pair<bool, _CharT>& __last_char,
130*38fd1498Szrj 			   _BracketMatcher<_TraitsT, __icase, __collate>&
131*38fd1498Szrj 			   __matcher);
132*38fd1498Szrj 
133*38fd1498Szrj       int
134*38fd1498Szrj       _M_cur_int_value(int __radix);
135*38fd1498Szrj 
136*38fd1498Szrj       bool
137*38fd1498Szrj       _M_try_char();
138*38fd1498Szrj 
139*38fd1498Szrj       _StateSeqT
140*38fd1498Szrj       _M_pop()
141*38fd1498Szrj       {
142*38fd1498Szrj 	auto ret = _M_stack.top();
143*38fd1498Szrj 	_M_stack.pop();
144*38fd1498Szrj 	return ret;
145*38fd1498Szrj       }
146*38fd1498Szrj 
147*38fd1498Szrj       _FlagT              _M_flags;
148*38fd1498Szrj       _ScannerT           _M_scanner;
149*38fd1498Szrj       shared_ptr<_RegexT> _M_nfa;
150*38fd1498Szrj       _StringT            _M_value;
151*38fd1498Szrj       _StackT             _M_stack;
152*38fd1498Szrj       const _TraitsT&     _M_traits;
153*38fd1498Szrj       const _CtypeT&      _M_ctype;
154*38fd1498Szrj     };
155*38fd1498Szrj 
156*38fd1498Szrj   template<typename _Tp>
157*38fd1498Szrj     struct __has_contiguous_iter : std::false_type { };
158*38fd1498Szrj 
159*38fd1498Szrj   template<typename _Ch, typename _Tr, typename _Alloc>
160*38fd1498Szrj     struct __has_contiguous_iter<std::basic_string<_Ch, _Tr, _Alloc>>
161*38fd1498Szrj     : std::true_type
162*38fd1498Szrj     { };
163*38fd1498Szrj 
164*38fd1498Szrj   template<typename _Tp, typename _Alloc>
165*38fd1498Szrj     struct __has_contiguous_iter<std::vector<_Tp, _Alloc>>
166*38fd1498Szrj     : std::true_type
167*38fd1498Szrj     { };
168*38fd1498Szrj 
169*38fd1498Szrj   template<typename _Tp>
170*38fd1498Szrj     struct __is_contiguous_normal_iter : std::false_type { };
171*38fd1498Szrj 
172*38fd1498Szrj   template<typename _CharT>
173*38fd1498Szrj     struct __is_contiguous_normal_iter<_CharT*> : std::true_type { };
174*38fd1498Szrj 
175*38fd1498Szrj   template<typename _Tp, typename _Cont>
176*38fd1498Szrj     struct
177*38fd1498Szrj     __is_contiguous_normal_iter<__gnu_cxx::__normal_iterator<_Tp, _Cont>>
178*38fd1498Szrj     : __has_contiguous_iter<_Cont>::type
179*38fd1498Szrj     { };
180*38fd1498Szrj 
181*38fd1498Szrj   template<typename _Iter, typename _TraitsT>
182*38fd1498Szrj     using __enable_if_contiguous_normal_iter
183*38fd1498Szrj       = typename enable_if< __is_contiguous_normal_iter<_Iter>::value,
184*38fd1498Szrj                            std::shared_ptr<const _NFA<_TraitsT>> >::type;
185*38fd1498Szrj 
186*38fd1498Szrj   template<typename _Iter, typename _TraitsT>
187*38fd1498Szrj     using __disable_if_contiguous_normal_iter
188*38fd1498Szrj       = typename enable_if< !__is_contiguous_normal_iter<_Iter>::value,
189*38fd1498Szrj                            std::shared_ptr<const _NFA<_TraitsT>> >::type;
190*38fd1498Szrj 
191*38fd1498Szrj   template<typename _TraitsT, typename _FwdIter>
192*38fd1498Szrj     inline __enable_if_contiguous_normal_iter<_FwdIter, _TraitsT>
193*38fd1498Szrj     __compile_nfa(_FwdIter __first, _FwdIter __last,
194*38fd1498Szrj 		  const typename _TraitsT::locale_type& __loc,
195*38fd1498Szrj 		  regex_constants::syntax_option_type __flags)
196*38fd1498Szrj     {
197*38fd1498Szrj       size_t __len = __last - __first;
198*38fd1498Szrj       const auto* __cfirst = __len ? std::__addressof(*__first) : nullptr;
199*38fd1498Szrj       using _Cmplr = _Compiler<_TraitsT>;
200*38fd1498Szrj       return _Cmplr(__cfirst, __cfirst + __len, __loc, __flags)._M_get_nfa();
201*38fd1498Szrj     }
202*38fd1498Szrj 
203*38fd1498Szrj   template<typename _TraitsT, typename _FwdIter>
204*38fd1498Szrj     inline __disable_if_contiguous_normal_iter<_FwdIter, _TraitsT>
205*38fd1498Szrj     __compile_nfa(_FwdIter __first, _FwdIter __last,
206*38fd1498Szrj 		  const typename _TraitsT::locale_type& __loc,
207*38fd1498Szrj 		  regex_constants::syntax_option_type __flags)
208*38fd1498Szrj     {
209*38fd1498Szrj       const basic_string<typename _TraitsT::char_type> __str(__first, __last);
210*38fd1498Szrj       return __compile_nfa<_TraitsT>(__str.data(), __str.data() + __str.size(),
211*38fd1498Szrj 				     __loc, __flags);
212*38fd1498Szrj     }
213*38fd1498Szrj 
214*38fd1498Szrj   // [28.13.14]
215*38fd1498Szrj   template<typename _TraitsT, bool __icase, bool __collate>
216*38fd1498Szrj     class _RegexTranslatorBase
217*38fd1498Szrj     {
218*38fd1498Szrj     public:
219*38fd1498Szrj       typedef typename _TraitsT::char_type	      _CharT;
220*38fd1498Szrj       typedef typename _TraitsT::string_type	      _StringT;
221*38fd1498Szrj       typedef _StringT _StrTransT;
222*38fd1498Szrj 
223*38fd1498Szrj       explicit
224*38fd1498Szrj       _RegexTranslatorBase(const _TraitsT& __traits)
225*38fd1498Szrj       : _M_traits(__traits)
226*38fd1498Szrj       { }
227*38fd1498Szrj 
228*38fd1498Szrj       _CharT
229*38fd1498Szrj       _M_translate(_CharT __ch) const
230*38fd1498Szrj       {
231*38fd1498Szrj 	if (__icase)
232*38fd1498Szrj 	  return _M_traits.translate_nocase(__ch);
233*38fd1498Szrj 	else if (__collate)
234*38fd1498Szrj 	  return _M_traits.translate(__ch);
235*38fd1498Szrj 	else
236*38fd1498Szrj 	  return __ch;
237*38fd1498Szrj       }
238*38fd1498Szrj 
239*38fd1498Szrj       _StrTransT
240*38fd1498Szrj       _M_transform(_CharT __ch) const
241*38fd1498Szrj       {
242*38fd1498Szrj 	_StrTransT __str(1, __ch);
243*38fd1498Szrj 	return _M_traits.transform(__str.begin(), __str.end());
244*38fd1498Szrj       }
245*38fd1498Szrj 
246*38fd1498Szrj       // See LWG 523. It's not efficiently implementable when _TraitsT is not
247*38fd1498Szrj       // std::regex_traits<>, and __collate is true. See specializations for
248*38fd1498Szrj       // implementations of other cases.
249*38fd1498Szrj       bool
250*38fd1498Szrj       _M_match_range(const _StrTransT& __first, const _StrTransT& __last,
251*38fd1498Szrj 		     const _StrTransT& __s) const
252*38fd1498Szrj       { return __first <= __s && __s <= __last; }
253*38fd1498Szrj 
254*38fd1498Szrj     protected:
255*38fd1498Szrj       bool _M_in_range_icase(_CharT __first, _CharT __last, _CharT __ch) const
256*38fd1498Szrj       {
257*38fd1498Szrj 	typedef std::ctype<_CharT> __ctype_type;
258*38fd1498Szrj 	const auto& __fctyp = use_facet<__ctype_type>(this->_M_traits.getloc());
259*38fd1498Szrj 	auto __lower = __fctyp.tolower(__ch);
260*38fd1498Szrj 	auto __upper = __fctyp.toupper(__ch);
261*38fd1498Szrj 	return (__first <= __lower && __lower <= __last)
262*38fd1498Szrj 	  || (__first <= __upper && __upper <= __last);
263*38fd1498Szrj       }
264*38fd1498Szrj 
265*38fd1498Szrj       const _TraitsT& _M_traits;
266*38fd1498Szrj     };
267*38fd1498Szrj 
268*38fd1498Szrj   template<typename _TraitsT, bool __icase, bool __collate>
269*38fd1498Szrj     class _RegexTranslator
270*38fd1498Szrj     : public _RegexTranslatorBase<_TraitsT, __icase, __collate>
271*38fd1498Szrj     {
272*38fd1498Szrj     public:
273*38fd1498Szrj       typedef _RegexTranslatorBase<_TraitsT, __icase, __collate> _Base;
274*38fd1498Szrj       using _Base::_Base;
275*38fd1498Szrj     };
276*38fd1498Szrj 
277*38fd1498Szrj   template<typename _TraitsT, bool __icase>
278*38fd1498Szrj     class _RegexTranslator<_TraitsT, __icase, false>
279*38fd1498Szrj     : public _RegexTranslatorBase<_TraitsT, __icase, false>
280*38fd1498Szrj     {
281*38fd1498Szrj     public:
282*38fd1498Szrj       typedef _RegexTranslatorBase<_TraitsT, __icase, false> _Base;
283*38fd1498Szrj       typedef typename _Base::_CharT _CharT;
284*38fd1498Szrj       typedef _CharT _StrTransT;
285*38fd1498Szrj 
286*38fd1498Szrj       using _Base::_Base;
287*38fd1498Szrj 
288*38fd1498Szrj       _StrTransT
289*38fd1498Szrj       _M_transform(_CharT __ch) const
290*38fd1498Szrj       { return __ch; }
291*38fd1498Szrj 
292*38fd1498Szrj       bool
293*38fd1498Szrj       _M_match_range(_CharT __first, _CharT __last, _CharT __ch) const
294*38fd1498Szrj       {
295*38fd1498Szrj 	if (!__icase)
296*38fd1498Szrj 	  return __first <= __ch && __ch <= __last;
297*38fd1498Szrj 	return this->_M_in_range_icase(__first, __last, __ch);
298*38fd1498Szrj       }
299*38fd1498Szrj     };
300*38fd1498Szrj 
301*38fd1498Szrj   template<typename _CharType>
302*38fd1498Szrj     class _RegexTranslator<std::regex_traits<_CharType>, true, true>
303*38fd1498Szrj     : public _RegexTranslatorBase<std::regex_traits<_CharType>, true, true>
304*38fd1498Szrj     {
305*38fd1498Szrj     public:
306*38fd1498Szrj       typedef _RegexTranslatorBase<std::regex_traits<_CharType>, true, true>
307*38fd1498Szrj 	_Base;
308*38fd1498Szrj       typedef typename _Base::_CharT _CharT;
309*38fd1498Szrj       typedef typename _Base::_StrTransT _StrTransT;
310*38fd1498Szrj 
311*38fd1498Szrj       using _Base::_Base;
312*38fd1498Szrj 
313*38fd1498Szrj       bool
314*38fd1498Szrj       _M_match_range(const _StrTransT& __first, const _StrTransT& __last,
315*38fd1498Szrj 		     const _StrTransT& __str) const
316*38fd1498Szrj       {
317*38fd1498Szrj 	__glibcxx_assert(__first.size() == 1);
318*38fd1498Szrj 	__glibcxx_assert(__last.size() == 1);
319*38fd1498Szrj 	__glibcxx_assert(__str.size() == 1);
320*38fd1498Szrj 	return this->_M_in_range_icase(__first[0], __last[0], __str[0]);
321*38fd1498Szrj       }
322*38fd1498Szrj     };
323*38fd1498Szrj 
324*38fd1498Szrj   template<typename _TraitsT>
325*38fd1498Szrj     class _RegexTranslator<_TraitsT, false, false>
326*38fd1498Szrj     {
327*38fd1498Szrj     public:
328*38fd1498Szrj       typedef typename _TraitsT::char_type _CharT;
329*38fd1498Szrj       typedef _CharT                       _StrTransT;
330*38fd1498Szrj 
331*38fd1498Szrj       explicit
332*38fd1498Szrj       _RegexTranslator(const _TraitsT&)
333*38fd1498Szrj       { }
334*38fd1498Szrj 
335*38fd1498Szrj       _CharT
336*38fd1498Szrj       _M_translate(_CharT __ch) const
337*38fd1498Szrj       { return __ch; }
338*38fd1498Szrj 
339*38fd1498Szrj       _StrTransT
340*38fd1498Szrj       _M_transform(_CharT __ch) const
341*38fd1498Szrj       { return __ch; }
342*38fd1498Szrj 
343*38fd1498Szrj       bool
344*38fd1498Szrj       _M_match_range(_CharT __first, _CharT __last, _CharT __ch) const
345*38fd1498Szrj       { return __first <= __ch && __ch <= __last; }
346*38fd1498Szrj     };
347*38fd1498Szrj 
348*38fd1498Szrj   template<typename _TraitsT, bool __is_ecma, bool __icase, bool __collate>
349*38fd1498Szrj     struct _AnyMatcher;
350*38fd1498Szrj 
351*38fd1498Szrj   template<typename _TraitsT, bool __icase, bool __collate>
352*38fd1498Szrj     struct _AnyMatcher<_TraitsT, false, __icase, __collate>
353*38fd1498Szrj     {
354*38fd1498Szrj       typedef _RegexTranslator<_TraitsT, __icase, __collate> _TransT;
355*38fd1498Szrj       typedef typename _TransT::_CharT                       _CharT;
356*38fd1498Szrj 
357*38fd1498Szrj       explicit
358*38fd1498Szrj       _AnyMatcher(const _TraitsT& __traits)
359*38fd1498Szrj       : _M_translator(__traits)
360*38fd1498Szrj       { }
361*38fd1498Szrj 
362*38fd1498Szrj       bool
363*38fd1498Szrj       operator()(_CharT __ch) const
364*38fd1498Szrj       {
365*38fd1498Szrj 	static auto __nul = _M_translator._M_translate('\0');
366*38fd1498Szrj 	return _M_translator._M_translate(__ch) != __nul;
367*38fd1498Szrj       }
368*38fd1498Szrj 
369*38fd1498Szrj       _TransT _M_translator;
370*38fd1498Szrj     };
371*38fd1498Szrj 
372*38fd1498Szrj   template<typename _TraitsT, bool __icase, bool __collate>
373*38fd1498Szrj     struct _AnyMatcher<_TraitsT, true, __icase, __collate>
374*38fd1498Szrj     {
375*38fd1498Szrj       typedef _RegexTranslator<_TraitsT, __icase, __collate> _TransT;
376*38fd1498Szrj       typedef typename _TransT::_CharT                       _CharT;
377*38fd1498Szrj 
378*38fd1498Szrj       explicit
379*38fd1498Szrj       _AnyMatcher(const _TraitsT& __traits)
380*38fd1498Szrj       : _M_translator(__traits)
381*38fd1498Szrj       { }
382*38fd1498Szrj 
383*38fd1498Szrj       bool
384*38fd1498Szrj       operator()(_CharT __ch) const
385*38fd1498Szrj       { return _M_apply(__ch, typename is_same<_CharT, char>::type()); }
386*38fd1498Szrj 
387*38fd1498Szrj       bool
388*38fd1498Szrj       _M_apply(_CharT __ch, true_type) const
389*38fd1498Szrj       {
390*38fd1498Szrj 	auto __c = _M_translator._M_translate(__ch);
391*38fd1498Szrj 	auto __n = _M_translator._M_translate('\n');
392*38fd1498Szrj 	auto __r = _M_translator._M_translate('\r');
393*38fd1498Szrj 	return __c != __n && __c != __r;
394*38fd1498Szrj       }
395*38fd1498Szrj 
396*38fd1498Szrj       bool
397*38fd1498Szrj       _M_apply(_CharT __ch, false_type) const
398*38fd1498Szrj       {
399*38fd1498Szrj 	auto __c = _M_translator._M_translate(__ch);
400*38fd1498Szrj 	auto __n = _M_translator._M_translate('\n');
401*38fd1498Szrj 	auto __r = _M_translator._M_translate('\r');
402*38fd1498Szrj 	auto __u2028 = _M_translator._M_translate(u'\u2028');
403*38fd1498Szrj 	auto __u2029 = _M_translator._M_translate(u'\u2029');
404*38fd1498Szrj 	return __c != __n && __c != __r && __c != __u2028 && __c != __u2029;
405*38fd1498Szrj       }
406*38fd1498Szrj 
407*38fd1498Szrj       _TransT _M_translator;
408*38fd1498Szrj     };
409*38fd1498Szrj 
410*38fd1498Szrj   template<typename _TraitsT, bool __icase, bool __collate>
411*38fd1498Szrj     struct _CharMatcher
412*38fd1498Szrj     {
413*38fd1498Szrj       typedef _RegexTranslator<_TraitsT, __icase, __collate> _TransT;
414*38fd1498Szrj       typedef typename _TransT::_CharT                       _CharT;
415*38fd1498Szrj 
416*38fd1498Szrj       _CharMatcher(_CharT __ch, const _TraitsT& __traits)
417*38fd1498Szrj       : _M_translator(__traits), _M_ch(_M_translator._M_translate(__ch))
418*38fd1498Szrj       { }
419*38fd1498Szrj 
420*38fd1498Szrj       bool
421*38fd1498Szrj       operator()(_CharT __ch) const
422*38fd1498Szrj       { return _M_ch == _M_translator._M_translate(__ch); }
423*38fd1498Szrj 
424*38fd1498Szrj       _TransT _M_translator;
425*38fd1498Szrj       _CharT  _M_ch;
426*38fd1498Szrj     };
427*38fd1498Szrj 
428*38fd1498Szrj   /// Matches a character range (bracket expression)
429*38fd1498Szrj   template<typename _TraitsT, bool __icase, bool __collate>
430*38fd1498Szrj     struct _BracketMatcher
431*38fd1498Szrj     {
432*38fd1498Szrj     public:
433*38fd1498Szrj       typedef _RegexTranslator<_TraitsT, __icase, __collate> _TransT;
434*38fd1498Szrj       typedef typename _TransT::_CharT                       _CharT;
435*38fd1498Szrj       typedef typename _TransT::_StrTransT                   _StrTransT;
436*38fd1498Szrj       typedef typename _TraitsT::string_type                 _StringT;
437*38fd1498Szrj       typedef typename _TraitsT::char_class_type             _CharClassT;
438*38fd1498Szrj 
439*38fd1498Szrj     public:
440*38fd1498Szrj       _BracketMatcher(bool __is_non_matching,
441*38fd1498Szrj 		      const _TraitsT& __traits)
442*38fd1498Szrj       : _M_class_set(0), _M_translator(__traits), _M_traits(__traits),
443*38fd1498Szrj       _M_is_non_matching(__is_non_matching)
444*38fd1498Szrj       { }
445*38fd1498Szrj 
446*38fd1498Szrj       bool
447*38fd1498Szrj       operator()(_CharT __ch) const
448*38fd1498Szrj       {
449*38fd1498Szrj 	_GLIBCXX_DEBUG_ASSERT(_M_is_ready);
450*38fd1498Szrj 	return _M_apply(__ch, _UseCache());
451*38fd1498Szrj       }
452*38fd1498Szrj 
453*38fd1498Szrj       void
454*38fd1498Szrj       _M_add_char(_CharT __c)
455*38fd1498Szrj       {
456*38fd1498Szrj 	_M_char_set.push_back(_M_translator._M_translate(__c));
457*38fd1498Szrj 	_GLIBCXX_DEBUG_ONLY(_M_is_ready = false);
458*38fd1498Szrj       }
459*38fd1498Szrj 
460*38fd1498Szrj       _StringT
461*38fd1498Szrj       _M_add_collate_element(const _StringT& __s)
462*38fd1498Szrj       {
463*38fd1498Szrj 	auto __st = _M_traits.lookup_collatename(__s.data(),
464*38fd1498Szrj 						 __s.data() + __s.size());
465*38fd1498Szrj 	if (__st.empty())
466*38fd1498Szrj 	  __throw_regex_error(regex_constants::error_collate,
467*38fd1498Szrj 			      "Invalid collate element.");
468*38fd1498Szrj 	_M_char_set.push_back(_M_translator._M_translate(__st[0]));
469*38fd1498Szrj 	_GLIBCXX_DEBUG_ONLY(_M_is_ready = false);
470*38fd1498Szrj 	return __st;
471*38fd1498Szrj       }
472*38fd1498Szrj 
473*38fd1498Szrj       void
474*38fd1498Szrj       _M_add_equivalence_class(const _StringT& __s)
475*38fd1498Szrj       {
476*38fd1498Szrj 	auto __st = _M_traits.lookup_collatename(__s.data(),
477*38fd1498Szrj 						 __s.data() + __s.size());
478*38fd1498Szrj 	if (__st.empty())
479*38fd1498Szrj 	  __throw_regex_error(regex_constants::error_collate,
480*38fd1498Szrj 			      "Invalid equivalence class.");
481*38fd1498Szrj 	__st = _M_traits.transform_primary(__st.data(),
482*38fd1498Szrj 					   __st.data() + __st.size());
483*38fd1498Szrj 	_M_equiv_set.push_back(__st);
484*38fd1498Szrj 	_GLIBCXX_DEBUG_ONLY(_M_is_ready = false);
485*38fd1498Szrj       }
486*38fd1498Szrj 
487*38fd1498Szrj       // __neg should be true for \D, \S and \W only.
488*38fd1498Szrj       void
489*38fd1498Szrj       _M_add_character_class(const _StringT& __s, bool __neg)
490*38fd1498Szrj       {
491*38fd1498Szrj 	auto __mask = _M_traits.lookup_classname(__s.data(),
492*38fd1498Szrj 						 __s.data() + __s.size(),
493*38fd1498Szrj 						 __icase);
494*38fd1498Szrj 	if (__mask == 0)
495*38fd1498Szrj 	  __throw_regex_error(regex_constants::error_collate,
496*38fd1498Szrj 			      "Invalid character class.");
497*38fd1498Szrj 	if (!__neg)
498*38fd1498Szrj 	  _M_class_set |= __mask;
499*38fd1498Szrj 	else
500*38fd1498Szrj 	  _M_neg_class_set.push_back(__mask);
501*38fd1498Szrj 	_GLIBCXX_DEBUG_ONLY(_M_is_ready = false);
502*38fd1498Szrj       }
503*38fd1498Szrj 
504*38fd1498Szrj       void
505*38fd1498Szrj       _M_make_range(_CharT __l, _CharT __r)
506*38fd1498Szrj       {
507*38fd1498Szrj 	if (__l > __r)
508*38fd1498Szrj 	  __throw_regex_error(regex_constants::error_range,
509*38fd1498Szrj 			      "Invalid range in bracket expression.");
510*38fd1498Szrj 	_M_range_set.push_back(make_pair(_M_translator._M_transform(__l),
511*38fd1498Szrj 					 _M_translator._M_transform(__r)));
512*38fd1498Szrj 	_GLIBCXX_DEBUG_ONLY(_M_is_ready = false);
513*38fd1498Szrj       }
514*38fd1498Szrj 
515*38fd1498Szrj       void
516*38fd1498Szrj       _M_ready()
517*38fd1498Szrj       {
518*38fd1498Szrj 	std::sort(_M_char_set.begin(), _M_char_set.end());
519*38fd1498Szrj 	auto __end = std::unique(_M_char_set.begin(), _M_char_set.end());
520*38fd1498Szrj 	_M_char_set.erase(__end, _M_char_set.end());
521*38fd1498Szrj 	_M_make_cache(_UseCache());
522*38fd1498Szrj 	_GLIBCXX_DEBUG_ONLY(_M_is_ready = true);
523*38fd1498Szrj       }
524*38fd1498Szrj 
525*38fd1498Szrj     private:
526*38fd1498Szrj       // Currently we only use the cache for char
527*38fd1498Szrj       typedef typename std::is_same<_CharT, char>::type _UseCache;
528*38fd1498Szrj 
529*38fd1498Szrj       static constexpr size_t
530*38fd1498Szrj       _S_cache_size()
531*38fd1498Szrj       {
532*38fd1498Szrj 	return 1ul << (sizeof(_CharT) * __CHAR_BIT__ * int(_UseCache::value));
533*38fd1498Szrj       }
534*38fd1498Szrj 
535*38fd1498Szrj       struct _Dummy { };
536*38fd1498Szrj       typedef typename std::conditional<_UseCache::value,
537*38fd1498Szrj 					std::bitset<_S_cache_size()>,
538*38fd1498Szrj 					_Dummy>::type _CacheT;
539*38fd1498Szrj       typedef typename std::make_unsigned<_CharT>::type _UnsignedCharT;
540*38fd1498Szrj 
541*38fd1498Szrj       bool
542*38fd1498Szrj       _M_apply(_CharT __ch, false_type) const;
543*38fd1498Szrj 
544*38fd1498Szrj       bool
545*38fd1498Szrj       _M_apply(_CharT __ch, true_type) const
546*38fd1498Szrj       { return _M_cache[static_cast<_UnsignedCharT>(__ch)]; }
547*38fd1498Szrj 
548*38fd1498Szrj       void
549*38fd1498Szrj       _M_make_cache(true_type)
550*38fd1498Szrj       {
551*38fd1498Szrj 	for (unsigned __i = 0; __i < _M_cache.size(); __i++)
552*38fd1498Szrj 	  _M_cache[__i] = _M_apply(static_cast<_CharT>(__i), false_type());
553*38fd1498Szrj       }
554*38fd1498Szrj 
555*38fd1498Szrj       void
556*38fd1498Szrj       _M_make_cache(false_type)
557*38fd1498Szrj       { }
558*38fd1498Szrj 
559*38fd1498Szrj     private:
560*38fd1498Szrj       std::vector<_CharT>                       _M_char_set;
561*38fd1498Szrj       std::vector<_StringT>                     _M_equiv_set;
562*38fd1498Szrj       std::vector<pair<_StrTransT, _StrTransT>> _M_range_set;
563*38fd1498Szrj       std::vector<_CharClassT>                  _M_neg_class_set;
564*38fd1498Szrj       _CharClassT                               _M_class_set;
565*38fd1498Szrj       _TransT                                   _M_translator;
566*38fd1498Szrj       const _TraitsT&                           _M_traits;
567*38fd1498Szrj       bool                                      _M_is_non_matching;
568*38fd1498Szrj       _CacheT					_M_cache;
569*38fd1498Szrj #ifdef _GLIBCXX_DEBUG
570*38fd1498Szrj       bool                                      _M_is_ready = false;
571*38fd1498Szrj #endif
572*38fd1498Szrj     };
573*38fd1498Szrj 
574*38fd1498Szrj  //@} regex-detail
575*38fd1498Szrj } // namespace __detail
576*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
577*38fd1498Szrj } // namespace std
578*38fd1498Szrj 
579*38fd1498Szrj #include <bits/regex_compiler.tcc>
580