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