]> git.lyx.org Git - lyx.git/blob - boost/boost/regex.hpp
some boost changes and updates
[lyx.git] / boost / boost / regex.hpp
1 /*
2  *
3  * Copyright (c) 1998-2000
4  * Dr John Maddock
5  *
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.
13  *
14  */
15
16  /*
17   *   LOCATION:    see http://www.boost.org for most recent version.
18   *   FILE         regex.cpp
19   *   VERSION      3.03
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.
23   */
24
25
26 /* start with C compatability API */
27
28 #ifndef BOOST_RE_REGEX_HPP
29 #define BOOST_RE_REGEX_HPP
30
31 #include <boost/cregex.hpp>
32
33 #ifdef __cplusplus
34
35 // what follows is all C++ don't include in C builds!!
36
37 #ifdef BOOST_RE_DEBUG
38 # include <iosfwd>
39 #endif
40
41 #include <new>
42 #include <boost/re_detail/regex_config.hpp>
43 #if !defined(BOOST_RE_NO_TYPEINFO)
44 #include <typeinfo>
45 #endif
46 #include <cstring>
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>
53
54
55 namespace boost{
56
57 #ifdef __BORLANDC__
58    #if __BORLANDC__ == 0x530
59     #pragma option push -a4 -b -Ve
60    #elif __BORLANDC__ > 0x530
61     #pragma option push -a8 -b -Ve
62    #endif
63 #endif
64
65 namespace re_detail{
66
67 struct re_set_long;
68 struct re_syntax_base;
69
70 } // namespace re_detail
71
72 namespace deprecated{
73 //
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> {};
78
79 template<>
80 class char_regex_traits_i<char> : public regex_traits<char>
81 {
82 public:
83    typedef char char_type;
84    typedef unsigned char uchar_type;
85    typedef unsigned int size_type;
86    typedef regex_traits<char> base_type;
87
88    char BOOST_RE_CALL translate(char c, bool)const
89    {
90       return static_cast<const regex_traits<char>*>(this)->translate(c, true);
91    }
92 };
93
94 #ifndef BOOST_RE_NO_WCSTRING
95 template<>
96 class char_regex_traits_i<wchar_t> : public regex_traits<wchar_t>
97 {
98 public:
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;
103
104    wchar_t BOOST_RE_CALL translate(wchar_t c, bool)const
105    {
106       return static_cast<const regex_traits<wchar_t>*>(this)->translate(c, true);
107    }
108    jm_uintfast32_t BOOST_RE_CALL lookup_classname(const wchar_t* first, const wchar_t* last)const
109    {
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;
113       return result;
114    }
115 };
116 #endif
117 } // namespace deprecated
118
119
120 namespace re_detail{
121
122 enum mask_type
123 {
124    mask_take = 1,
125    mask_skip = 2,
126    mask_any = mask_skip | mask_take,
127    mask_all = mask_any
128 };
129
130 struct _narrow_type{};
131 struct _wide_type{};
132
133 template <class charT>
134 class is_byte;
135
136 template<>
137 class is_byte<char>
138 {
139 public:
140    typedef _narrow_type width_type;
141 };
142
143 template<>
144 class is_byte<unsigned char>
145 {
146 public:
147    typedef _narrow_type width_type;
148 };
149
150 template<>
151 class is_byte<signed char>
152 {
153 public:
154    typedef _narrow_type width_type;
155 };
156
157 template <class charT>
158 class is_byte
159 {
160 public:
161    typedef _wide_type width_type;
162 };
163
164
165 //
166 // compiled structures
167 //
168 // the following defs describe the format of the compiled string
169 //
170
171 //
172 // enum syntax_element_type
173 // describes the type of a record
174 enum syntax_element_type
175 {
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
198 };
199
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);
203 #endif
204
205 union offset_type
206 {
207    re_syntax_base* p;
208    unsigned i;
209 };
210
211 //
212 // struct re_syntax_base
213 // base class for all syntax types:
214 struct re_syntax_base
215 {
216    syntax_element_type type;
217    offset_type next;
218    unsigned int can_be_null;
219 };
220
221 //
222 // struct re_brace
223 // marks start or end of (...)
224 struct re_brace : public re_syntax_base
225 {
226    unsigned int index;
227 };
228
229 //
230 // struct re_literal
231 // marks a literal string and
232 // is followed by an array of charT[length]:
233 struct re_literal : public re_syntax_base
234 {
235    unsigned int length;
236 };
237
238 //
239 // struct re_long_set
240 // provides data for sets [...] containing
241 // wide characters
242 struct re_set_long : public re_syntax_base
243 {
244    unsigned int csingles, cranges, cequivalents;
245    jm_uintfast32_t cclasses;
246    bool isnot;
247 };
248
249 //
250 // struct re_set
251 // provides a map of bools for sets containing
252 // narrow, single byte characters.
253 struct re_set : public re_syntax_base
254 {
255    unsigned char _map[256];
256 };
257
258 //
259 // struct re_jump
260 // provides alternative next destination
261 struct re_jump : public re_syntax_base
262 {
263    offset_type alt;
264    unsigned char _map[256];
265 };
266
267 //
268 // struct re_repeat
269 // provides repeat expressions
270 struct re_repeat : public re_jump
271 {
272    unsigned min, max;
273    int id;
274    bool leading;
275    bool greedy;
276 };
277
278
279 //
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
284 // bytes to insert
285 enum re_jump_size_type
286 {
287    re_jump_size = (sizeof(re_jump) + padding_mask) & ~(padding_mask),
288    re_repeater_size = (sizeof(re_repeat) + padding_mask) & ~(padding_mask)
289 };
290
291 } // namespace re_detail
292
293 //
294 // class basic_regex
295 // handles error codes and flags
296
297 class BOOST_RE_IX_DECL regbase
298 {
299 public:
300    enum flag_type_
301    {
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 \|
312
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
318
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,
326       sed = basic,
327       perl = normal
328    };
329    typedef unsigned int flag_type;
330
331    enum restart_info
332    {
333       restart_any = 0,
334       restart_word = 1,
335       restart_line = 2,
336       restart_buf = 3,
337       restart_continue = 4,
338       restart_lit = 5,
339       restart_fixed_lit = 6
340    };
341
342    flag_type BOOST_RE_CALL flags()const
343    {
344       return _flags;
345    }
346
347    regbase();
348    regbase(const regbase& b);
349 protected:
350    flag_type _flags;
351 };
352
353 //
354 // some forward declarations:
355 namespace re_detail{
356 template <class iterator, class Allocator>
357 class _priv_match_data;
358
359 #if defined(BOOST_NO_STD_ITERATOR_TRAITS) || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
360
361 template <class T>
362 struct regex_iterator_traits 
363 {
364   typedef typename T::iterator_category iterator_category;
365   typedef typename T::value_type        value_type;
366 #ifndef BOOST_MSVC
367   typedef typename T::difference_type   difference_type;
368   typedef typename T::pointer           pointer;
369   typedef typename T::reference         reference;
370 #else
371   typedef std::ptrdiff_t                difference_type;
372   typedef value_type*                   pointer;
373   typedef value_type&                   reference;
374 #endif
375 };
376
377 template <class T>
378 struct pointer_iterator_traits
379 {
380    typedef std::ptrdiff_t difference_type;
381    typedef T value_type;
382    typedef T* pointer;
383    typedef T& reference;
384    typedef std::random_access_iterator_tag iterator_category;
385 };
386 template <class T>
387 struct const_pointer_iterator_traits
388 {
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;
394 };
395
396 template<>
397 struct regex_iterator_traits<char*> : pointer_iterator_traits<char>{};
398 template<>
399 struct regex_iterator_traits<const char*> : const_pointer_iterator_traits<char>{};
400 template<>
401 struct regex_iterator_traits<wchar_t*> : pointer_iterator_traits<wchar_t>{};
402 template<>
403 struct regex_iterator_traits<const wchar_t*> : const_pointer_iterator_traits<wchar_t>{};
404
405 #if defined(__SGI_STL_PORT) && defined(__STL_DEBUG)
406 template<>
407 struct regex_iterator_traits<std::string::iterator> : pointer_iterator_traits<char>{};
408 template<>
409 struct regex_iterator_traits<std::string::const_iterator> : const_pointer_iterator_traits<char>{};
410 #ifndef BOOST_NO_WSTRING
411 template<>
412 struct regex_iterator_traits<std::wstring::iterator> : pointer_iterator_traits<wchar_t>{};
413 template<>
414 struct regex_iterator_traits<std::wstring::const_iterator> : const_pointer_iterator_traits<wchar_t>{};
415 #endif // BOOST_NO_WSTRING
416 #endif // stport
417
418 #else
419
420 template <class T>
421 struct regex_iterator_traits : public std::iterator_traits<T> {};
422
423 #endif
424
425 template <class I>
426 struct def_alloc_param_traits
427 {
428    typedef typename regex_iterator_traits<I>::value_type const_value_type;
429    typedef typename remove_cv<const_value_type>::type type;
430 };
431
432 }
433
434 template <class iterator, class Allocator BOOST_RE_DEF_ALLOC_PARAM(typename re_detail::def_alloc_param_traits<iterator>::type) >
435 class match_results;
436
437 //
438 // class reg_expression
439 // represents the compiled
440 // regular expression:
441 //
442
443 #if defined(BOOST_RE_NO_TEMPLATE_SWITCH_MERGE) && !defined(BOOST_RE_NO_NAMESPACES)
444 //
445 // Ugly ugly hack, 
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.
449 namespace{
450 #endif
451
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
454 {
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;
458 public:
459    // typedefs:
460    typedef charT char_type;
461    typedef traits traits_type;
462
463    // locale_type
464    // placeholder for actual locale type used by the
465    // traits class to localise *this.
466    typedef typename traits::locale_type locale_type;
467    // value_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;
475    // difference_type
476    typedef typename Allocator::difference_type difference_type;
477    // size_type
478    typedef typename Allocator::size_type size_type;   
479    // allocator_type
480    typedef Allocator allocator_type;
481    typedef Allocator alloc_type;
482    // flag_type
483    typedef regbase::flag_type flag_type;
484    
485 public:
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&);
491    ~reg_expression();
492    reg_expression& BOOST_RE_CALL operator=(const reg_expression&);
493    reg_expression& BOOST_RE_CALL operator=(const charT* ptr)
494    {
495       set_expression(ptr, regbase::normal | regbase::use_except);
496       return *this;
497    }
498
499    //
500    // assign:
501    reg_expression& assign(const reg_expression& that)
502    { return *this = that; }
503    reg_expression& assign(const charT* ptr, flag_type f = regbase::normal)
504    {
505       set_expression(ptr, f | regbase::use_except);
506       return *this;
507    }
508
509    reg_expression& assign(const charT* first,
510                           const charT* last,
511                           flag_type f = regbase::normal)
512    {
513       set_expression(first, last, f | regbase::use_except);
514       return *this;
515    }
516 #ifndef BOOST_RE_NO_MEMBER_TEMPLATES
517
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); }
521
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); }
525
526    template <class I>
527    reg_expression(I first, I last, flag_type f = regbase::normal, const Allocator& al = Allocator())
528     : data(al), pkmp(0)
529    {
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);
534    }
535
536    template <class ST, class SA>
537    reg_expression& BOOST_RE_CALL operator=(const std::basic_string<charT, ST, SA>& p)
538    {
539       set_expression(p.c_str(), p.c_str() + p.size(), regbase::normal | regbase::use_except);
540       return *this;
541    }
542
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)
547    {
548       set_expression(s.c_str(), s.c_str() + s.size(), f | regbase::use_except);
549       return *this;
550    }
551
552    template <class fwd_iterator>
553    reg_expression& BOOST_RE_CALL assign(fwd_iterator first,
554                           fwd_iterator last,
555                           flag_type f = regbase::normal)
556    {
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);
561       return *this;
562    }
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); }
566
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); }
569
570    reg_expression& BOOST_RE_CALL operator=(const std::basic_string<charT>& p)
571    {
572       set_expression(p.c_str(), p.c_str() + p.size(), regbase::normal | regbase::use_except);
573       return *this;
574    }
575
576    reg_expression& BOOST_RE_CALL assign(
577        const std::basic_string<charT>& s,
578        flag_type f = regbase::normal)
579    {
580       set_expression(s.c_str(), s.c_str() + s.size(), f | regbase::use_except);
581       return *this;
582    }
583
584 #endif
585
586
587    //
588    // allocator access:
589    Allocator BOOST_RE_CALL get_allocator()const;
590    //
591    // locale:
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(); }
594    //
595    // flags:
596    flag_type BOOST_RE_CALL getflags()const
597    { return flags(); }
598    //
599    // str:
600    std::basic_string<charT> BOOST_RE_CALL str()const
601    { return std::basic_string<charT>(_expression, _expression_len); }
602    //
603    // begin, end:
604    const_iterator BOOST_RE_CALL begin()const
605    { return _expression; }
606    const_iterator BOOST_RE_CALL end()const
607    { return _expression + _expression_len; }
608    //
609    // swap:
610    void BOOST_RE_CALL swap(reg_expression&)throw();
611    //
612    // size:
613    size_type BOOST_RE_CALL size()const
614    { return _expression_len; }
615    //
616    // max_size:
617    size_type BOOST_RE_CALL max_size()const
618    { return UINT_MAX; }
619    //
620    // empty:
621    bool BOOST_RE_CALL empty()const
622    { return this->error_code(); }
623
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;
627    //
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); }
634    //
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
638    {
639       return error_code_;
640    }
641
642 private:
643    re_detail::raw_storage<Allocator> data;
644    unsigned _restart_type;
645    unsigned marks;
646    int repeats;
647    unsigned char* startmap;
648    charT* _expression;
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_;
656
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);
668
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);
677
678 protected:
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)
690    { return e.pkmp; }
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&);
693 };
694
695 template <class charT, class traits, class Allocator>
696 void BOOST_RE_CALL reg_expression<charT, traits, Allocator>::swap(reg_expression& that)throw()
697 {
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);
702    that = *this;
703    *this = e;
704 }
705
706
707 #if defined(BOOST_RE_NO_TEMPLATE_SWITCH_MERGE) && !defined(BOOST_RE_NO_NAMESPACES)
708 } // namespace
709 #endif
710
711 //
712 // class match_results and match_results_base
713 // handles what matched where
714
715 template <class iterator>
716 struct sub_match
717 {
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;
721 #else
722    typedef typename re_detail::regex_iterator_traits<iterator>::difference_type       difference_type;
723 #endif
724    typedef iterator                                                  iterator_type;
725    
726    iterator first;
727    iterator second;
728    bool matched;
729
730    operator std::basic_string<value_type> ()const
731    {
732       std::basic_string<value_type> result;
733       unsigned len;
734       BOOST_RE_DISTANCE((iterator)first, (iterator)second, len);
735       result.reserve(len);
736       iterator i = first;
737       while(i != second)
738       {
739          result.append(1, *i);
740          ++i;
741       }
742       return result;
743    }
744    #ifdef BOOST_OLD_REGEX_H
745    //
746    // the following are deprecated, do not use!!
747    //
748    operator int()const;
749    operator unsigned int()const;
750    operator short()const
751    {
752       return (short)(int)(*this);
753    }
754    operator unsigned short()const
755    {
756       return (unsigned short)(unsigned int)(*this);
757    }
758    #endif
759    sub_match() { matched = false; }
760    sub_match(iterator i) : first(i), second(i), matched(false) {}
761
762    bool operator==(const sub_match& that)const
763    {
764       return (first == that.first) && (second == that.second) && (matched == that.matched);
765    }
766    bool BOOST_RE_CALL operator !=(const sub_match& that)const
767    { return !(*this == that); }
768
769    difference_type BOOST_RE_CALL length()const
770    {
771       difference_type n;
772       BOOST_RE_DISTANCE((iterator)first, (iterator)second, n);
773       return n;
774    }
775 };
776
777 #ifdef BOOST_OLD_REGEX_H
778 namespace re_detail{
779 template <class iterator, class charT>
780 int do_toi(iterator i, iterator j, char c, int radix)
781 {
782    std::string s(i, j);
783    char* p;
784    int result = std::strtol(s.c_str(), &p, radix);
785    if(*p)throw bad_pattern("Bad sub-expression");
786    return result;
787 }
788
789 //
790 // helper:
791 template <class I, class charT>
792 int do_toi(I& i, I j, charT c)
793 {
794    int result = 0;
795    while((i != j) && (isdigit(*i)))
796    {
797       result = result*10 + (*i - '0');
798       ++i;
799    }
800    return result;
801 }
802 }
803
804
805 template <class iterator>
806 sub_match<iterator>::operator int()const
807 {
808    iterator i = first;
809    iterator j = second;
810    if(i == j)throw bad_pattern("Bad sub-expression");
811    int neg = 1;
812    if((i != j) && (*i == '-'))
813    {
814       neg = -1;
815       ++i;
816    }
817    neg *= re_detail::do_toi(i, j, *i);
818    if(i != j)throw bad_pattern("Bad sub-expression");
819    return neg;
820 }
821 template <class iterator>
822 sub_match<iterator>::operator unsigned int()const
823 {
824    iterator i = first;
825    iterator j = second;
826    if(i == j)
827       throw bad_pattern("Bad sub-expression");
828    return re_detail::do_toi(i, j, *first);
829 }
830 #endif
831
832 namespace re_detail{
833
834 template <class iterator, class Allocator BOOST_RE_DEF_ALLOC_PARAM(typename def_alloc_param_traits<iterator>::type) >
835 class match_results_base
836 {
837 public:
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;
843 #else
844    typedef std::ptrdiff_t                                            difference_type;
845    typedef typename re_detail::regex_iterator_traits<iterator>::value_type char_type;
846 #endif
847    typedef sub_match<iterator>                                       value_type;
848    typedef iterator                                                  iterator_type;
849
850 protected:
851    typedef BOOST_RE_MAYBE_TYPENAME REBIND_TYPE(char, Allocator) c_alloc;
852    
853    struct c_reference : public c_alloc
854    {
855       unsigned int cmatches;
856       unsigned count;
857       sub_match<iterator> head, tail, null;
858       unsigned int lines;
859       iterator line_pos, base;
860       c_reference(const Allocator& a) : c_alloc(a) {  }
861
862       bool operator==(const c_reference& that)const
863       {
864          return (cmatches == that.cmatches) &&
865                   (count == that.count) &&
866                   (head == that.head) &&
867                   (tail == that.tail) &&
868                   (lines == that.lines) &&
869                   (base == that.base);
870       }
871       bool operator!=(const c_reference& that)const
872       { return !(*this == that); }
873    };
874
875    c_reference* ref;
876
877    void BOOST_RE_CALL cow();
878
879    // protected contructor for derived class...
880    match_results_base(bool){}
881    void BOOST_RE_CALL free();
882
883 public:
884
885    match_results_base(const Allocator& a = Allocator());
886
887    match_results_base(const match_results_base& m)
888    {
889       ref = m.ref;
890       ++(ref->count);
891    }
892
893    match_results_base& BOOST_RE_CALL operator=(const match_results_base& m);
894
895    ~match_results_base()
896    {
897       free();
898    }
899
900    size_type BOOST_RE_CALL size()const
901    {
902       //return (*this)[0].matched ? ref->cmatches : 0;
903       return ref->cmatches;
904    }
905
906    const sub_match<iterator>& BOOST_RE_CALL operator[](int n) const
907    {
908       if((n >= 0) && ((unsigned int)n < ref->cmatches))
909          return *(sub_match<iterator>*)((char*)ref + sizeof(c_reference) + sizeof(sub_match<iterator>)*n);
910       return (n == -1) ? ref->head : (n == -2) ? ref->tail : ref->null;
911    }
912
913    Allocator BOOST_RE_CALL allocator()const;
914
915    difference_type BOOST_RE_CALL length(unsigned int sub = 0)const
916    {
917       jm_assert(ref->cmatches);
918       const sub_match<iterator>& m = (*this)[sub];
919       if(m.matched == false)
920          return 0;
921       difference_type n;
922       BOOST_RE_DISTANCE((iterator)m.first, (iterator)m.second, n);
923       return n;
924    }
925
926    std::basic_string<char_type> str(int i)const
927    {
928       return static_cast<std::basic_string<char_type> >((*this)[i]);
929    }
930
931    unsigned int BOOST_RE_CALL line()const
932    {
933       return ref->lines;
934    }
935
936    difference_type BOOST_RE_CALL position(unsigned int sub = 0)const
937    {
938       jm_assert(ref->cmatches);
939       const sub_match<iterator>& s = (*this)[sub];
940       if(s.matched == false)
941          return -1;
942       difference_type n;
943       BOOST_RE_DISTANCE((iterator)ref->base, (iterator)s.first, n);
944       return n;
945    }
946
947    iterator BOOST_RE_CALL line_start()const
948    {
949       return ref->line_pos;
950    }
951
952    void swap(match_results_base& that)
953    {
954       c_reference* t = that.ref;
955       that.ref = ref;
956       ref = t;
957    }
958
959    bool operator==(const match_results_base& that)const;
960    bool operator<(const match_results_base& that)const
961    { return position() < that.position(); }
962
963    friend class match_results<iterator, Allocator>;
964
965    void BOOST_RE_CALL set_size(size_type n);
966    void BOOST_RE_CALL set_size(size_type n, iterator i, iterator j);
967    void BOOST_RE_CALL maybe_assign(const match_results_base& m);
968    void BOOST_RE_CALL init_fail(iterator i, iterator j);
969
970    void BOOST_RE_CALL set_first(iterator i);
971    void BOOST_RE_CALL set_first(iterator i, size_t pos);
972
973    void BOOST_RE_CALL set_second(iterator i)
974    {
975       cow();
976       ((sub_match<iterator>*)(ref+1))->second = i;
977       ((sub_match<iterator>*)(ref+1))->matched = true;
978       ref->tail.first = i;
979       ref->tail.matched = (ref->tail.first == ref->tail.second) ? false : true;
980    }
981
982    void BOOST_RE_CALL set_second(iterator i, size_t pos)
983    {
984       cow();
985       ((sub_match<iterator>*)((char*)ref + sizeof(c_reference) + sizeof(sub_match<iterator>) * pos))->second = i;
986       ((sub_match<iterator>*)((char*)ref + sizeof(c_reference) + sizeof(sub_match<iterator>) * pos))->matched = true;
987       if(pos == 0)
988       {
989          ref->tail.first = i;
990          ref->tail.matched = (ref->tail.first == ref->tail.second) ? false : true;
991       }
992    }
993
994    void BOOST_RE_CALL set_line(unsigned int i, iterator pos)
995    {
996       ref->lines = i;
997       ref->line_pos = pos;
998    }
999
1000    void BOOST_RE_CALL set_base(iterator pos)
1001    {
1002       ref->base = pos;
1003    }
1004 };
1005
1006 template <class iterator, class Allocator>
1007 void BOOST_RE_CALL match_results_base<iterator, Allocator>::set_first(iterator i)
1008 {
1009    cow();
1010    ref->head.second = i;
1011    ref->head.matched = (ref->head.first == ref->head.second) ? false : true;
1012    sub_match<iterator>* p1 = (sub_match<iterator>*)(ref+1);
1013    sub_match<iterator>* p2 = p1 + ref->cmatches;
1014    p1->first = i;
1015    p1->matched = false;
1016    ++p1;
1017    while(p1 != p2)
1018    {
1019       p1->matched = false;
1020       p1->first = ref->tail.second;
1021       p1->second = ref->tail.second;
1022       ++p1;
1023    }
1024 }
1025
1026 template <class iterator, class Allocator>
1027 void BOOST_RE_CALL match_results_base<iterator, Allocator>::set_first(iterator i, size_t pos)
1028 {
1029    cow();
1030    ((sub_match<iterator>*)((char*)ref + sizeof(c_reference) + sizeof(sub_match<iterator>) * pos))->first = i;
1031    if(pos == 0)
1032    {
1033       ref->head.second = i;
1034       ref->head.matched = (ref->head.first == ref->head.second) ? false : true;
1035       sub_match<iterator>* p1 = (sub_match<iterator>*)(ref+1);
1036       sub_match<iterator>* p2 = p1 + ref->cmatches;
1037       p1->first = i;
1038       p1->matched = false;
1039       ++p1;
1040       while(p1 != p2)
1041       {
1042          p1->matched = false;
1043          p1->first = ref->tail.second;
1044          p1->second = ref->tail.second;
1045          ++p1;
1046       }
1047    }
1048 }
1049
1050
1051 template <class iterator, class Allocator>
1052 match_results_base<iterator, Allocator>::match_results_base(const Allocator& a)
1053 {
1054    ref = (c_reference*)c_alloc(a).allocate(sizeof(sub_match<iterator>) + sizeof(c_reference));
1055    try
1056    {
1057       new (ref) c_reference(a);
1058       ref->cmatches = 1;
1059       ref->count = 1;
1060       // construct the sub_match<iterator>:
1061       try
1062       {
1063          new ((sub_match<iterator>*)(ref+1)) sub_match<iterator>();
1064       }
1065       catch(...)
1066       { 
1067          jm_destroy(ref); 
1068          throw; 
1069       }
1070    }
1071    catch(...)
1072    { 
1073       c_alloc(a).deallocate((char*)(void*)ref, sizeof(sub_match<iterator>) + sizeof(c_reference)); 
1074       throw; 
1075    }
1076 }
1077
1078 template <class iterator, class Allocator>
1079 Allocator BOOST_RE_CALL match_results_base<iterator, Allocator>::allocator()const
1080 {
1081   return *((c_alloc*)ref);
1082 }
1083
1084 template <class iterator, class Allocator>
1085 inline match_results_base<iterator, Allocator>& BOOST_RE_CALL match_results_base<iterator, Allocator>::operator=(const match_results_base<iterator, Allocator>& m)
1086 {
1087    if(ref != m.ref)
1088    {
1089       free();
1090       ref = m.ref;
1091       ++(ref->count);
1092    }
1093    return *this;
1094 }
1095
1096
1097 template <class iterator, class Allocator>
1098 void BOOST_RE_CALL match_results_base<iterator, Allocator>::free()
1099 {
1100    if(--(ref->count) == 0)
1101    {
1102       c_alloc a(*ref);
1103       sub_match<iterator>* p1, *p2;
1104       p1 = (sub_match<iterator>*)(ref+1);
1105       p2 = p1 + ref->cmatches;
1106       while(p1 != p2)
1107       {
1108          jm_destroy(p1);
1109          ++p1;
1110       }
1111       jm_destroy(ref);
1112       a.deallocate((char*)(void*)ref, sizeof(sub_match<iterator>) * ref->cmatches + sizeof(c_reference));
1113    }
1114 }
1115
1116 template <class iterator, class Allocator>
1117 bool match_results_base<iterator, Allocator>::operator==(const match_results_base<iterator, Allocator>& that)const
1118 {
1119    if(*ref != *(that.ref))
1120       return false;
1121    const sub_match<iterator>* p1 = (sub_match<iterator>*)(ref+1);
1122    const sub_match<iterator>* p2 = p1 + ref->cmatches;
1123    const sub_match<iterator>* p3 = (sub_match<iterator>*)(that.ref+1);
1124    while(p1 != p2)
1125    {
1126       if(*p1 != *p3)
1127          return false;
1128       ++p1;
1129       ++p3;
1130    }
1131    return true;
1132 }
1133
1134 template <class iterator, class Allocator>
1135 void BOOST_RE_CALL match_results_base<iterator, Allocator>::set_size(size_type n)
1136 {
1137    if(ref->cmatches != n)
1138    {
1139       c_reference* newref = (c_reference*)ref->allocate(sizeof(sub_match<iterator>) * n + sizeof(c_reference));
1140       try
1141       {
1142          new (newref) c_reference(*ref);
1143          newref->count = 1;
1144          newref->cmatches = n;
1145          sub_match<iterator>* p1, *p2;
1146          p1 = (sub_match<iterator>*)(newref+1);
1147          p2 = p1 + newref->cmatches;
1148          try
1149          {
1150             while(p1 != p2)
1151             {
1152                new (p1) sub_match<iterator>();
1153                ++p1;
1154             }
1155             free();
1156          }
1157          catch(...)
1158          { 
1159             p2 = (sub_match<iterator>*)(newref+1);
1160             while(p2 != p1)
1161             {
1162                jm_destroy(p2);
1163                ++p2;
1164             }
1165             jm_destroy(ref);
1166             throw; 
1167          }
1168          ref = newref;
1169       }
1170       catch(...)
1171       { 
1172          ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * n + sizeof(c_reference)); 
1173          throw; 
1174       }
1175    }
1176 }
1177
1178 template <class iterator, class Allocator>
1179 void BOOST_RE_CALL match_results_base<iterator, Allocator>::set_size(size_type n, iterator i, iterator j)
1180 {
1181    if(ref->cmatches != n)
1182    {
1183       c_reference* newref = (c_reference*)ref->allocate(sizeof(sub_match<iterator>) * n + sizeof(c_reference));;
1184       try{
1185          new (newref) c_reference(*ref);
1186          newref->count = 1;
1187          newref->cmatches = n;
1188          sub_match<iterator>* p1 = (sub_match<iterator>*)(newref+1);
1189          sub_match<iterator>* p2 = p1 + newref->cmatches;
1190          try
1191          {
1192             while(p1 != p2)
1193             {
1194                new (p1) sub_match<iterator>(j);
1195                ++p1;
1196             }
1197             free();
1198          }
1199          catch(...)
1200          { 
1201             p2 = (sub_match<iterator>*)(newref+1);
1202             while(p2 != p1)
1203             {
1204                jm_destroy(p2);
1205                ++p2;
1206             }
1207             jm_destroy(ref);
1208             throw; 
1209          }
1210          ref = newref;
1211       }
1212       catch(...)
1213       { 
1214          ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * n + sizeof(c_reference)); 
1215          throw; 
1216       }
1217    }
1218    else
1219    {
1220       cow();
1221       // set iterators to be i, matched to false:
1222       sub_match<iterator>* p1, *p2;
1223       p1 = (sub_match<iterator>*)(ref+1);
1224       p2 = p1 + ref->cmatches;
1225       while(p1 != p2)
1226       {
1227          p1->first = j;
1228          p1->second = j;
1229          p1->matched = false;
1230          ++p1;
1231       }                                 
1232    }
1233    ref->head.first = i;
1234    ref->tail.second = j;
1235    ref->head.matched = ref->tail.matched = true;
1236    ref->null.first = ref->null.second = j;
1237    ref->null.matched = false;
1238 }
1239
1240 template <class iterator, class Allocator>
1241 inline void BOOST_RE_CALL match_results_base<iterator, Allocator>::init_fail(iterator i, iterator j)
1242 {
1243    set_size(ref->cmatches, i, j);
1244 }
1245
1246 template <class iterator, class Allocator>
1247 void BOOST_RE_CALL match_results_base<iterator, Allocator>::maybe_assign(const match_results_base<iterator, Allocator>& m)
1248 {
1249    sub_match<iterator>* p1, *p2;
1250    p1 = (sub_match<iterator>*)(ref+1);
1251    p2 = (sub_match<iterator>*)(m.ref+1);
1252    iterator base = (*this)[-1].first;
1253    unsigned int len1 = 0;
1254    unsigned int len2 = 0;
1255    unsigned int base1 = 0;
1256    unsigned int base2 = 0;
1257    unsigned int i;
1258    for(i = 0; i < ref->cmatches; ++i)
1259    {
1260       //
1261       // leftmost takes priority over longest:
1262       BOOST_RE_DISTANCE(base, p1->first, base1);
1263       BOOST_RE_DISTANCE(base, p2->first, base2);
1264       if(base1 < base2) return;
1265       if(base2 < base1) break;
1266
1267       BOOST_RE_DISTANCE(p1->first, p1->second, len1);
1268       BOOST_RE_DISTANCE(p2->first, p2->second, len2);
1269       if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
1270          break;
1271       if((p1->matched == true) && (p2->matched == false))
1272          return;
1273       ++p1;
1274       ++p2;
1275    }
1276    if(i == ref->cmatches)
1277       return;
1278    if(base2 < base1)
1279       *this = m;
1280    else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) )
1281       *this = m;
1282 }
1283
1284 template <class iterator, class Allocator>
1285 void BOOST_RE_CALL match_results_base<iterator, Allocator>::cow()
1286 {
1287    if(ref->count > 1)
1288    {
1289       c_reference* newref = (c_reference*)ref->allocate(sizeof(sub_match<iterator>) * ref->cmatches + sizeof(c_reference));
1290       try{
1291          new (newref) c_reference(*ref);
1292          newref->count = 1;
1293          sub_match<iterator>* p1 = (sub_match<iterator>*)(newref+1);
1294          sub_match<iterator>* p2 = p1 + newref->cmatches;
1295          sub_match<iterator>* p3 = (sub_match<iterator>*)(ref+1);
1296          try{
1297             while(p1 != p2)
1298             {
1299                new (p1) sub_match<iterator>(*p3);
1300                ++p1;
1301                ++p3;
1302             }
1303          }
1304          catch(...)
1305          { 
1306             p2 = (sub_match<iterator>*)(newref+1);
1307             while(p2 != p1)
1308             {
1309                jm_destroy(p2);
1310                ++p2;
1311             }
1312             jm_destroy(ref);
1313             throw; 
1314          }
1315       --(ref->count);
1316       ref = newref;
1317       }
1318       catch(...)
1319       { 
1320          ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * ref->cmatches + sizeof(c_reference)); 
1321          throw; 
1322       }
1323    }
1324 }
1325
1326 } // namespace re_detail
1327
1328 //
1329 // class match_results
1330 // encapsulates match_results_base, does a deep copy rather than
1331 // reference counting to ensure thread safety when copying
1332 // other match_results instances
1333
1334 template <class iterator, class Allocator>
1335 class match_results : public re_detail::match_results_base<iterator, Allocator>
1336 {
1337    typedef re_detail::match_results_base<iterator, Allocator> base_type;
1338 public:
1339
1340    typedef typename base_type::alloc_type          alloc_type;
1341    typedef typename base_type::size_type           size_type;
1342    typedef typename base_type::char_type           char_type;
1343    typedef typename base_type::value_type          value_type;
1344    typedef typename base_type::difference_type     difference_type;
1345    typedef typename base_type::iterator_type       iterator_type;
1346
1347    explicit match_results(const Allocator& a = Allocator())
1348       : re_detail::match_results_base<iterator, Allocator>(a){}
1349
1350    match_results(const re_detail::match_results_base<iterator, Allocator>& m)
1351       : re_detail::match_results_base<iterator, Allocator>(m){}
1352
1353    match_results& operator=(const re_detail::match_results_base<iterator, Allocator>& m)
1354    {
1355       // shallow copy
1356       base_type::operator=(m);
1357       return *this;
1358    }
1359
1360    match_results(const match_results& m);
1361    match_results& operator=(const match_results& m);
1362    //
1363    // the following function definitions should *not* be required, except
1364    // when this class is used as a template inside another template definition,
1365    // in which members of the base class are not visible to the calling code.
1366    // As a workaround we define simple forwarding functions:
1367    //
1368    size_type size()const
1369    { return static_cast<const base_type*>(this)->size(); }
1370
1371    const sub_match<iterator>& operator[](int n) const
1372    { return (*static_cast<const base_type*>(this))[n]; }
1373
1374    Allocator allocator()const
1375    { return static_cast<const base_type*>(this)->allocator(); }
1376
1377    difference_type length(int sub = 0)const
1378    { return static_cast<const base_type*>(this)->length(sub); }
1379
1380    difference_type position(unsigned int sub = 0)const
1381    { return static_cast<const base_type*>(this)->position(sub); }
1382
1383    unsigned int line()const
1384    { return static_cast<const base_type*>(this)->line(); }
1385
1386    iterator line_start()const
1387    { return static_cast<const base_type*>(this)->line_start(); }
1388
1389    std::basic_string<char_type> str(int sub = 0)const
1390    { return static_cast<const base_type*>(this)->str(sub); }
1391
1392    void swap(match_results& that)
1393    { static_cast<base_type*>(this)->swap(that); }
1394
1395    bool operator==(const match_results& that)const
1396    { return static_cast<const base_type&>(*this) == static_cast<const base_type&>(that); }
1397
1398    bool operator<(const match_results& that) const
1399    { return position() < that.position(); }
1400 };
1401
1402 template <class iterator, class Allocator>
1403 match_results<iterator, Allocator>::match_results(const match_results<iterator, Allocator>& m)
1404    : re_detail::match_results_base<iterator, Allocator>(false)
1405 {
1406    this->ref =
1407       reinterpret_cast<typename re_detail::match_results_base<iterator, Allocator>::c_reference *>
1408          (m.ref->allocate(sizeof(sub_match<iterator>) * m.ref->cmatches +
1409                           sizeof(typename re_detail::match_results_base<iterator, Allocator>::c_reference)));
1410    try{
1411       new (this->ref) typename re_detail::match_results_base<iterator, Allocator>::c_reference(*m.ref);
1412       this->ref->count = 1;
1413       sub_match<iterator>* p1 = (sub_match<iterator>*)(this->ref+1);
1414       sub_match<iterator>* p2 = p1 + this->ref->cmatches;
1415       sub_match<iterator>* p3 = (sub_match<iterator>*)(m.ref+1);
1416       try{
1417          while(p1 != p2)
1418          {
1419             new (p1) sub_match<iterator>(*p3);
1420             ++p1;
1421             ++p3;
1422          }
1423       }
1424       catch(...)
1425       { 
1426          p2 = (sub_match<iterator>*)(this->ref+1);
1427          while(p2 != p1)
1428          {
1429             re_detail::jm_destroy(p2);
1430             ++p2;
1431          }
1432          re_detail::jm_destroy(this->ref);
1433          throw; 
1434       }
1435    }
1436    catch(...)
1437    { 
1438       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));
1439       throw; 
1440    }
1441 }
1442
1443 template <class iterator, class Allocator>
1444 match_results<iterator, Allocator>& match_results<iterator, Allocator>::operator=(const match_results<iterator, Allocator>& m)
1445 {
1446    match_results<iterator, Allocator> t(m);
1447    this->swap(t);
1448    return *this;
1449 }
1450
1451 namespace re_detail{
1452 template <class iterator, class charT, class traits_type, class Allocator>
1453 iterator BOOST_RE_CALL re_is_set_member(iterator next, 
1454                           iterator last, 
1455                           re_set_long* set_, 
1456                           const reg_expression<charT, traits_type, Allocator>& e);
1457 } // namepsace re_detail
1458
1459 #ifdef __BORLANDC__
1460  #if __BORLANDC__ > 0x520
1461   #pragma option pop
1462  #endif
1463 #endif
1464
1465 } // namespace boost
1466
1467 #include <boost/re_detail/regex_compile.hpp>
1468
1469 namespace boost{
1470
1471 typedef reg_expression<char, regex_traits<char>, BOOST_RE_DEF_ALLOC(char)> regex;
1472 #ifndef BOOST_RE_NO_WCSTRING
1473 typedef reg_expression<wchar_t, regex_traits<wchar_t>, BOOST_RE_DEF_ALLOC(wchar_t)> wregex;
1474 #endif
1475
1476 typedef match_results<const char*> cmatch;
1477 #ifndef BOOST_RE_NO_WCSTRING
1478 typedef match_results<const wchar_t*> wcmatch;
1479 #endif
1480
1481 } // namespace boost
1482
1483 #include <boost/re_detail/regex_match.hpp>
1484 #include <boost/re_detail/regex_format.hpp>
1485 #include <boost/re_detail/regex_split.hpp>
1486
1487
1488 #endif  // __cplusplus
1489
1490 #endif  // include
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515