1 // class template regex -*- C++ -*-
3 // Copyright (C) 2013 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)
33 _GLIBCXX_BEGIN_NAMESPACE_VERSION
37 _GLIBCXX_BEGIN_NAMESPACE_VERSION
39 // Result of merging regex_match and regex_search.
41 // __policy now can be _S_auto(auto dispatch by checking back-references)
42 // and _S_force_dfs(just use _DFSExecutor).
44 // That __match_mode is true means regex_match, else regex_search.
45 template<typename _BiIter, typename _Alloc,
46 typename _CharT, typename _TraitsT,
47 _RegexExecutorPolicy __policy,
50 __regex_algo_impl(_BiIter __s,
52 match_results<_BiIter, _Alloc>& __m,
53 const basic_regex<_CharT, _TraitsT>& __re,
54 regex_constants::match_flag_type __flags)
56 if (__re._M_automaton == nullptr)
59 typename match_results<_BiIter, _Alloc>::_Base_type& __res = __m;
60 __res.resize(__re._M_automaton->_M_sub_count() + 2);
61 for (auto& __it : __res)
64 auto __executor = __get_executor<_BiIter, _Alloc, _CharT, _TraitsT,
65 __policy>(__s, __e, __res, __re, __flags);
69 __ret = __executor->_M_match();
71 __ret = __executor->_M_search();
74 for (auto __it : __res)
76 __it.first = __it.second = __e;
77 auto& __pre = __res[__res.size()-2];
78 auto& __suf = __res[__res.size()-1];
81 __pre.matched = false;
84 __suf.matched = false;
91 __pre.second = __res[0].first;
92 __pre.matched = (__pre.first != __pre.second);
93 __suf.first = __res[0].second;
95 __suf.matched = (__suf.first != __suf.second);
97 if (__re.flags() & regex_constants::nosubs)
103 _GLIBCXX_END_NAMESPACE_VERSION
106 template<typename _Ch_type>
107 template<typename _Fwd_iter>
108 typename regex_traits<_Ch_type>::string_type
109 regex_traits<_Ch_type>::
110 lookup_collatename(_Fwd_iter __first, _Fwd_iter __last) const
112 typedef std::ctype<char_type> __ctype_type;
113 const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
115 static const char* __collatenames[] =
208 "left-square-bracket",
210 "right-square-bracket",
240 "left-curly-bracket",
242 "right-curly-bracket",
249 //static const char* __digraphs[] =
275 std::string __s(__last - __first, '?');
276 __fctyp.narrow(__first, __last, '?', &*__s.begin());
278 for (unsigned int __i = 0; *__collatenames[__i]; __i++)
279 if (__s == __collatenames[__i])
280 return string_type(1, __fctyp.widen(static_cast<char>(__i)));
282 //for (unsigned int __i = 0; *__digraphs[__i]; __i++)
284 // const char* __now = __digraphs[__i];
287 // string_type ret(__s.size(), __fctyp.widen('?'));
288 // __fctyp.widen(__now, __now + 2/* ouch */, &*ret.begin());
292 return string_type();
295 template<typename _Ch_type>
296 template<typename _Fwd_iter>
297 typename regex_traits<_Ch_type>::char_class_type
298 regex_traits<_Ch_type>::
299 lookup_classname(_Fwd_iter __first, _Fwd_iter __last, bool __icase) const
301 typedef std::ctype<char_type> __ctype_type;
302 typedef std::ctype<char> __cctype_type;
303 typedef const pair<const char*, char_class_type> _ClassnameEntry;
304 const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
305 const __cctype_type& __cctyp(use_facet<__cctype_type>(_M_locale));
307 static _ClassnameEntry __classnames[] =
309 {"d", ctype_base::digit},
310 {"w", {ctype_base::alnum, _RegexMask::_S_under}},
311 {"s", ctype_base::space},
312 {"alnum", ctype_base::alnum},
313 {"alpha", ctype_base::alpha},
314 {"blank", {0, _RegexMask::_S_blank}},
315 {"cntrl", ctype_base::cntrl},
316 {"digit", ctype_base::digit},
317 {"graph", ctype_base::graph},
318 {"lower", ctype_base::lower},
319 {"print", ctype_base::print},
320 {"punct", ctype_base::punct},
321 {"space", ctype_base::space},
322 {"upper", ctype_base::upper},
323 {"xdigit", ctype_base::xdigit},
326 std::string __s(__last - __first, '?');
327 __fctyp.narrow(__first, __last, '?', &__s[0]);
328 __cctyp.tolower(&*__s.begin(), &*__s.begin() + __s.size());
329 for (_ClassnameEntry* __it = __classnames;
330 __it < *(&__classnames + 1);
333 if (__s == __it->first)
337 & (ctype_base::lower | ctype_base::upper)) != 0))
338 return ctype_base::alpha;
345 template<typename _Ch_type>
347 regex_traits<_Ch_type>::
348 isctype(_Ch_type __c, char_class_type __f) const
350 typedef std::ctype<char_type> __ctype_type;
351 const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
353 return __fctyp.is(__f._M_base, __c)
355 || ((__f._M_extended & _RegexMask::_S_under)
356 && __c == __fctyp.widen('_'))
358 || ((__f._M_extended & _RegexMask::_S_blank)
359 && (__c == __fctyp.widen(' ')
360 || __c == __fctyp.widen('\t')));
363 template<typename _Ch_type>
365 regex_traits<_Ch_type>::
366 value(_Ch_type __ch, int __radix) const
368 std::basic_istringstream<char_type> __is(string_type(1, __ch));
372 else if (__radix == 16)
375 return __is.fail() ? -1 : __v;
378 template<typename _Bi_iter, typename _Alloc>
379 template<typename _Out_iter>
380 _Out_iter match_results<_Bi_iter, _Alloc>::
381 format(_Out_iter __out,
382 const match_results<_Bi_iter, _Alloc>::char_type* __fmt_first,
383 const match_results<_Bi_iter, _Alloc>::char_type* __fmt_last,
384 match_flag_type __flags) const
386 _GLIBCXX_DEBUG_ASSERT( ready() );
387 regex_traits<char_type> __traits;
388 typedef std::ctype<char_type> __ctype_type;
390 __fctyp(use_facet<__ctype_type>(__traits.getloc()));
392 auto __output = [&](size_t __idx)
394 auto& __sub = _Base_type::operator[](__idx);
396 std::copy(__sub.first, __sub.second, __out);
399 if (__flags & regex_constants::format_sed)
401 for (; __fmt_first != __fmt_last;)
402 if (*__fmt_first == '&')
407 else if (*__fmt_first == '\\')
409 if (++__fmt_first != __fmt_last
410 && __fctyp.is(__ctype_type::digit, *__fmt_first))
411 __output(__traits.value(*__fmt_first++, 10));
416 *__out++ = *__fmt_first++;
422 auto __next = std::find(__fmt_first, __fmt_last, '$');
423 if (__next == __fmt_last)
426 std::copy(__fmt_first, __next, __out);
428 auto __eat = [&](char __ch) -> bool
438 if (++__next == __fmt_last)
445 __output(_Base_type::size()-2);
446 else if (__eat('\''))
447 __output(_Base_type::size()-1);
448 else if (__fctyp.is(__ctype_type::digit, *__next))
450 long __num = __traits.value(*__next, 10);
451 if (++__next != __fmt_last
452 && __fctyp.is(__ctype_type::digit, *__next))
455 __num += __traits.value(*__next++, 10);
457 if (0 <= __num && __num < this->size())
462 __fmt_first = __next;
464 std::copy(__fmt_first, __fmt_last, __out);
469 template<typename _Out_iter, typename _Bi_iter,
470 typename _Rx_traits, typename _Ch_type>
472 regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
473 const basic_regex<_Ch_type, _Rx_traits>& __e,
474 const _Ch_type* __fmt,
475 regex_constants::match_flag_type __flags)
477 typedef regex_iterator<_Bi_iter, _Ch_type, _Rx_traits> _IterT;
478 _IterT __i(__first, __last, __e, __flags);
482 if (!(__flags & regex_constants::format_no_copy))
483 std::copy(__first, __last, __out);
487 sub_match<_Bi_iter> __last;
488 auto __len = char_traits<_Ch_type>::length(__fmt);
489 for (; __i != __end; ++__i)
491 if (!(__flags & regex_constants::format_no_copy))
492 std::copy(__i->prefix().first, __i->prefix().second, __out);
493 __out = __i->format(__out, __fmt, __fmt + __len, __flags);
494 __last = __i->suffix();
495 if (__flags & regex_constants::format_first_only)
498 if (!(__flags & regex_constants::format_no_copy))
499 std::copy(__last.first, __last.second, __out);
504 template<typename _Bi_iter,
508 regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
509 operator==(const regex_iterator& __rhs) const
511 return (_M_match.empty() && __rhs._M_match.empty())
512 || (_M_begin == __rhs._M_begin
513 && _M_end == __rhs._M_end
514 && _M_pregex == __rhs._M_pregex
515 && _M_flags == __rhs._M_flags
516 && _M_match[0] == __rhs._M_match[0]);
519 template<typename _Bi_iter,
522 regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
523 regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
526 // In all cases in which the call to regex_search returns true,
527 // match.prefix().first shall be equal to the previous value of
528 // match[0].second, and for each index i in the half-open range
529 // [0, match.size()) for which match[i].matched is true,
530 // match[i].position() shall return distance(begin, match[i].first).
532 if (_M_match[0].matched)
534 auto __start = _M_match[0].second;
535 auto __prefix_first = _M_match[0].second;
536 if (_M_match[0].first == _M_match[0].second)
538 if (__start == _M_end)
540 _M_match = value_type();
545 if (regex_search(__start, _M_end, _M_match, *_M_pregex,
547 | regex_constants::match_not_null
548 | regex_constants::match_continuous))
550 _GLIBCXX_DEBUG_ASSERT(_M_match[0].matched);
551 _M_match.at(_M_match.size()).first = __prefix_first;
552 _M_match._M_in_iterator = true;
553 _M_match._M_begin = _M_begin;
560 _M_flags |= regex_constants::match_prev_avail;
561 if (regex_search(__start, _M_end, _M_match, *_M_pregex, _M_flags))
563 _GLIBCXX_DEBUG_ASSERT(_M_match[0].matched);
564 _M_match.at(_M_match.size()).first = __prefix_first;
565 _M_match._M_in_iterator = true;
566 _M_match._M_begin = _M_begin;
569 _M_match = value_type();
574 template<typename _Bi_iter,
577 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
578 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
579 operator=(const regex_token_iterator& __rhs)
581 _M_position = __rhs._M_position;
582 _M_subs = __rhs._M_subs;
584 _M_result = __rhs._M_result;
585 _M_suffix = __rhs._M_suffix;
586 _M_has_m1 = __rhs._M_has_m1;
587 if (__rhs._M_result == &__rhs._M_suffix)
588 _M_result = &_M_suffix;
592 template<typename _Bi_iter,
596 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
597 operator==(const regex_token_iterator& __rhs) const
599 if (_M_end_of_seq() && __rhs._M_end_of_seq())
601 if (_M_suffix.matched && __rhs._M_suffix.matched
602 && _M_suffix == __rhs._M_suffix)
604 if (_M_end_of_seq() || _M_suffix.matched
605 || __rhs._M_end_of_seq() || __rhs._M_suffix.matched)
607 return _M_position == __rhs._M_position
608 && _M_n == __rhs._M_n
609 && _M_subs == __rhs._M_subs;
612 template<typename _Bi_iter,
615 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
616 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
619 _Position __prev = _M_position;
620 if (_M_suffix.matched)
621 *this = regex_token_iterator();
622 else if (_M_n + 1 < _M_subs.size())
625 _M_result = &_M_current_match();
631 if (_M_position != _Position())
632 _M_result = &_M_current_match();
633 else if (_M_has_m1 && __prev->suffix().length() != 0)
635 _M_suffix.matched = true;
636 _M_suffix.first = __prev->suffix().first;
637 _M_suffix.second = __prev->suffix().second;
638 _M_result = &_M_suffix;
641 *this = regex_token_iterator();
646 template<typename _Bi_iter,
650 regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
651 _M_init(_Bi_iter __a, _Bi_iter __b)
654 for (auto __it : _M_subs)
660 if (_M_position != _Position())
661 _M_result = &_M_current_match();
664 _M_suffix.matched = true;
665 _M_suffix.first = __a;
666 _M_suffix.second = __b;
667 _M_result = &_M_suffix;
673 _GLIBCXX_END_NAMESPACE_VERSION