3 * Copyright (c) 1998-2000
6 * Permission to use, copy, modify, distribute and sell this software
7 * and its documentation for any purpose is hereby granted without fee,
8 * provided that the above copyright notice appear in all copies and
9 * that both that copyright notice and this permission notice appear
10 * in supporting documentation. Dr John Maddock makes no representations
11 * about the suitability of this software for any purpose.
12 * It is provided "as is" without express or implied warranty.
17 * LOCATION: see http://www.boost.org for most recent version.
20 * DESCRIPTION: Declares boost::reg_expression<> and associated
21 * functions and classes. This header is the main
22 * entry point for the template regex code.
26 /* start with C compatability API */
28 #ifndef BOOST_RE_REGEX_HPP
29 #define BOOST_RE_REGEX_HPP
31 #include <boost/cregex.hpp>
35 // what follows is all C++ don't include in C builds!!
42 #include <boost/re_detail/regex_config.hpp>
43 #if !defined(BOOST_RE_NO_TYPEINFO)
47 #include <boost/re_detail/regex_stack.hpp>
48 #include <boost/re_detail/regex_raw_buffer.hpp>
49 #include <boost/re_detail/regex_kmp.hpp>
50 #include <boost/pattern_except.hpp>
51 #include <boost/regex_traits.hpp>
52 #include <boost/type_traits.hpp>
58 #if __BORLANDC__ == 0x530
59 #pragma option push -a4 -b -Ve
60 #elif __BORLANDC__ > 0x530
61 #pragma option push -a8 -b -Ve
68 struct re_syntax_base
;
70 } // namespace re_detail
74 // class char_regex_traits_i
75 // provides case insensitive traits classes (deprecated):
76 template <class charT
>
77 class char_regex_traits_i
: public regex_traits
<charT
> {};
80 class char_regex_traits_i
<char> : public regex_traits
<char>
83 typedef char char_type
;
84 typedef unsigned char uchar_type
;
85 typedef unsigned int size_type
;
86 typedef regex_traits
<char> base_type
;
88 char BOOST_RE_CALL
translate(char c
, bool)const
90 return static_cast<const regex_traits
<char>*>(this)->translate(c
, true);
94 #ifndef BOOST_RE_NO_WCSTRING
96 class char_regex_traits_i
<wchar_t> : public regex_traits
<wchar_t>
99 typedef wchar_t char_type
;
100 typedef unsigned short uchar_type
;
101 typedef unsigned int size_type
;
102 typedef regex_traits
<wchar_t> base_type
;
104 wchar_t BOOST_RE_CALL
translate(wchar_t c
, bool)const
106 return static_cast<const regex_traits
<wchar_t>*>(this)->translate(c
, true);
108 jm_uintfast32_t BOOST_RE_CALL
lookup_classname(const wchar_t* first
, const wchar_t* last
)const
110 jm_uintfast32_t result
= static_cast<const regex_traits
<wchar_t>*>(this)->lookup_classname(first
, last
);
111 if((result
& base_type::char_class_upper
) == base_type::char_class_upper
)
112 result
|= base_type::char_class_alpha
;
117 } // namespace deprecated
126 mask_any
= mask_skip
| mask_take
,
130 struct _narrow_type
{};
133 template <class charT
>
140 typedef _narrow_type width_type
;
144 class is_byte
<unsigned char>
147 typedef _narrow_type width_type
;
151 class is_byte
<signed char>
154 typedef _narrow_type width_type
;
157 template <class charT
>
161 typedef _wide_type width_type
;
166 // compiled structures
168 // the following defs describe the format of the compiled string
172 // enum syntax_element_type
173 // describes the type of a record
174 enum syntax_element_type
176 syntax_element_startmark
= 0,
177 syntax_element_endmark
= syntax_element_startmark
+ 1,
178 syntax_element_literal
= syntax_element_endmark
+ 1,
179 syntax_element_start_line
= syntax_element_literal
+ 1,
180 syntax_element_end_line
= syntax_element_start_line
+ 1,
181 syntax_element_wild
= syntax_element_end_line
+ 1,
182 syntax_element_match
= syntax_element_wild
+ 1,
183 syntax_element_word_boundary
= syntax_element_match
+ 1,
184 syntax_element_within_word
= syntax_element_word_boundary
+ 1,
185 syntax_element_word_start
= syntax_element_within_word
+ 1,
186 syntax_element_word_end
= syntax_element_word_start
+ 1,
187 syntax_element_buffer_start
= syntax_element_word_end
+ 1,
188 syntax_element_buffer_end
= syntax_element_buffer_start
+ 1,
189 syntax_element_backref
= syntax_element_buffer_end
+ 1,
190 syntax_element_long_set
= syntax_element_backref
+ 1,
191 syntax_element_set
= syntax_element_long_set
+ 1,
192 syntax_element_jump
= syntax_element_set
+ 1,
193 syntax_element_alt
= syntax_element_jump
+ 1,
194 syntax_element_rep
= syntax_element_alt
+ 1,
195 syntax_element_combining
= syntax_element_rep
+ 1,
196 syntax_element_soft_buffer_end
= syntax_element_combining
+ 1,
197 syntax_element_restart_continue
= syntax_element_soft_buffer_end
+ 1
200 #ifdef BOOST_RE_DEBUG
201 // dwa 09/26/00 - This is needed to suppress warnings about an ambiguous conversion
202 std::ostream
& operator<<(std::ostream
&, syntax_element_type
);
212 // struct re_syntax_base
213 // base class for all syntax types:
214 struct re_syntax_base
216 syntax_element_type type
;
218 unsigned int can_be_null
;
223 // marks start or end of (...)
224 struct re_brace
: public re_syntax_base
231 // marks a literal string and
232 // is followed by an array of charT[length]:
233 struct re_literal
: public re_syntax_base
239 // struct re_long_set
240 // provides data for sets [...] containing
242 struct re_set_long
: public re_syntax_base
244 unsigned int csingles
, cranges
, cequivalents
;
245 jm_uintfast32_t cclasses
;
251 // provides a map of bools for sets containing
252 // narrow, single byte characters.
253 struct re_set
: public re_syntax_base
255 unsigned char _map
[256];
260 // provides alternative next destination
261 struct re_jump
: public re_syntax_base
264 unsigned char _map
[256];
269 // provides repeat expressions
270 struct re_repeat
: public re_jump
280 // enum re_jump_size_type
281 // provides compiled size of re_jump
282 // allowing for trailing alignment
283 // provide this so we know how many
285 enum re_jump_size_type
287 re_jump_size
= (sizeof(re_jump
) + padding_mask
) & ~(padding_mask
),
288 re_repeater_size
= (sizeof(re_repeat
) + padding_mask
) & ~(padding_mask
)
291 } // namespace re_detail
295 // handles error codes and flags
297 class BOOST_RE_IX_DECL regbase
302 escape_in_lists
= 1, // '\' special inside [...]
303 char_classes
= escape_in_lists
<< 1, // [[:CLASS:]] allowed
304 intervals
= char_classes
<< 1, // {x,y} allowed
305 limited_ops
= intervals
<< 1, // all of + ? and | are normal characters
306 newline_alt
= limited_ops
<< 1, // \n is the same as |
307 bk_plus_qm
= newline_alt
<< 1, // uses \+ and \?
308 bk_braces
= bk_plus_qm
<< 1, // uses \{ and \}
309 bk_parens
= bk_braces
<< 1, // uses \( and \)
310 bk_refs
= bk_parens
<< 1, // \d allowed
311 bk_vbar
= bk_refs
<< 1, // uses \|
313 use_except
= bk_vbar
<< 1, // exception on error
314 failbit
= use_except
<< 1, // error flag
315 literal
= failbit
<< 1, // all characters are literals
316 icase
= literal
<< 1, // characters are matched regardless of case
317 nocollate
= icase
<< 1, // don't use locale specific collation
319 basic
= char_classes
| intervals
| limited_ops
| bk_braces
| bk_parens
| bk_refs
,
320 extended
= char_classes
| intervals
| bk_refs
,
321 normal
= escape_in_lists
| char_classes
| intervals
| bk_refs
| nocollate
,
322 emacs
= bk_braces
| bk_parens
| bk_refs
| bk_vbar
,
323 awk
= extended
| escape_in_lists
,
324 grep
= basic
| newline_alt
,
325 egrep
= extended
| newline_alt
,
329 typedef unsigned int flag_type
;
337 restart_continue
= 4,
339 restart_fixed_lit
= 6
342 flag_type BOOST_RE_CALL
flags()const
348 regbase(const regbase
& b
);
354 // some forward declarations:
356 template <class iterator
, class Allocator
>
357 class _priv_match_data
;
359 #if defined(BOOST_NO_STD_ITERATOR_TRAITS) || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
362 struct regex_iterator_traits
364 typedef typename
T::iterator_category iterator_category
;
365 typedef typename
T::value_type value_type
;
367 typedef typename
T::difference_type difference_type
;
368 typedef typename
T::pointer pointer
;
369 typedef typename
T::reference reference
;
371 typedef std::ptrdiff_t difference_type
;
372 typedef value_type
* pointer
;
373 typedef value_type
& reference
;
378 struct pointer_iterator_traits
380 typedef std::ptrdiff_t difference_type
;
381 typedef T value_type
;
383 typedef T
& reference
;
384 typedef std::random_access_iterator_tag iterator_category
;
387 struct const_pointer_iterator_traits
389 typedef std::ptrdiff_t difference_type
;
390 typedef T value_type
;
391 typedef const T
* pointer
;
392 typedef const T
& reference
;
393 typedef std::random_access_iterator_tag iterator_category
;
397 struct regex_iterator_traits
<char*> : pointer_iterator_traits
<char>{};
399 struct regex_iterator_traits
<const char*> : const_pointer_iterator_traits
<char>{};
401 struct regex_iterator_traits
<wchar_t*> : pointer_iterator_traits
<wchar_t>{};
403 struct regex_iterator_traits
<const wchar_t*> : const_pointer_iterator_traits
<wchar_t>{};
405 #if defined(__SGI_STL_PORT) && defined(__STL_DEBUG)
407 struct regex_iterator_traits
<std::string::iterator
> : pointer_iterator_traits
<char>{};
409 struct regex_iterator_traits
<std::string::const_iterator
> : const_pointer_iterator_traits
<char>{};
410 #ifndef BOOST_NO_WSTRING
412 struct regex_iterator_traits
<std::wstring::iterator
> : pointer_iterator_traits
<wchar_t>{};
414 struct regex_iterator_traits
<std::wstring::const_iterator
> : const_pointer_iterator_traits
<wchar_t>{};
415 #endif // BOOST_NO_WSTRING
421 struct regex_iterator_traits
: public std::iterator_traits
<T
> {};
426 struct def_alloc_param_traits
428 typedef typename regex_iterator_traits
<I
>::value_type const_value_type
;
429 typedef typename remove_cv
<const_value_type
>::type type
;
434 template <class iterator
, class Allocator
BOOST_RE_DEF_ALLOC_PARAM(typename
re_detail::def_alloc_param_traits
<iterator
>::type
) >
438 // class reg_expression
439 // represents the compiled
440 // regular expression:
443 #if defined(BOOST_RE_NO_TEMPLATE_SWITCH_MERGE) && !defined(BOOST_RE_NO_NAMESPACES)
446 // template don't merge if they contain switch statements so declare these
447 // templates in unnamed namespace (ie with internal linkage), each translation
448 // unit then gets its own local copy, it works seemlessly but bloats the app.
452 template <class charT
, class traits
BOOST_RE_TRICKY_DEFAULT_PARAM(regex_traits
<charT
>), class Allocator
BOOST_RE_DEF_ALLOC_PARAM(charT
) >
453 class reg_expression
: public regbase
455 typedef typename
traits::size_type traits_size_type
;
456 typedef typename
traits::uchar_type traits_uchar_type
;
457 typedef typename
traits::string_type traits_string_type
;
460 typedef charT char_type
;
461 typedef traits traits_type
;
464 // placeholder for actual locale type used by the
465 // traits class to localise *this.
466 typedef typename
traits::locale_type locale_type
;
468 typedef charT value_type
;
469 // reference, const_reference
470 typedef charT
& reference
;
471 typedef const charT
& const_reference
;
472 // iterator, const_iterator
473 typedef const charT
* const_iterator
;
474 typedef const_iterator iterator
;
476 typedef typename
Allocator::difference_type difference_type
;
478 typedef typename
Allocator::size_type size_type
;
480 typedef Allocator allocator_type
;
481 typedef Allocator alloc_type
;
483 typedef regbase::flag_type flag_type
;
486 explicit reg_expression(const Allocator
& a
= Allocator());
487 explicit reg_expression(const charT
* p
, flag_type f
= regbase::normal
, const Allocator
& a
= Allocator());
488 reg_expression(const charT
* p1
, const charT
* p2
, flag_type f
= regbase::normal
, const Allocator
& a
= Allocator());
489 reg_expression(const charT
* p
, size_type len
, flag_type f
, const Allocator
& a
= Allocator());
490 reg_expression(const reg_expression
&);
492 reg_expression
& BOOST_RE_CALL
operator=(const reg_expression
&);
493 reg_expression
& BOOST_RE_CALL
operator=(const charT
* ptr
)
495 set_expression(ptr
, regbase::normal
| regbase::use_except
);
501 reg_expression
& assign(const reg_expression
& that
)
502 { return *this = that
; }
503 reg_expression
& assign(const charT
* ptr
, flag_type f
= regbase::normal
)
505 set_expression(ptr
, f
| regbase::use_except
);
509 reg_expression
& assign(const charT
* first
,
511 flag_type f
= regbase::normal
)
513 set_expression(first
, last
, f
| regbase::use_except
);
516 #ifndef BOOST_RE_NO_MEMBER_TEMPLATES
518 template <class ST
, class SA
>
519 unsigned int BOOST_RE_CALL
set_expression(const std::basic_string
<charT
, ST
, SA
>& p
, flag_type f
= regbase::normal
)
520 { return set_expression(p
.data(), p
.data() + p
.size(), f
); }
522 template <class ST
, class SA
>
523 explicit reg_expression(const std::basic_string
<charT
, ST
, SA
>& p
, flag_type f
= regbase::normal
, const Allocator
& a
= Allocator())
524 : data(a
), pkmp(0) { set_expression(p
, f
); }
527 reg_expression(I first
, I last
, flag_type f
= regbase::normal
, const Allocator
& a
= Allocator())
530 size_type len
= last
-first
;
531 scoped_array
<charT
> a(new charT
[len
]);
532 std::copy(first
, last
, a
.get());
533 set_expression(a
.get(), a
.get() + len
, f
| regbase::use_except
);
536 template <class ST
, class SA
>
537 reg_expression
& BOOST_RE_CALL
operator=(const std::basic_string
<charT
, ST
, SA
>& p
)
539 set_expression(p
.c_str(), p
.c_str() + p
.size(), regbase::normal
| regbase::use_except
);
543 template <class string_traits
, class A
>
544 reg_expression
& BOOST_RE_CALL
assign(
545 const std::basic_string
<charT
, string_traits
, A
>& s
,
546 flag_type f
= regbase::normal
)
548 set_expression(p
.c_str(), p
.c_str() + p
.size(), f
| regbase::use_except
);
552 template <class fwd_iterator
>
553 reg_expression
& BOOST_RE_CALL
assign(fwd_iterator first
,
555 flag_type f
= regbase::normal
)
557 size_type len
= last
-first
;
558 scoped_array
<charT
> a(new charT
[len
]);
559 std::copy(first
, last
, a
.get());
560 set_expression(a
.get(), a
.get() + len
, f
| regbase::use_except
);
563 #elif !defined(BOOST_RE_NO_STRING_DEF_ARGS)
564 unsigned int BOOST_RE_CALL
set_expression(const std::basic_string
<charT
>& p
, flag_type f
= regbase::normal
)
565 { return set_expression(p
.data(), p
.data() + p
.size(), f
); }
567 reg_expression(const std::basic_string
<charT
>& p
, flag_type f
= regbase::normal
, const Allocator
& a
= Allocator())
568 : data(a
), pkmp(0) { set_expression(p
, f
); }
570 reg_expression
& BOOST_RE_CALL
operator=(const std::basic_string
<charT
>& p
)
572 set_expression(p
.c_str(), p
.c_str() + p
.size(), regbase::normal
| regbase::use_except
);
576 reg_expression
& BOOST_RE_CALL
assign(
577 const std::basic_string
<charT
>& s
,
578 flag_type f
= regbase::normal
)
580 set_expression(s
.c_str(), s
.c_str() + s
.size(), f
| regbase::use_except
);
589 Allocator BOOST_RE_CALL
get_allocator()const;
592 locale_type BOOST_RE_CALL
imbue(locale_type l
){ return traits_inst
.imbue(l
); }
593 locale_type BOOST_RE_CALL
getloc()const{ return traits_inst
.getloc(); }
596 flag_type BOOST_RE_CALL
getflags()const
600 std::basic_string
<charT
> BOOST_RE_CALL
str()const
601 { return std::basic_string
<charT
>(_expression
, _expression_len
); }
604 const_iterator BOOST_RE_CALL
begin()const
605 { return _expression
; }
606 const_iterator BOOST_RE_CALL
end()const
607 { return _expression
+ _expression_len
; }
610 void BOOST_RE_CALL
swap(reg_expression
&)throw();
613 size_type BOOST_RE_CALL
size()const
614 { return _expression_len
; }
617 size_type BOOST_RE_CALL
max_size()const
621 bool BOOST_RE_CALL
empty()const
622 { return this->error_code(); }
624 unsigned BOOST_RE_CALL
mark_count()const { return marks
; }
625 bool BOOST_RE_CALL
operator==(const reg_expression
&)const;
626 bool BOOST_RE_CALL
operator<(const reg_expression
&)const;
628 // The following are deprecated as public interfaces
629 // but are available for compatability with earlier versions.
630 allocator_type BOOST_RE_CALL
allocator()const;
631 const charT
* BOOST_RE_CALL
expression()const { return _expression
; }
632 unsigned int BOOST_RE_CALL
set_expression(const charT
* p
, const charT
* end
, flag_type f
= regbase::normal
);
633 unsigned int BOOST_RE_CALL
set_expression(const charT
* p
, flag_type f
= regbase::normal
) { return set_expression(p
, p
+ traits_type::length(p
), f
); }
635 // this should be private but template friends don't work:
636 const traits_type
& get_traits()const { return traits_inst
; }
637 unsigned int BOOST_RE_CALL
error_code()const
643 re_detail::raw_storage
<Allocator
> data
;
644 unsigned _restart_type
;
647 unsigned char* startmap
;
649 unsigned _expression_len
;
650 unsigned int _leading_len
;
651 const charT
* _leading_string
;
652 unsigned int _leading_string_len
;
653 re_detail::kmp_info
<charT
>* pkmp
;
654 traits_type traits_inst
;
655 unsigned error_code_
;
657 void BOOST_RE_CALL
compile_maps();
658 void BOOST_RE_CALL
compile_map(re_detail::re_syntax_base
* node
, unsigned char* _map
, unsigned int* pnull
, unsigned char mask
, re_detail::re_syntax_base
* terminal
= NULL
)const;
659 bool BOOST_RE_CALL
probe_start(re_detail::re_syntax_base
* node
, charT c
, re_detail::re_syntax_base
* terminal
)const;
660 bool BOOST_RE_CALL
probe_start_null(re_detail::re_syntax_base
* node
, re_detail::re_syntax_base
* terminal
)const;
661 void BOOST_RE_CALL
fixup_apply(re_detail::re_syntax_base
* b
, unsigned cbraces
);
662 void BOOST_RE_CALL
move_offsets(re_detail::re_syntax_base
* j
, unsigned size
);
663 re_detail::re_syntax_base
* BOOST_RE_CALL
compile_set(const charT
*& first
, const charT
* last
);
664 re_detail::re_syntax_base
* BOOST_RE_CALL
compile_set_aux(re_detail::jstack
<traits_string_type
, Allocator
>& singles
, re_detail::jstack
<traits_string_type
, Allocator
>& ranges
, re_detail::jstack
<jm_uintfast32_t
, Allocator
>& classes
, re_detail::jstack
<traits_string_type
, Allocator
>& equivalents
, bool isnot
, const re_detail::_narrow_type
&);
665 re_detail::re_syntax_base
* BOOST_RE_CALL
compile_set_aux(re_detail::jstack
<traits_string_type
, Allocator
>& singles
, re_detail::jstack
<traits_string_type
, Allocator
>& ranges
, re_detail::jstack
<jm_uintfast32_t
, Allocator
>& classes
, re_detail::jstack
<traits_string_type
, Allocator
>& equivalents
, bool isnot
, const re_detail::_wide_type
&);
666 re_detail::re_syntax_base
* BOOST_RE_CALL
compile_set_simple(re_detail::re_syntax_base
* dat
, unsigned long cls
, bool isnot
= false);
667 unsigned int BOOST_RE_CALL
parse_inner_set(const charT
*& first
, const charT
* last
);
669 re_detail::re_syntax_base
* BOOST_RE_CALL
add_simple(re_detail::re_syntax_base
* dat
, re_detail::syntax_element_type type
, unsigned int size
= sizeof(re_detail::re_syntax_base
));
670 re_detail::re_syntax_base
* BOOST_RE_CALL
add_literal(re_detail::re_syntax_base
* dat
, charT c
);
671 charT BOOST_RE_CALL
parse_escape(const charT
*& first
, const charT
* last
);
672 void BOOST_RE_CALL
parse_range(const charT
*& first
, const charT
* last
, unsigned& min
, unsigned& max
);
673 bool BOOST_RE_CALL
skip_space(const charT
*& first
, const charT
* last
);
674 unsigned int BOOST_RE_CALL
probe_restart(re_detail::re_syntax_base
* dat
);
675 unsigned int BOOST_RE_CALL
fixup_leading_rep(re_detail::re_syntax_base
* dat
, re_detail::re_syntax_base
* end
);
676 void BOOST_RE_CALL
fail(unsigned int err
);
679 static int BOOST_RE_CALL
repeat_count(const reg_expression
& e
)
680 { return e
.repeats
; }
681 static unsigned int BOOST_RE_CALL
restart_type(const reg_expression
& e
)
682 { return e
._restart_type
; }
683 static const re_detail::re_syntax_base
* BOOST_RE_CALL
first(const reg_expression
& e
)
684 { return (const re_detail::re_syntax_base
*)e
.data
.data(); }
685 static const unsigned char* BOOST_RE_CALL
get_map(const reg_expression
& e
)
686 { return e
.startmap
; }
687 static unsigned int BOOST_RE_CALL
leading_length(const reg_expression
& e
)
688 { return e
._leading_len
; }
689 static const re_detail::kmp_info
<charT
>* get_kmp(const reg_expression
& e
)
691 static bool BOOST_RE_CALL
can_start(charT c
, const unsigned char* _map
, unsigned char mask
, const re_detail::_wide_type
&);
692 static bool BOOST_RE_CALL
can_start(charT c
, const unsigned char* _map
, unsigned char mask
, const re_detail::_narrow_type
&);
695 template <class charT
, class traits
, class Allocator
>
696 void BOOST_RE_CALL reg_expression
<charT
, traits
, Allocator
>::swap(reg_expression
& that
)throw()
698 // this is not as efficient as it should be,
699 // however swapping traits classes is problematic
700 // so just use 'brute force' method for now:
701 reg_expression
<charT
, traits
, Allocator
> e(that
);
707 #if defined(BOOST_RE_NO_TEMPLATE_SWITCH_MERGE) && !defined(BOOST_RE_NO_NAMESPACES)
712 // class match_results and match_results_base
713 // handles what matched where
715 template <class iterator
>
718 typedef typename
re_detail::regex_iterator_traits
<iterator
>::value_type value_type
;
719 #if defined(BOOST_NO_STD_ITERATOR_TRAITS) || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
720 typedef std::ptrdiff_t difference_type
;
722 typedef typename
re_detail::regex_iterator_traits
<iterator
>::difference_type difference_type
;
724 typedef iterator iterator_type
;
730 operator std::basic_string
<value_type
> ()const
732 std::basic_string
<value_type
> result
;
734 BOOST_RE_DISTANCE((iterator
)first
, (iterator
)second
, len
);
739 result
.append(1, *i
);
744 #ifdef BOOST_OLD_REGEX_H
746 // the following are deprecated, do not use!!
749 operator unsigned int()const;
750 operator short()const
752 return (short)(int)(*this);
754 operator unsigned short()const
756 return (unsigned short)(unsigned int)(*this);
759 sub_match() { matched
= false; }
760 sub_match(iterator i
) : first(i
), second(i
), matched(false) {}
762 bool operator==(const sub_match
& that
)const
764 return (first
== that
.first
) && (second
== that
.second
) && (matched
== that
.matched
);
766 bool BOOST_RE_CALL
operator !=(const sub_match
& that
)const
767 { return !(*this == that
); }
769 difference_type BOOST_RE_CALL
length()const
772 BOOST_RE_DISTANCE((iterator
)first
, (iterator
)second
, n
);
777 #ifdef BOOST_OLD_REGEX_H
779 template <class iterator
, class charT
>
780 int do_toi(iterator i
, iterator j
, char c
, int radix
)
784 int result
= std::strtol(s
.c_str(), &p
, radix
);
785 if(*p
)throw bad_pattern("Bad sub-expression");
791 template <class I
, class charT
>
792 int do_toi(I
& i
, I j
, charT c
)
795 while((i
!= j
) && (isdigit(*i
)))
797 result
= result
*10 + (*i
- '0');
805 template <class iterator
>
806 sub_match
<iterator
>::operator int()const
810 if(i
== j
)throw bad_pattern("Bad sub-expression");
812 if((i
!= j
) && (*i
== '-'))
817 neg
*= re_detail::do_toi(i
, j
, *i
);
818 if(i
!= j
)throw bad_pattern("Bad sub-expression");
821 template <class iterator
>
822 sub_match
<iterator
>::operator unsigned int()const
827 throw bad_pattern("Bad sub-expression");
828 return re_detail::do_toi(i
, j
, *first
);
834 template <class iterator
, class Allocator
BOOST_RE_DEF_ALLOC_PARAM(typename def_alloc_param_traits
<iterator
>::type
) >
835 class match_results_base
838 typedef Allocator alloc_type
;
839 typedef typename
REBIND_TYPE(iterator
, Allocator
)::size_type size_type
;
840 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
841 typedef typename
std::iterator_traits
<iterator
>::difference_type difference_type
;
842 typedef typename
std::iterator_traits
<iterator
>::value_type char_type
;
844 typedef std::ptrdiff_t difference_type
;
846 typedef sub_match
<iterator
> value_type
;
847 typedef iterator iterator_type
;
850 typedef BOOST_RE_MAYBE_TYPENAME
REBIND_TYPE(char, Allocator
) c_alloc
;
852 struct c_reference
: public c_alloc
854 unsigned int cmatches
;
856 sub_match
<iterator
> head
, tail
, null
;
858 iterator line_pos
, base
;
859 c_reference(const Allocator
& a
) : c_alloc(a
) { }
861 bool operator==(const c_reference
& that
)const
863 return (cmatches
== that
.cmatches
) &&
864 (count
== that
.count
) &&
865 (head
== that
.head
) &&
866 (tail
== that
.tail
) &&
867 (lines
== that
.lines
) &&
870 bool operator!=(const c_reference
& that
)const
871 { return !(*this == that
); }
876 void BOOST_RE_CALL
cow();
878 // protected contructor for derived class...
879 match_results_base(bool){}
880 void BOOST_RE_CALL
free();
884 match_results_base(const Allocator
& a
= Allocator());
886 match_results_base(const match_results_base
& m
)
892 match_results_base
& BOOST_RE_CALL
operator=(const match_results_base
& m
);
894 ~match_results_base()
899 size_type BOOST_RE_CALL
size()const
901 //return (*this)[0].matched ? ref->cmatches : 0;
902 return ref
->cmatches
;
905 const sub_match
<iterator
>& BOOST_RE_CALL
operator[](int n
) const
907 if((n
>= 0) && ((unsigned int)n
< ref
->cmatches
))
908 return *(sub_match
<iterator
>*)((char*)ref
+ sizeof(c_reference
) + sizeof(sub_match
<iterator
>)*n
);
909 return (n
== -1) ? ref
->head
: (n
== -2) ? ref
->tail
: ref
->null
;
912 Allocator BOOST_RE_CALL
allocator()const;
914 difference_type BOOST_RE_CALL
length(unsigned int sub
= 0)const
916 jm_assert(ref
->cmatches
);
917 const sub_match
<iterator
>& m
= (*this)[sub
];
918 if(m
.matched
== false)
921 BOOST_RE_DISTANCE((iterator
)m
.first
, (iterator
)m
.second
, n
);
925 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
926 std::basic_string
<value_type
> str(int i
)const
928 return static_cast<std::basic_string
<value_type
> >((*this)[i
]);
931 std::basic_string
<char> str(int i
)const
933 return static_cast<std::basic_string
<char> >((*this)[i
]);
937 unsigned int BOOST_RE_CALL
line()const
942 difference_type BOOST_RE_CALL
position(unsigned int sub
= 0)const
944 jm_assert(ref
->cmatches
);
945 const sub_match
<iterator
>& s
= (*this)[sub
];
946 if(s
.matched
== false)
949 BOOST_RE_DISTANCE((iterator
)ref
->base
, (iterator
)s
.first
, n
);
953 iterator BOOST_RE_CALL
line_start()const
955 return ref
->line_pos
;
958 void swap(match_results_base
& that
)
960 c_reference
* t
= that
.ref
;
965 bool operator==(const match_results_base
& that
)const;
966 bool operator<(const match_results_base
& that
)const
967 { return position() < that
.position(); }
969 friend class match_results
<iterator
, Allocator
>;
971 void BOOST_RE_CALL
set_size(size_type n
);
972 void BOOST_RE_CALL
set_size(size_type n
, iterator i
, iterator j
);
973 void BOOST_RE_CALL
maybe_assign(const match_results_base
& m
);
974 void BOOST_RE_CALL
init_fail(iterator i
, iterator j
);
976 void BOOST_RE_CALL
set_first(iterator i
);
977 void BOOST_RE_CALL
set_first(iterator i
, size_t pos
);
979 void BOOST_RE_CALL
set_second(iterator i
)
982 ((sub_match
<iterator
>*)(ref
+1))->second
= i
;
983 ((sub_match
<iterator
>*)(ref
+1))->matched
= true;
985 ref
->tail
.matched
= (ref
->tail
.first
== ref
->tail
.second
) ? false : true;
988 void BOOST_RE_CALL
set_second(iterator i
, size_t pos
)
991 ((sub_match
<iterator
>*)((char*)ref
+ sizeof(c_reference
) + sizeof(sub_match
<iterator
>) * pos
))->second
= i
;
992 ((sub_match
<iterator
>*)((char*)ref
+ sizeof(c_reference
) + sizeof(sub_match
<iterator
>) * pos
))->matched
= true;
996 ref
->tail
.matched
= (ref
->tail
.first
== ref
->tail
.second
) ? false : true;
1000 void BOOST_RE_CALL
set_line(unsigned int i
, iterator pos
)
1003 ref
->line_pos
= pos
;
1006 void BOOST_RE_CALL
set_base(iterator pos
)
1012 template <class iterator
, class Allocator
>
1013 void BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::set_first(iterator i
)
1016 ref
->head
.second
= i
;
1017 ref
->head
.matched
= (ref
->head
.first
== ref
->head
.second
) ? false : true;
1018 sub_match
<iterator
>* p1
= (sub_match
<iterator
>*)(ref
+1);
1019 sub_match
<iterator
>* p2
= p1
+ ref
->cmatches
;
1021 p1
->matched
= false;
1025 p1
->matched
= false;
1026 p1
->first
= ref
->tail
.second
;
1027 p1
->second
= ref
->tail
.second
;
1032 template <class iterator
, class Allocator
>
1033 void BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::set_first(iterator i
, size_t pos
)
1036 ((sub_match
<iterator
>*)((char*)ref
+ sizeof(c_reference
) + sizeof(sub_match
<iterator
>) * pos
))->first
= i
;
1039 ref
->head
.second
= i
;
1040 ref
->head
.matched
= (ref
->head
.first
== ref
->head
.second
) ? false : true;
1041 sub_match
<iterator
>* p1
= (sub_match
<iterator
>*)(ref
+1);
1042 sub_match
<iterator
>* p2
= p1
+ ref
->cmatches
;
1044 p1
->matched
= false;
1048 p1
->matched
= false;
1049 p1
->first
= ref
->tail
.second
;
1050 p1
->second
= ref
->tail
.second
;
1057 template <class iterator
, class Allocator
>
1058 match_results_base
<iterator
, Allocator
>::match_results_base(const Allocator
& a
)
1060 ref
= (c_reference
*)c_alloc(a
).allocate(sizeof(sub_match
<iterator
>) + sizeof(c_reference
));
1063 new (ref
) c_reference(a
);
1066 // construct the sub_match<iterator>:
1069 new ((sub_match
<iterator
>*)(ref
+1)) sub_match
<iterator
>();
1079 c_alloc(a
).deallocate((char*)(void*)ref
, sizeof(sub_match
<iterator
>) + sizeof(c_reference
));
1084 template <class iterator
, class Allocator
>
1085 Allocator BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::allocator()const
1087 return *((c_alloc
*)ref
);
1090 template <class iterator
, class Allocator
>
1091 inline match_results_base
<iterator
, Allocator
>& BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::operator=(const match_results_base
<iterator
, Allocator
>& m
)
1103 template <class iterator
, class Allocator
>
1104 void BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::free()
1106 if(--(ref
->count
) == 0)
1109 sub_match
<iterator
>* p1
, *p2
;
1110 p1
= (sub_match
<iterator
>*)(ref
+1);
1111 p2
= p1
+ ref
->cmatches
;
1118 a
.deallocate((char*)(void*)ref
, sizeof(sub_match
<iterator
>) * ref
->cmatches
+ sizeof(c_reference
));
1122 template <class iterator
, class Allocator
>
1123 bool match_results_base
<iterator
, Allocator
>::operator==(const match_results_base
<iterator
, Allocator
>& that
)const
1125 if(*ref
!= *(that
.ref
))
1127 const sub_match
<iterator
>* p1
= (sub_match
<iterator
>*)(ref
+1);
1128 const sub_match
<iterator
>* p2
= p1
+ ref
->cmatches
;
1129 const sub_match
<iterator
>* p3
= (sub_match
<iterator
>*)(that
.ref
+1);
1140 template <class iterator
, class Allocator
>
1141 void BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::set_size(size_type n
)
1143 if(ref
->cmatches
!= n
)
1145 c_reference
* newref
= (c_reference
*)ref
->allocate(sizeof(sub_match
<iterator
>) * n
+ sizeof(c_reference
));
1148 new (newref
) c_reference(*ref
);
1150 newref
->cmatches
= n
;
1151 sub_match
<iterator
>* p1
, *p2
;
1152 p1
= (sub_match
<iterator
>*)(newref
+1);
1153 p2
= p1
+ newref
->cmatches
;
1158 new (p1
) sub_match
<iterator
>();
1165 p2
= (sub_match
<iterator
>*)(newref
+1);
1178 ref
->deallocate((char*)(void*)newref
, sizeof(sub_match
<iterator
>) * n
+ sizeof(c_reference
));
1184 template <class iterator
, class Allocator
>
1185 void BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::set_size(size_type n
, iterator i
, iterator j
)
1187 if(ref
->cmatches
!= n
)
1189 c_reference
* newref
= (c_reference
*)ref
->allocate(sizeof(sub_match
<iterator
>) * n
+ sizeof(c_reference
));;
1191 new (newref
) c_reference(*ref
);
1193 newref
->cmatches
= n
;
1194 sub_match
<iterator
>* p1
= (sub_match
<iterator
>*)(newref
+1);
1195 sub_match
<iterator
>* p2
= p1
+ newref
->cmatches
;
1200 new (p1
) sub_match
<iterator
>(j
);
1207 p2
= (sub_match
<iterator
>*)(newref
+1);
1220 ref
->deallocate((char*)(void*)newref
, sizeof(sub_match
<iterator
>) * n
+ sizeof(c_reference
));
1227 // set iterators to be i, matched to false:
1228 sub_match
<iterator
>* p1
, *p2
;
1229 p1
= (sub_match
<iterator
>*)(ref
+1);
1230 p2
= p1
+ ref
->cmatches
;
1235 p1
->matched
= false;
1239 ref
->head
.first
= i
;
1240 ref
->tail
.second
= j
;
1241 ref
->head
.matched
= ref
->tail
.matched
= true;
1242 ref
->null
.first
= ref
->null
.second
= j
;
1243 ref
->null
.matched
= false;
1246 template <class iterator
, class Allocator
>
1247 inline void BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::init_fail(iterator i
, iterator j
)
1249 set_size(ref
->cmatches
, i
, j
);
1252 template <class iterator
, class Allocator
>
1253 void BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::maybe_assign(const match_results_base
<iterator
, Allocator
>& m
)
1255 sub_match
<iterator
>* p1
, *p2
;
1256 p1
= (sub_match
<iterator
>*)(ref
+1);
1257 p2
= (sub_match
<iterator
>*)(m
.ref
+1);
1258 iterator base
= (*this)[-1].first
;
1259 unsigned int len1
= 0;
1260 unsigned int len2
= 0;
1261 unsigned int base1
= 0;
1262 unsigned int base2
= 0;
1264 for(i
= 0; i
< ref
->cmatches
; ++i
)
1267 // leftmost takes priority over longest:
1268 BOOST_RE_DISTANCE(base
, p1
->first
, base1
);
1269 BOOST_RE_DISTANCE(base
, p2
->first
, base2
);
1270 if(base1
< base2
) return;
1271 if(base2
< base1
) break;
1273 BOOST_RE_DISTANCE(p1
->first
, p1
->second
, len1
);
1274 BOOST_RE_DISTANCE(p2
->first
, p2
->second
, len2
);
1275 if((len1
!= len2
) || ((p1
->matched
== false) && (p2
->matched
== true)))
1277 if((p1
->matched
== true) && (p2
->matched
== false))
1282 if(i
== ref
->cmatches
)
1286 else if((len2
> len1
) || ((p1
->matched
== false) && (p2
->matched
== true)) )
1290 template <class iterator
, class Allocator
>
1291 void BOOST_RE_CALL match_results_base
<iterator
, Allocator
>::cow()
1295 c_reference
* newref
= (c_reference
*)ref
->allocate(sizeof(sub_match
<iterator
>) * ref
->cmatches
+ sizeof(c_reference
));
1297 new (newref
) c_reference(*ref
);
1299 sub_match
<iterator
>* p1
= (sub_match
<iterator
>*)(newref
+1);
1300 sub_match
<iterator
>* p2
= p1
+ newref
->cmatches
;
1301 sub_match
<iterator
>* p3
= (sub_match
<iterator
>*)(ref
+1);
1305 new (p1
) sub_match
<iterator
>(*p3
);
1312 p2
= (sub_match
<iterator
>*)(newref
+1);
1326 ref
->deallocate((char*)(void*)newref
, sizeof(sub_match
<iterator
>) * ref
->cmatches
+ sizeof(c_reference
));
1332 } // namespace re_detail
1335 // class match_results
1336 // encapsulates match_results_base, does a deep copy rather than
1337 // reference counting to ensure thread safety when copying
1338 // other match_results instances
1340 template <class iterator
, class Allocator
>
1341 class match_results
: public re_detail::match_results_base
<iterator
, Allocator
>
1343 typedef re_detail::match_results_base
<iterator
, Allocator
> base_type
;
1345 explicit match_results(const Allocator
& a
= Allocator())
1346 : re_detail::match_results_base
<iterator
, Allocator
>(a
){}
1348 match_results(const re_detail::match_results_base
<iterator
, Allocator
>& m
)
1349 : re_detail::match_results_base
<iterator
, Allocator
>(m
){}
1351 match_results
& operator=(const re_detail::match_results_base
<iterator
, Allocator
>& m
)
1354 base_type::operator=(m
);
1358 match_results(const match_results
& m
);
1359 match_results
& operator=(const match_results
& m
);
1361 bool operator==(const match_results& that)const
1362 { return re_detail::match_results_base<iterator, Allocator>::operator==(that); }
1363 bool operator<(const match_results& that) const
1364 { return position() < that.position(); }
1368 template <class iterator
, class Allocator
>
1369 match_results
<iterator
, Allocator
>::match_results(const match_results
<iterator
, Allocator
>& m
)
1370 : re_detail::match_results_base
<iterator
, Allocator
>(false)
1373 reinterpret_cast<typename
re_detail::match_results_base
<iterator
, Allocator
>::c_reference
*>
1374 (m
.ref
->allocate(sizeof(sub_match
<iterator
>) * m
.ref
->cmatches
+
1375 sizeof(typename
re_detail::match_results_base
<iterator
, Allocator
>::c_reference
)));
1377 new (this->ref
) typename
re_detail::match_results_base
<iterator
, Allocator
>::c_reference(*m
.ref
);
1378 this->ref
->count
= 1;
1379 sub_match
<iterator
>* p1
= (sub_match
<iterator
>*)(this->ref
+1);
1380 sub_match
<iterator
>* p2
= p1
+ this->ref
->cmatches
;
1381 sub_match
<iterator
>* p3
= (sub_match
<iterator
>*)(m
.ref
+1);
1385 new (p1
) sub_match
<iterator
>(*p3
);
1392 p2
= (sub_match
<iterator
>*)(this->ref
+1);
1395 re_detail::jm_destroy(p2
);
1398 re_detail::jm_destroy(ref
);
1404 m
.ref
->deallocate((char*)(void*)this->ref
, sizeof(sub_match
<iterator
>) * m
.ref
->cmatches
+ sizeof(typename
re_detail::match_results_base
<iterator
, Allocator
>::c_reference
));
1409 template <class iterator
, class Allocator
>
1410 match_results
<iterator
, Allocator
>& match_results
<iterator
, Allocator
>::operator=(const match_results
<iterator
, Allocator
>& m
)
1412 match_results
<iterator
, Allocator
> t(m
);
1417 namespace re_detail
{
1418 template <class iterator
, class charT
, class traits_type
, class Allocator
>
1419 iterator BOOST_RE_CALL
re_is_set_member(iterator next
,
1422 const reg_expression
<charT
, traits_type
, Allocator
>& e
);
1423 } // namepsace re_detail
1426 #if __BORLANDC__ > 0x520
1431 } // namespace boost
1433 #include <boost/re_detail/regex_compile.hpp>
1437 typedef reg_expression
<char, regex_traits
<char>, BOOST_RE_DEF_ALLOC(char)> regex
;
1438 #ifndef BOOST_RE_NO_WCSTRING
1439 typedef reg_expression
<wchar_t, regex_traits
<wchar_t>, BOOST_RE_DEF_ALLOC(wchar_t)> wregex
;
1442 typedef match_results
<const char*> cmatch
;
1443 #ifndef BOOST_RE_NO_WCSTRING
1444 typedef match_results
<const wchar_t*> wcmatch
;
1447 } // namespace boost
1449 #include <boost/re_detail/regex_match.hpp>
1450 #include <boost/re_detail/regex_format.hpp>
1451 #include <boost/re_detail/regex_split.hpp>
1454 #endif // __cplusplus