3 * Copyright (c) 1998-2002
6 * Use, modification and distribution are subject to the
7 * Boost Software License, Version 1.0. (See accompanying file
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13 * LOCATION: see http://www.boost.org for most recent version.
14 * FILE regex_compile.hpp
15 * VERSION see <boost/version.hpp>
16 * DESCRIPTION: Declares reg_expression<> member functions. This is
17 * an internal header file, do not include directly.
20 #ifndef BOOST_REGEX_COMPILE_HPP
21 #define BOOST_REGEX_COMPILE_HPP
24 #ifdef BOOST_HAS_ABI_HEADERS
25 # include BOOST_ABI_PREFIX
28 #pragma option push -w-8004
34 template <class traits>
37 typedef typename traits::char_type char_type;
40 kmp_translator(bool c, traits* p) : icase(c), pt(p) {}
41 char_type operator()(char_type c)
43 return pt->translate(c, icase);
48 template <class charT, class traits_type, class Allocator>
49 bool BOOST_REGEX_CALL re_maybe_set_member(charT c,
50 const re_set_long* set_,
51 const reg_expression<charT, traits_type, Allocator>& e)
53 const charT* p = reinterpret_cast<const charT*>(set_+1);
54 bool icase = e.flags() & regex_constants::icase;
55 charT col = e.get_traits().translate(c, icase);
56 for(unsigned int i = 0; i < set_->csingles; ++i)
59 return set_->isnot ? false : true;
64 return set_->isnot ? true : false;
67 } // namespace re_detail
69 template <class traits>
72 typedef typename traits::uchar_type traits_uchar_type;
73 typedef typename traits::size_type traits_size_type;
74 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
75 static bool test(char)
77 static bool test(unsigned char)
79 static bool test(signed char)
82 template <class charT> static bool test(charT c)
83 { return (traits_size_type)(traits_uchar_type)c >= 256; }
86 template <class charT, class traits, class Allocator>
87 inline bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::can_start(charT c, const unsigned char* _map, unsigned char mask, const re_detail::_wide_type&)
89 if(is_big_char<traits>::test(c))
91 return BOOST_REGEX_MAKE_BOOL(_map[(traits_uchar_type)c] & mask);
94 template <class charT, class traits, class Allocator>
95 inline bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::can_start(charT c, const unsigned char* _map, unsigned char mask, const re_detail::_narrow_type&)
97 return BOOST_REGEX_MAKE_BOOL(_map[(traits_uchar_type)c] & mask);
100 template <class charT, class traits, class Allocator>
101 reg_expression<charT, traits, Allocator>::reg_expression(const Allocator& a)
102 : regbase(), data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
106 template <class charT, class traits, class Allocator>
107 reg_expression<charT, traits, Allocator>::reg_expression(const charT* p, flag_type f, const Allocator& a)
108 : data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
110 set_expression(p, f | regex_constants::use_except);
113 template <class charT, class traits, class Allocator>
114 reg_expression<charT, traits, Allocator>::reg_expression(const charT* p1, const charT* p2, flag_type f, const Allocator& a)
115 : data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
117 set_expression(p1, p2, f | regex_constants::use_except);
120 template <class charT, class traits, class Allocator>
121 reg_expression<charT, traits, Allocator>::reg_expression(const charT* p, size_type len, flag_type f, const Allocator& a)
122 : data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
124 set_expression(p, p + len, f | regex_constants::use_except);
127 template <class charT, class traits, class Allocator>
128 reg_expression<charT, traits, Allocator>::reg_expression(const reg_expression<charT, traits, Allocator>& e)
129 : regbase(e), data(e.allocator()), pkmp(0), error_code_(REG_EMPTY), _expression(0)
132 // we do a deep copy only if e is a valid expression, otherwise fail.
134 if(e.error_code() == 0)
136 const charT* pe = e.expression();
137 set_expression(pe, pe + e._expression_len, e.flags() | regex_constants::use_except);
141 _flags = e.flags() & ~(regex_constants::use_except);
142 fail(e.error_code());
146 template <class charT, class traits, class Allocator>
147 reg_expression<charT, traits, Allocator>::~reg_expression()
150 re_detail::kmp_free(pkmp, data.allocator());
153 template <class charT, class traits, class Allocator>
154 reg_expression<charT, traits, Allocator>& BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::operator=(const reg_expression<charT, traits, Allocator>& e)
157 // we do a deep copy only if e is a valid expression, otherwise fail.
159 if(this == &e) return *this;
161 fail(e.error_code());
162 if(error_code() == 0)
163 set_expression(e._expression, e._expression + e._expression_len, e.flags() | regex_constants::use_except);
167 template <class charT, class traits, class Allocator>
168 int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compare(const reg_expression<charT, traits, Allocator>& e)const
170 if(_flags != e.flags())
171 return _flags - e.flags();
172 return str().compare(e.str());
175 template <class charT, class traits, class Allocator>
176 void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::swap(reg_expression& that)throw()
178 traits_inst.swap(that.traits_inst);
179 data.swap(that.data);
180 static_cast<regbase&>(*this).swap(that);
182 std::swap(_restart_type, that._restart_type);
183 std::swap(marks, that.marks);
184 std::swap(repeats, that.repeats);
185 std::swap(startmap, that.startmap);
186 std::swap(_expression_len, that._expression_len);
187 std::swap(_leading_len, that._leading_len);
188 std::swap(_leading_string, that._leading_string);
189 std::swap(_leading_string_len, that._leading_string_len);
190 std::swap(pkmp, that.pkmp);
191 std::swap(error_code_, that.error_code_);
192 std::swap(_expression, that._expression);
195 template <class charT, class traits, class Allocator>
196 Allocator BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::allocator()const
198 return data.allocator();
201 template <class charT, class traits, class Allocator>
202 Allocator BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::get_allocator()const
204 return data.allocator();
207 template <class charT, class traits, class Allocator>
208 unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_inner_set(const charT*& arg_first, const charT* arg_last)
211 // we have an inner [...] construct
213 jm_assert(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*arg_first) == traits_type::syntax_open_set);
214 const charT* base = arg_first;
215 while( (arg_first != arg_last)
216 && (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*arg_first) != traits_type::syntax_close_set) )
218 if(arg_first == arg_last)
221 if((arg_first-base) < 5)
223 if(*(base+1) != *(arg_first-2))
225 unsigned int result = traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*(base+1));
226 if((result == traits_type::syntax_colon) && ((arg_first-base) == 5))
228 unsigned type = traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*(base+2));
229 if((type == traits_type::syntax_left_word) || (type == traits_type::syntax_right_word))
232 return ((result == traits_type::syntax_colon) || (result == traits_type::syntax_dot) || (result == traits_type::syntax_equal)) ? result : 0;
236 template <class charT, class traits, class Allocator>
237 bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::skip_space(const charT*& arg_first, const charT* arg_last)
240 // returns true if we get to arg_last:
242 while((arg_first != arg_last) && (traits_inst.is_class(*arg_first, traits_type::char_class_space) == true))
246 return arg_first == arg_last;
249 template <class charT, class traits, class Allocator>
250 void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_range(const charT*& ptr, const charT* arg_end, unsigned& min, unsigned& max)
253 // we have {x} or {x,} or {x,y} NB no spaces inside braces
254 // anything else is illegal
255 // On input ptr points to "{"
258 if(skip_space(ptr, arg_end))
263 if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_digit)
268 min = traits_inst.toi(ptr, arg_end, 10);
269 if(skip_space(ptr, arg_end))
274 if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_comma)
276 //we have a second interval:
278 if(skip_space(ptr, arg_end))
283 if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_digit)
284 max = traits_inst.toi(ptr, arg_end, 10);
292 if(skip_space(ptr, arg_end))
302 if(_flags & bk_braces)
304 if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_slash)
311 // back\ is OK now check the }
313 if((ptr == arg_end) || (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_close_brace))
320 else if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_close_brace)
327 template <class charT, class traits, class Allocator>
328 charT BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_escape(const charT*& arg_first, const charT* arg_last)
331 traits_size_type c_unsigned = (traits_size_type)(traits_uchar_type)*arg_first;
332 // this is only used for the switch(), but cannot be folded in
333 // due to a bug in Comeau 4.2.44beta3
334 traits_size_type syntax = traits_inst.syntax_type(c_unsigned);
337 case traits_type::syntax_a:
341 case traits_type::syntax_f:
345 case traits_type::syntax_n:
349 case traits_type::syntax_r:
353 case traits_type::syntax_t:
357 case traits_type::syntax_v:
361 case traits_type::syntax_x:
363 if(arg_first == arg_last)
368 // maybe have \x{ddd}
369 if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)(*arg_first)) == traits_type::syntax_open_brace)
372 if(arg_first == arg_last)
377 if(traits_inst.is_class(*arg_first, traits_type::char_class_xdigit) == false)
382 c = (charT)traits_inst.toi(arg_first, arg_last, -16);
383 if((arg_first == arg_last) || (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)(*arg_first)) != traits_type::syntax_close_brace))
392 if(traits_inst.is_class(*arg_first, traits_type::char_class_xdigit) == false)
397 c = (charT)traits_inst.toi(arg_first, arg_last, -16);
400 case traits_type::syntax_c:
402 if(arg_first == arg_last)
407 if(((traits_uchar_type)(*arg_first) < (traits_uchar_type)'@')
408 || ((traits_uchar_type)(*arg_first) > (traits_uchar_type)127) )
413 c = (charT)((traits_uchar_type)(*arg_first) - (traits_uchar_type)'@');
416 case traits_type::syntax_e:
420 case traits_type::syntax_digit:
421 c = (charT)traits_inst.toi(arg_first, arg_last, -8);
430 template <class charT, class traits, class Allocator>
431 void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_maps()
433 re_detail::re_syntax_base* record = static_cast<re_detail::re_syntax_base*>(data.data());
434 // always compile the first _map:
435 std::memset(startmap, 0, 256);
436 record->can_be_null = 0;
437 compile_map(record, startmap, 0, re_detail::mask_all);
439 while(record->type != re_detail::syntax_element_match)
441 if((record->type == re_detail::syntax_element_alt) || (record->type == re_detail::syntax_element_rep))
443 std::memset(&(static_cast<re_detail::re_jump*>(record)->_map), 0, 256);
444 record->can_be_null = 0;
445 compile_map(record->next.p, static_cast<re_detail::re_jump*>(record)->_map, &(record->can_be_null), re_detail::mask_take, static_cast<re_detail::re_jump*>(record)->alt.p);
446 compile_map(static_cast<re_detail::re_jump*>(record)->alt.p, static_cast<re_detail::re_jump*>(record)->_map, &(record->can_be_null), re_detail::mask_skip);
447 if(record->type == re_detail::syntax_element_rep)
449 re_detail::re_repeat* rep = static_cast<re_detail::re_repeat*>(record);
450 // set whether this is a singleton repeat or not:
451 if(rep->next.p->next.p->next.p == rep->alt.p)
453 switch(rep->next.p->type)
455 case re_detail::syntax_element_wild:
456 rep->type = re_detail::syntax_element_dot_rep;
458 case re_detail::syntax_element_literal:
459 rep->type = re_detail::syntax_element_char_rep;
461 case re_detail::syntax_element_set:
462 rep->type = re_detail::syntax_element_short_set_rep;
464 case re_detail::syntax_element_long_set:
465 if(static_cast<re_detail::re_set_long*>(rep->next.p)->singleton)
466 rep->type = re_detail::syntax_element_long_set_rep;
476 record->can_be_null = 0;
477 compile_map(record, 0, &(record->can_be_null), re_detail::mask_all);
479 record = record->next.p;
481 record->can_be_null = re_detail::mask_all;
484 template <class charT, class traits, class Allocator>
485 bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::probe_start(
486 re_detail::re_syntax_base* node, charT cc, re_detail::re_syntax_base* terminal) const
492 case re_detail::syntax_element_startmark:
493 if(static_cast<const re_detail::re_brace*>(node)->index == -1)
495 return probe_start(node->next.p->next.p, cc, terminal)
496 && probe_start(static_cast<const re_detail::re_jump*>(node->next.p)->alt.p, cc, terminal);
498 else if(static_cast<const re_detail::re_brace*>(node)->index == -3)
500 return probe_start(node->next.p->next.p, cc, terminal);
502 // doesn't tell us anything about the next character, so:
503 return probe_start(node->next.p, cc, terminal);
504 case re_detail::syntax_element_endmark:
505 if(static_cast<const re_detail::re_brace*>(node)->index == -3)
510 case re_detail::syntax_element_start_line:
511 case re_detail::syntax_element_word_boundary:
512 case re_detail::syntax_element_buffer_start:
513 case re_detail::syntax_element_restart_continue:
514 // doesn't tell us anything about the next character, so:
515 return probe_start(node->next.p, cc, terminal);
516 case re_detail::syntax_element_literal:
517 // only the first character of the literal can match:
518 // note these have already been translated:
519 if(*reinterpret_cast<charT*>(static_cast<re_detail::re_literal*>(node)+1) == traits_inst.translate(cc, (_flags & regex_constants::icase)))
522 case re_detail::syntax_element_end_line:
523 // next character (if there is one!) must be a newline:
524 if(traits_inst.is_separator(traits_inst.translate(cc, (_flags & regex_constants::icase))))
527 case re_detail::syntax_element_wild:
529 case re_detail::syntax_element_match:
531 case re_detail::syntax_element_within_word:
532 case re_detail::syntax_element_word_start:
533 return traits_inst.is_class(traits_inst.translate(cc, (_flags & regex_constants::icase)), traits_type::char_class_word);
534 case re_detail::syntax_element_word_end:
535 // what follows must not be a word character,
536 return traits_inst.is_class(traits_inst.translate(cc, (_flags & regex_constants::icase)), traits_type::char_class_word) ? false : true;
537 case re_detail::syntax_element_buffer_end:
538 // we can be null, nothing must follow,
539 // NB we assume that this is followed by
540 // re_detail::syntax_element_match, if its not then we can
541 // never match anything anyway!!
543 case re_detail::syntax_element_soft_buffer_end:
544 // we can be null, only newlines must follow,
545 // NB we assume that this is followed by
546 // re_detail::syntax_element_match, if its not then we can
547 // never match anything anyway!!
548 return traits_inst.is_separator(traits_inst.translate(cc, (_flags & regex_constants::icase)));
549 case re_detail::syntax_element_backref:
550 // there's no easy way to determine this
551 // which is not to say it can't be done!
554 case re_detail::syntax_element_long_set:
555 // we can not be null,
556 // we need to add already translated values in the set
557 // to values in the _map
558 return re_detail::re_maybe_set_member(cc, static_cast<const re_detail::re_set_long*>(node), *this) || (re_detail::re_is_set_member(static_cast<const charT*>(&cc), static_cast<const charT*>(&cc+1), static_cast<re_detail::re_set_long*>(node), *this) != &cc);
559 case re_detail::syntax_element_set:
560 // set all the elements that are set in corresponding set:
561 c = (traits_size_type)(traits_uchar_type)traits_inst.translate(cc, (_flags & regex_constants::icase));
562 return static_cast<re_detail::re_set*>(node)->_map[c] != 0;
563 case re_detail::syntax_element_jump:
564 if(static_cast<re_detail::re_jump*>(node)->alt.p < node)
567 // caused only by end of repeat section, we'll treat this
568 // the same as a match, because the sub-expression has matched.
569 if(node->next.p == terminal)
570 return true; // null repeat - we can always take this
574 // take the jump, add in fix for the fact that if the
575 // repeat that we're jumping to has non-zero minimum count
576 // then we need to add in the possiblity that we could still
578 re_detail::re_syntax_base* next = static_cast<re_detail::re_jump*>(node)->alt.p;
579 bool b = probe_start(next, cc, terminal);
580 if((next->type == re_detail::syntax_element_rep) && (static_cast<re_detail::re_repeat*>(next)->min != 0))
582 b = b || probe_start(static_cast<re_detail::re_jump*>(next)->alt.p, cc, terminal);
588 // take the jump and compile:
589 return probe_start(static_cast<re_detail::re_jump*>(node)->alt.p, cc, terminal);
590 case re_detail::syntax_element_alt:
591 // we need to take the OR of the two alternatives:
592 return probe_start(static_cast<re_detail::re_jump*>(node)->alt.p, cc, terminal) || probe_start(node->next.p, cc, terminal);
593 case re_detail::syntax_element_rep:
594 case re_detail::syntax_element_char_rep:
595 case re_detail::syntax_element_dot_rep:
596 case re_detail::syntax_element_long_set_rep:
597 case re_detail::syntax_element_short_set_rep:
598 // we need to take the OR of the two alternatives
599 if(static_cast<re_detail::re_repeat*>(node)->min == 0)
600 return probe_start(node->next.p, cc, static_cast<re_detail::re_jump*>(node)->alt.p) || probe_start(static_cast<re_detail::re_jump*>(node)->alt.p, cc, terminal);
602 return probe_start(node->next.p, cc, static_cast<re_detail::re_jump*>(node)->alt.p);
603 case re_detail::syntax_element_combining:
604 return !traits_inst.is_combining(traits_inst.translate(cc, (_flags & regex_constants::icase)));
609 template <class charT, class traits, class Allocator>
610 bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::probe_start_null(re_detail::re_syntax_base* node, re_detail::re_syntax_base* terminal)const
614 case re_detail::syntax_element_endmark:
615 if(static_cast<const re_detail::re_brace*>(node)->index == -3)
620 case re_detail::syntax_element_startmark:
621 case re_detail::syntax_element_start_line:
622 case re_detail::syntax_element_word_boundary:
623 case re_detail::syntax_element_buffer_start:
624 case re_detail::syntax_element_restart_continue:
625 case re_detail::syntax_element_end_line:
626 case re_detail::syntax_element_word_end:
627 // doesn't tell us anything about the next character, so:
628 return probe_start_null(node->next.p, terminal);
629 case re_detail::syntax_element_match:
630 case re_detail::syntax_element_buffer_end:
631 case re_detail::syntax_element_soft_buffer_end:
632 case re_detail::syntax_element_backref:
634 case re_detail::syntax_element_jump:
635 if(static_cast<re_detail::re_jump*>(node)->alt.p < node)
638 // caused only by end of repeat section, we'll treat this
639 // the same as a match, because the sub-expression has matched.
640 // this is only caused by NULL repeats as in "(a*)*" or "(\<)*"
641 // these are really nonsensence and make the matching code much
642 // harder, it would be nice to get rid of them altogether.
643 if(node->next.p == terminal)
646 return probe_start_null(static_cast<re_detail::re_jump*>(node)->alt.p, terminal);
649 // take the jump and compile:
650 return probe_start_null(static_cast<re_detail::re_jump*>(node)->alt.p, terminal);
651 case re_detail::syntax_element_alt:
652 // we need to take the OR of the two alternatives:
653 return probe_start_null(static_cast<re_detail::re_jump*>(node)->alt.p, terminal) || probe_start_null(node->next.p, terminal);
654 case re_detail::syntax_element_rep:
655 // only need to consider skipping the repeat:
656 return probe_start_null(static_cast<re_detail::re_jump*>(node)->alt.p, terminal);
663 template <class charT, class traits, class Allocator>
664 void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_map(
665 re_detail::re_syntax_base* node, unsigned char* _map,
666 unsigned int* pnull, unsigned char mask, re_detail::re_syntax_base* terminal)const
670 for(unsigned int i = 0; i < 256; ++i)
672 if(probe_start(node, (charT)i, terminal))
676 if(pnull && probe_start_null(node, terminal))
680 template <class charT, class traits, class Allocator>
681 void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::move_offsets(re_detail::re_syntax_base* j, unsigned arg_size)
684 # pragma warning(push)
685 # pragma warning(disable: 4127)
687 // move all offsets starting with j->link forward by arg_size
688 // called after an insert:
689 j = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + j->next.i);
694 case re_detail::syntax_element_rep:
695 static_cast<re_detail::re_jump*>(j)->alt.i += arg_size;
696 j->next.i += arg_size;
698 case re_detail::syntax_element_jump:
699 case re_detail::syntax_element_alt:
700 static_cast<re_detail::re_jump*>(j)->alt.i += arg_size;
701 j->next.i += arg_size;
704 j->next.i += arg_size;
707 if(j->next.i == arg_size)
709 j = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + j->next.i);
712 # pragma warning(pop)
716 template <class charT, class traits, class Allocator>
717 re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_set_simple(re_detail::re_syntax_base* dat, unsigned long cls, bool isnot)
719 typedef typename re_detail::is_byte<charT>::width_type width_type;
720 re_detail::jstack<traits_string_type, Allocator> singles(64, data.allocator());
721 re_detail::jstack<traits_string_type, Allocator> ranges(64, data.allocator());
722 re_detail::jstack<boost::uint_fast32_t, Allocator> classes(64, data.allocator());
723 re_detail::jstack<traits_string_type, Allocator> equivalents(64, data.allocator());
728 dat->next.i = data.size();
730 return compile_set_aux(singles, ranges, classes, equivalents, isnot, width_type());
733 template <class charT, class traits, class Allocator>
734 re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_set(const charT*& arg_first, const charT* arg_last)
736 re_detail::jstack<traits_string_type, Allocator> singles(64, data.allocator());
737 re_detail::jstack<traits_string_type, Allocator> ranges(64, data.allocator());
738 re_detail::jstack<boost::uint_fast32_t, Allocator> classes(64, data.allocator());
739 re_detail::jstack<traits_string_type, Allocator> equivalents(64, data.allocator());
740 bool has_digraphs = false;
741 jm_assert(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*arg_first) == traits_type::syntax_open_set);
743 bool started = false;
754 unsigned l = last_none;
755 traits_string_type s;
757 while((arg_first != arg_last) && !done)
759 traits_size_type c = (traits_size_type)(traits_uchar_type)*arg_first;
760 // this is only used for the switch(), but cannot be folded in
761 // due to a bug in Comeau 4.2.44beta3
762 traits_size_type syntax = traits_inst.syntax_type(c);
765 case traits_type::syntax_caret:
766 if(!started && !isnot)
773 goto char_set_literal;
776 case traits_type::syntax_open_set:
778 if((_flags & char_classes) == 0)
781 goto char_set_literal;
783 // check to see if we really have a class:
784 const charT* base = arg_first;
785 // this is only used for the switch(), but cannot be folded in
786 // due to a bug in Comeau 4.2.44beta3
787 unsigned int inner_set = parse_inner_set(arg_first, arg_last);
790 case traits_type::syntax_colon:
797 boost::uint_fast32_t id = traits_inst.lookup_classname(base+2, arg_first-2);
798 if(_flags & regex_constants::icase)
800 if((id == traits_type::char_class_upper) || (id == traits_type::char_class_lower))
802 id = traits_type::char_class_alpha;
815 case traits_type::syntax_dot:
817 // we have a collating element [.collating-name.]
819 if(traits_inst.lookup_collatename(s, base+2, arg_first-2))
824 if(s.size())goto char_set_literal;
828 case traits_type::syntax_equal:
830 // we have an equivalence class [=collating-name=]
832 if(traits_inst.lookup_collatename(s, base+2, arg_first-2))
834 std::size_t len = s.size();
840 s[i] = traits_inst.translate(s[i], (_flags & regex_constants::icase));
843 traits_string_type s2;
844 traits_inst.transform_primary(s2, s);
845 equivalents.push(s2);
853 case traits_type::syntax_left_word:
854 if((started == false) && (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*arg_first) == traits_type::syntax_close_set))
857 return add_simple(0, re_detail::syntax_element_word_start);
861 case traits_type::syntax_right_word:
862 if((started == false) && (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*arg_first) == traits_type::syntax_close_set))
865 return add_simple(0, re_detail::syntax_element_word_end);
872 unsigned int t = traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*(base+1));
873 if((t != traits_type::syntax_colon) && (t != traits_type::syntax_dot) && (t != traits_type::syntax_equal))
877 goto char_set_literal;
883 if(arg_first == arg_last)
890 case traits_type::syntax_close_set:
894 goto char_set_literal;
898 case traits_type::syntax_dash:
902 goto char_set_literal;
905 if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*arg_first) == traits_type::syntax_close_set)
909 goto char_set_literal;
911 if((singles.empty() == true) || (l != last_single))
916 ranges.push(singles.peek());
917 if(singles.peek().size() <= 1) // leave digraphs and ligatures in place
921 case traits_type::syntax_slash:
922 if(_flags & regex_constants::escape_in_lists)
925 if(arg_first == arg_last)
927 /*traits_size_type*/ c = (traits_size_type)(traits_uchar_type)*arg_first;
928 // this is only used for the switch(), but cannot be folded in
929 // due to a bug in Comeau 4.2.44beta3
930 traits_size_type syntax4 = traits_inst.syntax_type(c);
933 case traits_type::syntax_w:
939 classes.push(traits_type::char_class_word);
944 case traits_type::syntax_d:
950 classes.push(traits_type::char_class_digit);
955 case traits_type::syntax_s:
961 classes.push(traits_type::char_class_space);
966 case traits_type::syntax_l:
972 classes.push(traits_type::char_class_lower);
977 case traits_type::syntax_u:
983 classes.push(traits_type::char_class_upper);
988 case traits_type::syntax_W:
989 case traits_type::syntax_D:
990 case traits_type::syntax_S:
991 case traits_type::syntax_U:
992 case traits_type::syntax_L:
996 c = parse_escape(arg_first, arg_last);
999 goto char_set_literal;
1005 goto char_set_literal;
1011 // get string length to stop us going past the end of string (DWA)
1012 std::size_t len = s.size();
1015 s[i] = traits_inst.translate(s[i], (_flags & regex_constants::icase));
1023 if(s.size() > 1) // add ligatures to singles list as well
1037 typedef typename re_detail::is_byte<charT>::width_type width_type;
1039 re_detail::re_syntax_base* result;
1041 result = compile_set_aux(singles, ranges, classes, equivalents, isnot, re_detail::_wide_type());
1043 result = compile_set_aux(singles, ranges, classes, equivalents, isnot, width_type());
1046 if((result == 0) && (_flags & regex_constants::use_except))
1052 template <class charT, class traits, class Allocator>
1053 re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_set_aux(re_detail::jstack<traits_string_type, Allocator>& singles, re_detail::jstack<traits_string_type, Allocator>& ranges, re_detail::jstack<boost::uint_fast32_t, Allocator>& classes, re_detail::jstack<traits_string_type, Allocator>& equivalents, bool isnot, const re_detail::_wide_type&)
1055 size_type base = data.size();
1056 data.extend(sizeof(re_detail::re_set_long));
1057 unsigned int csingles = 0;
1058 unsigned int cranges = 0;
1059 boost::uint_fast32_t cclasses = 0;
1060 unsigned int cequivalents = 0;
1061 bool nocollate_state = !(flags() & regex_constants::collate);
1062 bool singleton = true;
1064 while(singles.empty() == false)
1067 const traits_string_type& s = singles.peek();
1068 std::size_t len = (s.size() + 1) * sizeof(charT);
1069 if(len > sizeof(charT))
1071 std::memcpy(reinterpret_cast<charT*>(data.extend(len)), s.c_str(), len);
1074 while(ranges.empty() == false)
1076 traits_string_type c1, c2;
1080 traits_inst.transform(c1, ranges.peek());
1085 traits_inst.transform(c2, ranges.peek());
1089 // for some reason bc5 crashes when throwing exceptions
1090 // from here - probably an EH-compiler bug, but hard to
1092 // delay throw to later:
1094 boost::uint_fast32_t f = _flags;
1095 _flags &= ~regex_constants::use_except;
1104 std::size_t len = (re_detail::re_strlen(c1.c_str()) + 1) * sizeof(charT);
1105 std::memcpy(data.extend(len), c1.c_str(), len);
1106 len = (re_detail::re_strlen(c2.c_str()) + 1) * sizeof(charT);
1107 std::memcpy(data.extend(len), c2.c_str(), len);
1109 while(classes.empty() == false)
1111 cclasses |= classes.peek();
1114 while(equivalents.empty() == false)
1117 const traits_string_type& s = equivalents.peek();
1118 std::size_t len = (re_detail::re_strlen(s.c_str()) + 1) * sizeof(charT);
1119 std::memcpy(reinterpret_cast<charT*>(data.extend(len)), s.c_str(), len);
1123 re_detail::re_set_long* dat = reinterpret_cast<re_detail::re_set_long*>(reinterpret_cast<unsigned char*>(data.data()) + base);
1124 dat->type = re_detail::syntax_element_long_set;
1125 dat->csingles = csingles;
1126 dat->cranges = cranges;
1127 dat->cclasses = cclasses;
1128 dat->cequivalents = cequivalents;
1131 dat->singleton = isnot ? true : singleton;
1135 template <class charT, class traits, class Allocator>
1136 re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_set_aux(re_detail::jstack<traits_string_type, Allocator>& singles, re_detail::jstack<traits_string_type, Allocator>& ranges, re_detail::jstack<boost::uint_fast32_t, Allocator>& classes, re_detail::jstack<traits_string_type, Allocator>& equivalents, bool isnot, const re_detail::_narrow_type&)
1138 re_detail::re_set* dat = reinterpret_cast<re_detail::re_set*>(data.extend(sizeof(re_detail::re_set)));
1139 std::memset(dat, 0, sizeof(re_detail::re_set));
1141 while(singles.empty() == false)
1143 dat->_map[(traits_size_type)(traits_uchar_type)*(singles.peek().c_str())] = re_detail::mask_all;
1146 while(ranges.empty() == false)
1148 traits_string_type c1, c2, c3, c4;
1150 if((flags() & regex_constants::collate) == 0)
1153 traits_inst.transform(c1, ranges.peek());
1155 if((flags() & regex_constants::collate) == 0)
1158 traits_inst.transform(c2, ranges.peek());
1163 // for some reason bc5 crashes when throwing exceptions
1164 // from here - probably an EH-compiler bug, but hard to
1166 // delay throw to later:
1168 boost::uint_fast32_t f = _flags;
1169 _flags &= ~regex_constants::use_except;
1177 for(unsigned int i = 0; i < 256; ++i)
1180 if((flags() & regex_constants::collate) == 0)
1183 traits_inst.transform(c3, c4);
1184 if((c3 <= c1) && (c3 >= c2))
1185 dat->_map[i] = re_detail::mask_all;
1188 while(equivalents.empty() == false)
1190 traits_string_type c1, c2;
1191 for(unsigned int i = 0; i < 256; ++i)
1194 traits_inst.transform_primary(c1, c2);
1195 if(c1 == equivalents.peek())
1196 dat->_map[i] = re_detail::mask_all;
1201 boost::uint_fast32_t l_flags = 0;
1202 while(classes.empty() == false)
1204 l_flags |= classes.peek();
1209 for(unsigned int i = 0; i < 256; ++i)
1211 if(traits_inst.is_class(charT(i), l_flags))
1212 dat->_map[(traits_uchar_type)traits_inst.translate((charT)i, (_flags & regex_constants::icase))] = re_detail::mask_all;
1218 for(unsigned int i = 0; i < 256; ++i)
1220 dat->_map[i] = !dat->_map[i];
1224 dat->type = re_detail::syntax_element_set;
1229 #ifndef __CODEGUARD__
1230 // this must not be inline when Borland's codeguard support is turned
1231 // on, otherwise we _will_ get surious codeguard errors...
1234 re_detail::re_syntax_base* add_offset(void* base, std::ptrdiff_t off)
1236 return reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(base) + off);
1239 template <class charT, class traits, class Allocator>
1240 void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::fixup_apply(re_detail::re_syntax_base* b, unsigned cbraces)
1242 typedef typename boost::detail::rebind_allocator<bool, Allocator>::type b_alloc;
1244 register unsigned char* base = reinterpret_cast<unsigned char*>(b);
1245 register re_detail::re_syntax_base* ptr = b;
1247 b_alloc a(data.allocator());
1248 #ifndef BOOST_NO_EXCEPTIONS
1252 pb = a.allocate(cbraces);
1253 BOOST_REGEX_NOEH_ASSERT(pb)
1254 for(unsigned i = 0; i < cbraces; ++i)
1263 case re_detail::syntax_element_rep:
1264 jm_assert(data.size() > static_cast<re_detail::re_jump*>(ptr)->alt.i);
1265 static_cast<re_detail::re_jump*>(ptr)->alt.p = add_offset(base, static_cast<re_detail::re_jump*>(ptr)->alt.i);
1266 #ifdef BOOST_REGEX_DEBUG
1267 if((re_detail::padding_mask & reinterpret_cast<int>(static_cast<re_detail::re_jump*>(ptr)->alt.p)) && (static_cast<re_detail::re_jump*>(ptr)->alt.p != b))
1269 jm_trace("padding mis-aligment in repeat jump to object type: " << static_cast<re_detail::re_jump*>(ptr)->alt.p->type)
1270 //jm_assert(0 == (padding_mask & (int)((re_detail::re_jump*)ptr)->alt.p));
1273 static_cast<re_detail::re_repeat*>(ptr)->id = repeats;
1276 case re_detail::syntax_element_jump:
1277 case re_detail::syntax_element_alt:
1278 jm_assert(data.size() > static_cast<re_detail::re_jump*>(ptr)->alt.i);
1279 static_cast<re_detail::re_jump*>(ptr)->alt.p = add_offset(base, static_cast<re_detail::re_jump*>(ptr)->alt.i);
1280 #ifdef BOOST_REGEX_DEBUG
1281 if((re_detail::padding_mask & reinterpret_cast<int>(static_cast<re_detail::re_jump*>(ptr)->alt.p) && (static_cast<re_detail::re_jump*>(ptr)->alt.p != b)))
1283 jm_trace("padding mis-aligment in alternation jump to object type: " << static_cast<re_detail::re_jump*>(ptr)->alt.p->type)
1284 //jm_assert(0 == (padding_mask & (int)((re_detail::re_jump*)ptr)->alt.p));
1288 case re_detail::syntax_element_backref:
1289 if((static_cast<re_detail::re_brace*>(ptr)->index >= (int)cbraces) || (pb[static_cast<re_detail::re_brace*>(ptr)->index] == false) )
1292 a.deallocate(pb, cbraces);
1296 case re_detail::syntax_element_endmark:
1297 if(static_cast<re_detail::re_brace*>(ptr)->index > 0)
1298 pb[static_cast<re_detail::re_brace*>(ptr)->index] = true;
1302 jm_assert(data.size() > ptr->next.i);
1303 ptr->next.p = add_offset(base, ptr->next.i);
1304 #ifdef BOOST_REGEX_DEBUG
1305 if((re_detail::padding_mask & (int)(ptr->next.p)) && (static_cast<re_detail::re_jump*>(ptr)->alt.p != b))
1307 jm_trace("padding mis-alignment in next record of type " << ptr->next.p->type)
1308 jm_assert(0 == (re_detail::padding_mask & (int)(ptr->next.p)));
1314 a.deallocate(pb, cbraces);
1316 #ifndef BOOST_NO_EXCEPTIONS
1321 a.deallocate(pb, cbraces);
1328 template <class charT, class traits, class Allocator>
1329 unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::set_expression(const charT* arg_first, const charT* arg_last, flag_type f)
1332 # pragma warning(push)
1333 # pragma warning(disable: 4127)
1336 // strxfrm not working on OpenBSD??
1337 f &= ~regex_constants::collate;
1340 if(arg_first == expression())
1342 traits_string_type s(arg_first, arg_last);
1343 return set_expression(s.c_str(), s.c_str() + s.size(), f);
1345 typedef typename traits_type::sentry sentry_t;
1346 sentry_t sent(traits_inst);
1349 const charT* base = arg_first;
1352 fail(REG_NOERROR); // clear any error
1354 if(arg_first >= arg_last)
1357 return error_code();
1360 const charT* ptr = arg_first;
1362 re_detail::jstack<std::size_t, Allocator> mark(64, data.allocator());
1363 re_detail::jstack<int, Allocator> markid(64, data.allocator());
1364 std::size_t last_mark_popped = 0;
1365 register traits_size_type c;
1366 register re_detail::re_syntax_base* dat;
1368 unsigned rep_min = 0;
1369 unsigned rep_max = 0;
1377 if(_flags & regex_constants::literal)
1379 while(ptr != arg_last)
1381 dat = add_literal(dat, traits_inst.translate(*ptr, (_flags & regex_constants::icase)));
1386 while (ptr < arg_last)
1388 c = (traits_size_type)(traits_uchar_type)*ptr;
1389 // this is only used for the switch(), but cannot be folded in
1390 // due to a bug in Comeau 4.2.44beta3
1391 traits_size_type syntax = traits_inst.syntax_type(c);
1394 case traits_type::syntax_open_bracket:
1395 if(_flags & bk_parens)
1397 dat = add_literal(dat, (charT)c);
1403 dat = add_simple(dat, re_detail::syntax_element_startmark, sizeof(re_detail::re_brace));
1407 static_cast<re_detail::re_brace*>(dat)->index = 0;
1412 static_cast<re_detail::re_brace*>(dat)->index = marks++;
1414 mark.push(data.index(dat));
1417 // check for perl like (?...) extention syntax
1418 c = (traits_size_type)(traits_uchar_type)*ptr;
1419 if(((_flags & (bk_parens|perlex)) == perlex) && (traits_type::syntax_question == traits_inst.syntax_type(c)))
1422 c = (traits_size_type)(traits_uchar_type)*ptr;
1423 // this is only used for the switch(), but cannot be folded in
1424 // due to a bug in Comeau 4.2.44beta3
1425 traits_size_type syntax2 = traits_inst.syntax_type(c);
1428 case traits_type::syntax_colon:
1429 static_cast<re_detail::re_brace*>(dat)->index = 0;
1435 case traits_type::syntax_equal:
1436 static_cast<re_detail::re_brace*>(dat)->index = -1;
1439 common_forward_assert:
1443 dat = add_simple(dat, re_detail::syntax_element_jump, re_detail::re_jump_size);
1446 // we don't know what value to put here yet,
1447 // use an arbitrarily large value for now
1448 // and check it later:
1449 static_cast<re_detail::re_jump*>(dat)->alt.i = INT_MAX/2;
1450 mark.push(data.size() - re_detail::re_jump_size);
1452 case traits_type::syntax_right_word:
1453 static_cast<re_detail::re_brace*>(dat)->index = -3;
1456 goto common_forward_assert;
1457 case traits_type::syntax_not:
1458 static_cast<re_detail::re_brace*>(dat)->index = -2;
1461 goto common_forward_assert;
1462 case traits_type::syntax_hash:
1463 // comment just skip it:
1464 static_cast<re_detail::re_brace*>(dat)->index = 0;
1470 c = (traits_size_type)(traits_uchar_type)*ptr;
1471 }while(traits_type::syntax_close_bracket != traits_inst.syntax_type(c));
1476 // error, return to standard parsing and let that handle the error:
1482 case traits_type::syntax_close_bracket:
1483 if(_flags & bk_parens)
1485 dat = add_literal(dat, (charT)c);
1494 dat->next.i = data.size();
1500 return error_code();
1502 // see if we have an empty alternative:
1503 if(mark.peek() == data.index(dat) )
1505 re_detail::re_syntax_base* para = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + mark.peek());
1506 if(para->type == re_detail::syntax_element_jump)
1509 return error_code();
1513 // pop any pushed alternatives and set the target arg_last destination:
1514 dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + mark.peek());
1515 while(dat->type == re_detail::syntax_element_jump)
1517 static_cast<re_detail::re_jump*>(dat)->alt.i = data.size();
1522 return error_code();
1524 dat = reinterpret_cast<re_detail::re_jump*>(reinterpret_cast<unsigned char*>(data.data()) + mark.peek());
1527 dat = add_simple(0, re_detail::syntax_element_endmark, sizeof(re_detail::re_brace));
1528 static_cast<re_detail::re_brace*>(dat)->index = markid.peek();
1530 last_mark_popped = mark.peek();
1534 case traits_type::syntax_char:
1535 dat = add_literal(dat, (charT)c);
1538 case traits_type::syntax_slash:
1540 if(++ptr == arg_last)
1543 return error_code();
1545 c = (traits_size_type)(traits_uchar_type)*ptr;
1546 // this is only used for the switch(), but cannot be folded in
1547 // due to a bug in Comeau 4.2.44beta3
1548 traits_size_type syntax3 = traits_inst.syntax_type(c);
1551 case traits_type::syntax_open_bracket:
1552 if(_flags & bk_parens)
1553 goto open_bracked_jump;
1555 case traits_type::syntax_close_bracket:
1556 if(_flags & bk_parens)
1557 goto close_bracked_jump;
1559 case traits_type::syntax_plus:
1560 if((_flags & bk_plus_qm) && ((_flags & limited_ops) == 0))
1563 rep_max = (unsigned)-1;
1567 case traits_type::syntax_question:
1568 if((_flags & bk_plus_qm) && ((_flags & limited_ops) == 0))
1575 case traits_type::syntax_or:
1576 if(((_flags & bk_vbar) == 0) || (_flags & limited_ops))
1578 goto alt_string_jump;
1579 case traits_type::syntax_open_brace:
1580 if( ((_flags & bk_braces) == 0) || ((_flags & intervals) == 0))
1583 // we have {x} or {x,} or {x,y}:
1584 parse_range(ptr, arg_last, rep_min, rep_max);
1587 case traits_type::syntax_digit:
1588 if(_flags & bk_refs)
1591 int i = traits_inst.toi((charT)c);
1594 // we can have \025 which means take char whose
1595 // code is 25 (octal), so parse string:
1596 c = traits_inst.toi(ptr, arg_last, -8);
1600 dat = add_simple(dat, re_detail::syntax_element_backref, sizeof(re_detail::re_brace));
1601 static_cast<re_detail::re_brace*>(dat)->index = i;
1606 case traits_type::syntax_b: // re_detail::syntax_element_word_boundary
1607 dat = add_simple(dat, re_detail::syntax_element_word_boundary);
1610 case traits_type::syntax_B:
1611 dat = add_simple(dat, re_detail::syntax_element_within_word);
1614 case traits_type::syntax_left_word:
1615 dat = add_simple(dat, re_detail::syntax_element_word_start);
1618 case traits_type::syntax_right_word:
1619 dat = add_simple(dat, re_detail::syntax_element_word_end);
1622 case traits_type::syntax_w: //re_detail::syntax_element_word_char
1623 dat = compile_set_simple(dat, traits_type::char_class_word);
1626 case traits_type::syntax_W:
1627 dat = compile_set_simple(dat, traits_type::char_class_word, true);
1630 case traits_type::syntax_d: //re_detail::syntax_element_word_char
1631 dat = compile_set_simple(dat, traits_type::char_class_digit);
1634 case traits_type::syntax_D:
1635 dat = compile_set_simple(dat, traits_type::char_class_digit, true);
1638 case traits_type::syntax_s: //re_detail::syntax_element_word_char
1639 dat = compile_set_simple(dat, traits_type::char_class_space);
1642 case traits_type::syntax_S:
1643 dat = compile_set_simple(dat, traits_type::char_class_space, true);
1646 case traits_type::syntax_l: //re_detail::syntax_element_word_char
1647 dat = compile_set_simple(dat, traits_type::char_class_lower);
1650 case traits_type::syntax_L:
1651 dat = compile_set_simple(dat, traits_type::char_class_lower, true);
1654 case traits_type::syntax_u: //re_detail::syntax_element_word_char
1655 dat = compile_set_simple(dat, traits_type::char_class_upper);
1658 case traits_type::syntax_U:
1659 dat = compile_set_simple(dat, traits_type::char_class_upper, true);
1662 case traits_type::syntax_Q:
1669 return error_code();
1671 if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_slash)
1674 if((ptr != arg_last) && (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_E))
1678 dat = add_literal(dat, *(ptr-1));
1682 dat = add_literal(dat, *ptr);
1687 case traits_type::syntax_C:
1688 dat = add_simple(dat, re_detail::syntax_element_wild);
1691 case traits_type::syntax_X:
1692 dat = add_simple(dat, re_detail::syntax_element_combining);
1695 case traits_type::syntax_Z:
1696 dat = add_simple(dat, re_detail::syntax_element_soft_buffer_end);
1699 case traits_type::syntax_G:
1700 dat = add_simple(dat, re_detail::syntax_element_restart_continue);
1703 case traits_type::syntax_start_buffer:
1704 dat = add_simple(dat, re_detail::syntax_element_buffer_start);
1707 case traits_type::syntax_end_buffer:
1708 dat = add_simple(dat, re_detail::syntax_element_buffer_end);
1712 c = (traits_size_type)(traits_uchar_type)parse_escape(ptr, arg_last);
1713 dat = add_literal(dat, (charT)c);
1716 dat = add_literal(dat, (charT)c);
1720 case traits_type::syntax_dollar:
1721 dat = add_simple(dat, re_detail::syntax_element_end_line, sizeof(re_detail::re_syntax_base));
1724 case traits_type::syntax_caret:
1725 dat = add_simple(dat, re_detail::syntax_element_start_line, sizeof(re_detail::re_syntax_base));
1728 case traits_type::syntax_dot:
1729 dat = add_simple(dat, re_detail::syntax_element_wild, sizeof(re_detail::re_syntax_base));
1732 case traits_type::syntax_star:
1734 rep_max = (unsigned)-1;
1738 std::ptrdiff_t offset;
1742 return error_code();
1746 case re_detail::syntax_element_endmark:
1747 offset = last_mark_popped;
1749 case re_detail::syntax_element_literal:
1750 if(static_cast<re_detail::re_literal*>(dat)->length > 1)
1753 charT lit = *reinterpret_cast<charT*>(reinterpret_cast<char*>(dat) + sizeof(re_detail::re_literal) + ((static_cast<re_detail::re_literal*>(dat)->length-1)*sizeof(charT)));
1754 --static_cast<re_detail::re_literal*>(dat)->length;
1755 dat = add_simple(dat, re_detail::syntax_element_literal, sizeof(re_detail::re_literal) + sizeof(charT));
1756 static_cast<re_detail::re_literal*>(dat)->length = 1;
1757 *reinterpret_cast<charT*>(static_cast<re_detail::re_literal*>(dat)+1) = lit;
1759 offset = reinterpret_cast<char*>(dat) - reinterpret_cast<char*>(data.data());
1761 case re_detail::syntax_element_backref:
1762 case re_detail::syntax_element_long_set:
1763 case re_detail::syntax_element_set:
1764 case re_detail::syntax_element_wild:
1765 case re_detail::syntax_element_combining:
1766 // we're repeating a single item:
1767 offset = reinterpret_cast<char*>(dat) - reinterpret_cast<char*>(data.data());
1771 return error_code();
1774 dat->next.i = data.size();
1775 //unsigned pos = (char*)dat - (char*)data.data();
1777 // add the trailing jump:
1778 dat = add_simple(dat, re_detail::syntax_element_jump, re_detail::re_jump_size);
1779 static_cast<re_detail::re_jump*>(dat)->alt.i = 0;
1781 // now insert the leading repeater:
1782 dat = static_cast<re_detail::re_syntax_base*>(data.insert(offset, re_detail::re_repeater_size));
1783 dat->next.i = (reinterpret_cast<char*>(dat) - reinterpret_cast<char*>(data.data())) + re_detail::re_repeater_size;
1784 dat->type = re_detail::syntax_element_rep;
1785 static_cast<re_detail::re_repeat*>(dat)->alt.i = data.size();
1786 static_cast<re_detail::re_repeat*>(dat)->min = rep_min;
1787 static_cast<re_detail::re_repeat*>(dat)->max = rep_max;
1788 static_cast<re_detail::re_repeat*>(dat)->leading = false;
1789 static_cast<re_detail::re_repeat*>(dat)->greedy = true;
1790 move_offsets(dat, re_detail::re_repeater_size);
1793 // now check to see if we have a non-greedy repeat:
1794 if((ptr != arg_last) && (_flags & (perlex | limited_ops | bk_plus_qm | bk_braces)) == perlex)
1796 c = (traits_size_type)(traits_uchar_type)*ptr;
1797 if(traits_type::syntax_question == traits_inst.syntax_type(c))
1799 // OK repeat is non-greedy:
1800 static_cast<re_detail::re_repeat*>(dat)->greedy = false;
1804 dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + data.size() - re_detail::re_jump_size);
1805 static_cast<re_detail::re_repeat*>(dat)->alt.i = offset;
1808 case traits_type::syntax_plus:
1809 if(_flags & (bk_plus_qm | limited_ops))
1811 dat = add_literal(dat, (charT)c);
1816 rep_max = (unsigned)-1;
1818 case traits_type::syntax_question:
1819 if(_flags & (bk_plus_qm | limited_ops))
1821 dat = add_literal(dat, (charT)c);
1828 case traits_type::syntax_open_set:
1833 dat->next.i = data.size();
1836 dat = compile_set(ptr, arg_last);
1839 if((_flags & regex_constants::failbit) == 0)
1841 return error_code();
1844 case traits_type::syntax_or:
1846 if(_flags & (bk_vbar | limited_ops))
1848 dat = add_literal(dat, (charT)c);
1858 // start of pattern can't have empty "|"
1860 return error_code();
1862 // see if we have an empty alternative:
1863 if(mark.empty() == false)
1864 if(mark.peek() == data.index(dat))
1867 return error_code();
1870 dat = add_simple(dat, re_detail::syntax_element_jump, re_detail::re_jump_size);
1873 // we don't know what value to put here yet,
1874 // use an arbitrarily large value for now
1875 // and check it later (TODO!)
1876 static_cast<re_detail::re_jump*>(dat)->alt.i = INT_MAX/2;
1878 // now work out where to insert:
1879 std::size_t offset = 0;
1880 if(mark.empty() == false)
1882 // we have a '(' or '|' to go back to:
1883 offset = mark.peek();
1884 re_detail::re_syntax_base* base2 = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + offset);
1885 offset = base2->next.i;
1887 re_detail::re_jump* j = static_cast<re_detail::re_jump*>(data.insert(offset, re_detail::re_jump_size));
1888 j->type = re_detail::syntax_element_alt;
1889 j->next.i = offset + re_detail::re_jump_size;
1890 j->alt.i = data.size();
1891 move_offsets(j, re_detail::re_jump_size);
1892 dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + data.size() - re_detail::re_jump_size);
1893 mark.push(data.size() - re_detail::re_jump_size);
1897 case traits_type::syntax_open_brace:
1898 if((_flags & bk_braces) || ((_flags & intervals) == 0))
1900 dat = add_literal(dat, (charT)c);
1904 // we have {x} or {x,} or {x,y}:
1905 parse_range(ptr, arg_last, rep_min, rep_max);
1907 case traits_type::syntax_newline:
1908 if(_flags & newline_alt)
1909 goto alt_string_jump;
1910 dat = add_literal(dat, (charT)c);
1913 case traits_type::syntax_close_brace:
1914 if(_flags & bk_braces)
1916 dat = add_literal(dat, (charT)c);
1921 return error_code();
1923 dat = add_literal(dat, (charT)c);
1934 dat->next.i = data.size();
1937 // see if we have an empty alternative:
1938 if(mark.empty() == false)
1939 if(mark.peek() == data.index(dat) )
1941 re_detail::re_syntax_base* para = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + mark.peek());
1942 if(para->type == re_detail::syntax_element_jump)
1945 return error_code();
1951 if(mark.empty() == false)
1953 // pop any pushed alternatives and set the target arg_last destination:
1954 dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + mark.peek());
1955 while(dat->type == re_detail::syntax_element_jump)
1957 static_cast<re_detail::re_jump*>(dat)->alt.i = data.size();
1959 if(mark.empty() == true)
1961 dat = reinterpret_cast<re_detail::re_jump*>(reinterpret_cast<unsigned char*>(data.data()) + mark.peek());
1965 dat = static_cast<re_detail::re_brace*>(data.extend(sizeof(re_detail::re_syntax_base)));
1966 dat->type = re_detail::syntax_element_match;
1969 if(mark.empty() == false)
1972 return error_code();
1976 // allocate space for start _map:
1977 startmap = reinterpret_cast<unsigned char*>(data.extend(256 + ((arg_last - base + 1) * sizeof(charT))));
1979 // and copy the expression we just compiled:
1980 _expression = reinterpret_cast<charT*>(reinterpret_cast<char*>(startmap) + 256);
1981 _expression_len = arg_last - base;
1982 std::memcpy(_expression, base, _expression_len * sizeof(charT));
1983 *(_expression + _expression_len) = charT(0);
1986 // now we need to apply fixups to the array
1987 // so that we can use pointers and not indexes
1988 fixup_apply(static_cast<re_detail::re_syntax_base*>(data.data()), marks);
1990 // check for error during fixup:
1991 if(_flags & regex_constants::failbit)
1992 return error_code();
1995 // finally compile the maps so that we can make intelligent choices
1996 // whenever we encounter an alternative:
2000 re_detail::kmp_free(pkmp, data.allocator());
2003 re_detail::re_syntax_base* sbase = static_cast<re_detail::re_syntax_base*>(data.data());
2004 _restart_type = probe_restart(sbase);
2005 _leading_len = fixup_leading_rep(sbase, 0);
2006 if((sbase->type == re_detail::syntax_element_literal) && (sbase->next.p->type == re_detail::syntax_element_match))
2008 _restart_type = restart_fixed_lit;
2011 charT* p1 = reinterpret_cast<charT*>(reinterpret_cast<char*>(sbase) + sizeof(re_detail::re_literal));
2012 charT* p2 = p1 + static_cast<re_detail::re_literal*>(sbase)->length;
2013 pkmp = re_detail::kmp_compile(p1, p2, charT(), re_detail::kmp_translator<traits>(_flags®ex_constants::icase, &traits_inst), data.allocator());
2016 return error_code();
2022 # pragma warning(pop)
2027 template <class charT, class traits, class Allocator>
2028 re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::add_simple(re_detail::re_syntax_base* dat, re_detail::syntax_element_type type, unsigned int arg_size)
2033 dat->next.i = data.size();
2035 if(arg_size < sizeof(re_detail::re_syntax_base))
2036 arg_size = sizeof(re_detail::re_syntax_base);
2037 dat = static_cast<re_detail::re_syntax_base*>(data.extend(arg_size));
2043 template <class charT, class traits, class Allocator>
2044 re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::add_literal(re_detail::re_syntax_base* dat, charT c)
2046 if(dat && (dat->type == re_detail::syntax_element_literal))
2048 // add another charT to the list:
2049 std::ptrdiff_t pos = reinterpret_cast<unsigned char*>(dat) - reinterpret_cast<unsigned char*>(data.data());
2050 *reinterpret_cast<charT*>(data.extend(sizeof(charT))) = traits_inst.translate(c, (_flags & regex_constants::icase));
2051 dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + pos);
2052 ++(static_cast<re_detail::re_literal*>(dat)->length);
2057 dat = add_simple(dat, re_detail::syntax_element_literal, sizeof(re_detail::re_literal) + sizeof(charT));
2058 static_cast<re_detail::re_literal*>(dat)->length = 1;
2059 *reinterpret_cast<charT*>(reinterpret_cast<re_detail::re_literal*>(dat)+1) = traits_inst.translate(c, (_flags & regex_constants::icase));
2064 template <class charT, class traits, class Allocator>
2065 unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::probe_restart(re_detail::re_syntax_base* dat)
2069 case re_detail::syntax_element_startmark:
2070 case re_detail::syntax_element_endmark:
2071 if(static_cast<const re_detail::re_brace*>(dat)->index == -2)
2072 return regbase::restart_any;
2073 return probe_restart(dat->next.p);
2074 case re_detail::syntax_element_start_line:
2075 return regbase::restart_line;
2076 case re_detail::syntax_element_word_start:
2077 return regbase::restart_word;
2078 case re_detail::syntax_element_buffer_start:
2079 return regbase::restart_buf;
2080 case re_detail::syntax_element_restart_continue:
2081 return regbase::restart_continue;
2083 return regbase::restart_any;
2087 template <class charT, class traits, class Allocator>
2088 unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::fixup_leading_rep(re_detail::re_syntax_base* dat, re_detail::re_syntax_base* arg_end)
2090 unsigned int len = 0;
2091 bool leading_lit = arg_end ? false : true;
2092 while(dat != arg_end)
2096 case re_detail::syntax_element_literal:
2097 len += static_cast<re_detail::re_literal*>(dat)->length;
2098 if((leading_lit) && (static_cast<re_detail::re_literal*>(dat)->length > 2))
2100 // we can do a literal search for the leading literal string
2101 // using Knuth-Morris-Pratt (or whatever), and only then check for
2102 // matches. We need a decent length string though to make it
2104 _leading_string = reinterpret_cast<charT*>(reinterpret_cast<char*>(dat) + sizeof(re_detail::re_literal));
2105 _leading_string_len = static_cast<re_detail::re_literal*>(dat)->length;
2106 _restart_type = restart_lit;
2107 leading_lit = false;
2108 const charT* p1 = _leading_string;
2109 const charT* p2 = _leading_string + _leading_string_len;
2110 pkmp = re_detail::kmp_compile(p1, p2, charT(), re_detail::kmp_translator<traits>(_flags®ex_constants::icase, &traits_inst), data.allocator());
2112 leading_lit = false;
2114 case re_detail::syntax_element_wild:
2116 leading_lit = false;
2118 case re_detail::syntax_element_match:
2120 case re_detail::syntax_element_backref:
2121 //case re_detail::syntax_element_jump:
2122 case re_detail::syntax_element_alt:
2123 case re_detail::syntax_element_combining:
2125 case re_detail::syntax_element_long_set:
2127 // we need to verify that there are no multi-character
2128 // collating elements inside the repeat:
2129 if(!static_cast<re_detail::re_set_long*>(dat)->singleton)
2132 leading_lit = false;
2135 case re_detail::syntax_element_set:
2137 leading_lit = false;
2139 case re_detail::syntax_element_rep:
2140 case re_detail::syntax_element_dot_rep:
2141 case re_detail::syntax_element_char_rep:
2142 case re_detail::syntax_element_short_set_rep:
2143 case re_detail::syntax_element_long_set_rep:
2144 if((len == 0) && (1 == fixup_leading_rep(dat->next.p, static_cast<re_detail::re_repeat*>(dat)->alt.p) ))
2146 static_cast<re_detail::re_repeat*>(dat)->leading = leading_lit;
2150 case re_detail::syntax_element_startmark:
2151 if(static_cast<const re_detail::re_brace*>(dat)->index == -2)
2162 template <class charT, class traits, class Allocator>
2163 void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::fail(unsigned int err)
2168 _flags |= regex_constants::failbit;
2169 #ifndef BOOST_NO_EXCEPTIONS
2170 if(_flags & regex_constants::use_except)
2172 re_detail::raise_error(traits_inst, err);
2177 _flags &= ~regex_constants::failbit;
2183 #ifdef BOOST_HAS_ABI_HEADERS
2184 # include BOOST_ABI_SUFFIX
2187 } // namespace boost
2190 #endif // BOOST_REGEX_COMPILE_HPP