1 // class template regex -*- C++ -*-
3 // Copyright (C) 2013-2017 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
26 * @file bits/regex.tcc
27 * This is an internal header file, included by other library headers.
28 * Do not attempt to use it directly. @headername{regex}
31 namespace std _GLIBCXX_VISIBILITY(default)
35 _GLIBCXX_BEGIN_NAMESPACE_VERSION
37 // Result of merging regex_match and regex_search.
39 // __policy now can be _S_auto (auto dispatch) and _S_alternate (use
40 // the other one if possible, for test purpose).
42 // That __match_mode is true means regex_match, else regex_search.
43 template<typename _BiIter, typename _Alloc,
44 typename _CharT, typename _TraitsT,
45 _RegexExecutorPolicy __policy,
48 __regex_algo_impl(_BiIter __s,
50 match_results<_BiIter, _Alloc>& __m,
51 const basic_regex<_CharT, _TraitsT>& __re,
52 regex_constants::match_flag_type __flags)
54 if (__re._M_automaton == nullptr)
57 typename match_results<_BiIter, _Alloc>::_Base_type& __res = __m;
59 __m._M_resize(__re._M_automaton->_M_sub_count());
60 for (auto& __it : __res)
64 if ((__re.flags() & regex_constants::__polynomial)
65 || (__policy == _RegexExecutorPolicy::_S_alternate
66 && !__re._M_automaton->_M_has_backref))
68 _Executor<_BiIter, _Alloc, _TraitsT, false>
69 __executor(__s, __e, __m, __re, __flags);
71 __ret = __executor._M_match();
73 __ret = __executor._M_search();
77 _Executor<_BiIter, _Alloc, _TraitsT, true>
78 __executor(__s, __e, __m, __re, __flags);
80 __ret = __executor._M_match();
82 __ret = __executor._M_search();
86 for (auto& __it : __res)
88 __it.first = __it.second = __e;
89 auto& __pre = __m._M_prefix();
90 auto& __suf = __m._M_suffix();
93 __pre.matched = false;
96 __suf.matched = false;
103 __pre.second = __res[0].first;
104 __pre.matched = (__pre.first != __pre.second);
105 __suf.first = __res[0].second;
107 __suf.matched = (__suf.first != __suf.second);
113 for (auto& __it : __res)
115 __it.matched = false;
116 __it.first = __it.second = __e;
122 _GLIBCXX_END_NAMESPACE_VERSION
125 _GLIBCXX_BEGIN_NAMESPACE_VERSION
127 template<typename _Ch_type>
128 template<typename _Fwd_iter>
129 typename regex_traits<_Ch_type>::string_type
130 regex_traits<_Ch_type>::
131 lookup_collatename(_Fwd_iter __first, _Fwd_iter __last) const
133 typedef std::ctype<char_type> __ctype_type;
134 const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
136 static const char* __collatenames[] =
229 "left-square-bracket",
231 "right-square-bracket",
261 "left-curly-bracket",
263 "right-curly-bracket",
269 for (; __first != __last; ++__first)
270 __s += __fctyp.narrow(*__first, 0);
272 for (const auto& __it : __collatenames)
274 return string_type(1, __fctyp.widen(
275 static_cast<char>(&__it - __collatenames)));
277 // TODO Add digraph support:
278 // http://boost.sourceforge.net/libs/regex/doc/collating_names.html
280 return string_type();
283 template<typename _Ch_type>
284 template<typename _Fwd_iter>
285 typename regex_traits<_Ch_type>::char_class_type
286 regex_traits<_Ch_type>::
287 lookup_classname(_Fwd_iter __first, _Fwd_iter __last, bool __icase) const
289 typedef std::ctype<char_type> __ctype_type;
290 const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
292 // Mappings from class name to class mask.
293 static const pair<const char*, char_class_type> __classnames[] =
295 {"d", ctype_base::digit},
296 {"w", {ctype_base::alnum, _RegexMask::_S_under}},
297 {"s", ctype_base::space},
298 {"alnum", ctype_base::alnum},
299 {"alpha", ctype_base::alpha},
300 {"blank", ctype_base::blank},
301 {"cntrl", ctype_base::cntrl},
302 {"digit", ctype_base::digit},
303 {"graph", ctype_base::graph},
304 {"lower", ctype_base::lower},
305 {"print", ctype_base::print},
306 {"punct", ctype_base::punct},
307 {"space", ctype_base::space},
308 {"upper", ctype_base::upper},
309 {"xdigit", ctype_base::xdigit},
313 for (; __first != __last; ++__first)
314 __s += __fctyp.narrow(__fctyp.tolower(*__first), 0);
316 for (const auto& __it : __classnames)
317 if (__s == __it.first)
321 & (ctype_base::lower | ctype_base::upper)) != 0))
322 return ctype_base::alpha;
328 template<typename _Ch_type>
330 regex_traits<_Ch_type>::
331 isctype(_Ch_type __c, char_class_type __f) const
333 typedef std::ctype<char_type> __ctype_type;
334 const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
336 return __fctyp.is(__f._M_base, __c)
338 || ((__f._M_extended & _RegexMask::_S_under)
339 && __c == __fctyp.widen('_'));
342 template<typename _Ch_type>
344 regex_traits<_Ch_type>::
345 value(_Ch_type __ch, int __radix) const
347 std::basic_istringstream<char_type> __is(string_type(1, __ch));
351 else if (__radix == 16)
354 return __is.fail() ? -1 : __v;
357 template<typename _Bi_iter, typename _Alloc>
358 template<typename _Out_iter>
359 _Out_iter match_results<_Bi_iter, _Alloc>::
360 format(_Out_iter __out,
361 const match_results<_Bi_iter, _Alloc>::char_type* __fmt_first,
362 const match_results<_Bi_iter, _Alloc>::char_type* __fmt_last,
363 match_flag_type __flags) const
365 __glibcxx_assert( ready() );
366 regex_traits<char_type> __traits;
367 typedef std::ctype<char_type> __ctype_type;
369 __fctyp(use_facet<__ctype_type>(__traits.getloc()));
371 auto __output = [&](size_t __idx)
373 auto& __sub = (*this)[__idx];
375 __out = std::copy(__sub.first, __sub.second, __out);
378 if (__flags & regex_constants::format_sed)
380 for (; __fmt_first != __fmt_last;)
381 if (*__fmt_first == '&')
386 else if (*__fmt_first == '\\')
388 if (++__fmt_first != __fmt_last
389 && __fctyp.is(__ctype_type::digit, *__fmt_first))
390 __output(__traits.value(*__fmt_first++, 10));
395 *__out++ = *__fmt_first++;
401 auto __next = std::find(__fmt_first, __fmt_last, '$');
402 if (__next == __fmt_last)
405 __out = std::copy(__fmt_first, __next, __out);
407 auto __eat = [&](char __ch) -> bool
417 if (++__next == __fmt_last)
425 auto& __sub = _M_prefix();
427 __out = std::copy(__sub.first, __sub.second, __out);
429 else if (__eat('\''))
431 auto& __sub = _M_suffix();
433 __out = std::copy(__sub.first, __sub.second, __out);
435 else if (__fctyp.is(__ctype_type::digit, *__next))
437 long __num = __traits.value(*__next, 10);
438 if (++__next != __fmt_last
439 && __fctyp.is(__ctype_type::digit, *__next))
442 __num += __traits.value(*__next++, 10);
444 if (0 <= __num && __num < this->size())
449 __fmt_first = __next;
451 __out = std::copy(__fmt_first, __fmt_last, __out);
456 template<typename _Out_iter, typename _Bi_iter,
457 typename _Rx_traits, typename _Ch_type>
459 regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
460 const basic_regex<_Ch_type, _Rx_traits>& __e,
461 const _Ch_type* __fmt,
462 regex_constants::match_flag_type __flags)
464 typedef regex_iterator<_Bi_iter, _Ch_type, _Rx_traits> _IterT;
465 _IterT __i(__first, __last, __e, __flags);
469 if (!(__flags & regex_constants::format_no_copy))
470 __out = std::copy(__first, __last, __out);
474 sub_match<_Bi_iter> __last;
475 auto __len = char_traits<_Ch_type>::length(__fmt);
476 for (; __i != __end; ++__i)
478 if (!(__flags & regex_constants::format_no_copy))
479 __out = std::copy(__i->prefix().first, __i->prefix().second,
481 __out = __i->format(__out, __fmt, __fmt + __len, __flags);
482 __last = __i->suffix();
483 if (__flags & regex_constants::format_first_only)
486 if (!(__flags & regex_constants::format_no_copy))
487 __out = std::copy(__last.first, __last.second, __out);
492 template<typename _Bi_iter,
496 regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
497 operator==(const regex_iterator& __rhs) const
499 if (_M_pregex == nullptr && __rhs._M_pregex == nullptr)
501 return _M_pregex == __rhs._M_pregex
502 && _M_begin == __rhs._M_begin
503 && _M_end == __rhs._M_end
504 && _M_flags == __rhs._M_flags
505 && _M_match[0] == __rhs._M_match[0];
508 template<typename _Bi_iter,
511 regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
512 regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
515 // In all cases in which the call to regex_search returns true,
516 // match.prefix().first shall be equal to the previous value of
517 // match[0].second, and for each index i in the half-open range
518 // [0, match.size()) for which match[i].matched is true,
519 // match[i].position() shall return distance(begin, match[i].first).
521 if (_M_match[0].matched)
523 auto __start = _M_match[0].second;
524 auto __prefix_first = _M_match[0].second;
525 if (_M_match[0].first == _M_match[0].second)
527 if (__start == _M_end)
534 if (regex_search(__start, _M_end, _M_match, *_M_pregex,
536 | regex_constants::match_not_null
537 | regex_constants::match_continuous))
539 __glibcxx_assert(_M_match[0].matched);
540 auto& __prefix = _M_match._M_prefix();
541 __prefix.first = __prefix_first;
542 __prefix.matched = __prefix.first != __prefix.second;
544 _M_match._M_begin = _M_begin;
551 _M_flags |= regex_constants::match_prev_avail;
552 if (regex_search(__start, _M_end, _M_match, *_M_pregex, _M_flags))
554 __glibcxx_assert(_M_match[0].matched);
555 auto& __prefix = _M_match._M_prefix();
556 __prefix.first = __prefix_first;
557 __prefix.matched = __prefix.first != __prefix.second;
559 _M_match._M_begin = _M_begin;
567 template<typename _Bi_iter,
570 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
571 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
572 operator=(const regex_token_iterator& __rhs)
574 _M_position = __rhs._M_position;
575 _M_subs = __rhs._M_subs;
577 _M_suffix = __rhs._M_suffix;
578 _M_has_m1 = __rhs._M_has_m1;
579 _M_normalize_result();
583 template<typename _Bi_iter,
587 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
588 operator==(const regex_token_iterator& __rhs) const
590 if (_M_end_of_seq() && __rhs._M_end_of_seq())
592 if (_M_suffix.matched && __rhs._M_suffix.matched
593 && _M_suffix == __rhs._M_suffix)
595 if (_M_end_of_seq() || _M_suffix.matched
596 || __rhs._M_end_of_seq() || __rhs._M_suffix.matched)
598 return _M_position == __rhs._M_position
599 && _M_n == __rhs._M_n
600 && _M_subs == __rhs._M_subs;
603 template<typename _Bi_iter,
606 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
607 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
610 _Position __prev = _M_position;
611 if (_M_suffix.matched)
612 *this = regex_token_iterator();
613 else if (_M_n + 1 < _M_subs.size())
616 _M_result = &_M_current_match();
622 if (_M_position != _Position())
623 _M_result = &_M_current_match();
624 else if (_M_has_m1 && __prev->suffix().length() != 0)
626 _M_suffix.matched = true;
627 _M_suffix.first = __prev->suffix().first;
628 _M_suffix.second = __prev->suffix().second;
629 _M_result = &_M_suffix;
632 *this = regex_token_iterator();
637 template<typename _Bi_iter,
641 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
642 _M_init(_Bi_iter __a, _Bi_iter __b)
645 for (auto __it : _M_subs)
651 if (_M_position != _Position())
652 _M_result = &_M_current_match();
655 _M_suffix.matched = true;
656 _M_suffix.first = __a;
657 _M_suffix.second = __b;
658 _M_result = &_M_suffix;
664 _GLIBCXX_END_NAMESPACE_VERSION