summaryrefslogtreecommitdiff
path: root/utils/tfstats/regexp/include/jm/regex.h
diff options
context:
space:
mode:
Diffstat (limited to 'utils/tfstats/regexp/include/jm/regex.h')
-rw-r--r--utils/tfstats/regexp/include/jm/regex.h1722
1 files changed, 1722 insertions, 0 deletions
diff --git a/utils/tfstats/regexp/include/jm/regex.h b/utils/tfstats/regexp/include/jm/regex.h
new file mode 100644
index 0000000..99a038c
--- /dev/null
+++ b/utils/tfstats/regexp/include/jm/regex.h
@@ -0,0 +1,1722 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+/*
+ *
+ * Copyright (c) 1998-9
+ * Dr John Maddock
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Dr John Maddock makes no representations
+ * about the suitability of this software for any purpose.
+ * It is provided "as is" without express or implied warranty.
+ *
+ */
+
+ /*
+ * FILE regex.h
+ * VERSION 2.12
+ */
+
+
+/* start with C compatability API */
+
+#ifndef __REGEX_H
+#define __REGEX_H
+
+#include <cregex>
+
+#ifdef __cplusplus
+
+// what follows is all C++ don't include in C builds!!
+
+#include <new.h>
+#if !defined(JM_NO_TYPEINFO)
+#include <typeinfo>
+#endif
+#include <string.h>
+#include <jm/jstack.h>
+#include <jm/re_raw.h>
+#include <jm/re_nls.h>
+#include <jm/regfac.h>
+#include <jm/re_cls.h>
+#include <jm/re_coll.h>
+#include <jm/re_kmp.h>
+
+
+JM_NAMESPACE(__JM)
+
+//
+// define error hanling classes
+#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_EXCEPTION_H)
+// standard classes are available:
+
+class JM_IX_DECL bad_expression : public __JM_STD::exception
+{
+#ifdef RE_LOCALE_CPP
+ __JM_STD::string code;
+public:
+ bad_expression(const __JM_STD::string& s) : code(s) {}
+#else
+ unsigned int code;
+public:
+ bad_expression(unsigned int err) : code(err) {}
+#endif
+ bad_expression(const bad_expression& e) : __JM_STD::exception(e), code(e.code) {}
+ bad_expression& operator=(const bad_expression& e)
+ {
+ #ifdef _MSC_VER
+ static_cast<__JM_STD::exception*>(this)->operator=(e);
+ #else
+ __JM_STD::exception::operator=(e);
+ #endif
+ code = e.code;
+ return *this;
+ }
+ virtual const char* what()const throw();
+};
+
+#elif !defined(JM_NO_EXCEPTIONS)
+// no standard classes, do it ourselves:
+
+class JM_IX_DECL bad_expression
+{
+#ifdef RE_LOCALE_CPP
+ __JM_STD::string code;
+public:
+ bad_expression(const __JM_STD::string& s) : code(s) {}
+#else
+ unsigned int code;
+public:
+ bad_expression(unsigned int err) : code(err) {}
+#endif
+ bad_expression(const bad_expression& e) : code(e.code) {}
+ bad_expression& operator=(const bad_expression& e) { code = e.code; return *this; }
+ virtual const char* what()const throw();
+};
+
+#endif
+
+//
+// define default traits classes for char and wchar_t types:
+//
+
+struct re_set_long;
+struct re_syntax_base;
+
+enum char_syntax_type
+{
+ syntax_char = 0,
+ syntax_open_bracket = 1, // (
+ syntax_close_bracket = 2, // )
+ syntax_dollar = 3, // $
+ syntax_caret = 4, // ^
+ syntax_dot = 5, // .
+ syntax_star = 6, // *
+ syntax_plus = 7, // +
+ syntax_question = 8, // ?
+ syntax_open_set = 9, // [
+ syntax_close_set = 10, // ]
+ syntax_or = 11, // |
+ syntax_slash = 12, //
+ syntax_hash = 13, // #
+ syntax_dash = 14, // -
+ syntax_open_brace = 15, // {
+ syntax_close_brace = 16, // }
+ syntax_digit = 17, // 0-9
+ syntax_b = 18, // for \b
+ syntax_B = 19, // for \B
+ syntax_left_word = 20, // for \<
+ syntax_right_word = 21, // for \>
+ syntax_w = 22, // for \w
+ syntax_W = 23, // for \W
+ syntax_start_buffer = 24, // for \`
+ syntax_end_buffer = 25, // for \'
+ syntax_newline = 26, // for newline alt
+ syntax_comma = 27, // for {x,y}
+
+ syntax_a = 28, // for \a
+ syntax_f = 29, // for \f
+ syntax_n = 30, // for \n
+ syntax_r = 31, // for \r
+ syntax_t = 32, // for \t
+ syntax_v = 33, // for \v
+ syntax_x = 34, // for \xdd
+ syntax_c = 35, // for \cx
+ syntax_colon = 36, // for [:...:]
+ syntax_equal = 37, // for [=...=]
+
+ // perl ops:
+ syntax_e = 38, // for \e
+ syntax_l = 39, // for \l
+ syntax_L = 40, // for \L
+ syntax_u = 41, // for \u
+ syntax_U = 42, // for \U
+ syntax_s = 43, // for \s
+ syntax_S = 44, // for \S
+ syntax_d = 45, // for \d
+ syntax_D = 46, // for \D
+ syntax_E = 47, // for \Q\E
+ syntax_Q = 48, // for \Q\E
+ syntax_X = 49, // for \X
+ syntax_C = 50, // for \C
+ syntax_Z = 51, // for \Z
+ syntax_G = 52, // for \G
+
+ syntax_max = 53
+};
+
+template <class charT>
+class char_regex_traits
+{
+public:
+ typedef charT char_type;
+ //
+ // uchar_type is the same size as char_type
+ // but must be unsigned:
+ typedef charT uchar_type;
+ //
+ // size_type is normally the same as charT
+ // but could be unsigned int to improve performance
+ // of narrow character types, NB must be unsigned:
+ typedef jm_uintfast32_t size_type;
+
+ // length:
+ // returns the length of a null terminated string
+ // can be left unimplimented for non-character types.
+ static size_t length(const char_type* );
+
+ // syntax_type
+ // returns the syntax type of a given charT
+ // translates customised syntax to a unified enum.
+ static unsigned int syntax_type(size_type c);
+
+ // translate:
+ //
+ static charT RE_CALL translate(charT c, bool icase
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale&
+ #endif
+ );
+
+ // transform:
+ //
+ // converts a string into a sort key for locale dependant
+ // character ranges.
+ static void RE_CALL transform(re_str<charT>& out, const re_str<charT>& in
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale&
+ #endif
+ );
+
+ // transform_primary:
+ //
+ // converts a string into a primary sort key for locale dependant
+ // equivalence classes.
+ static void RE_CALL transform_primary(re_str<charT>& out, const re_str<charT>& in
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale&
+ #endif
+ );
+
+ // is_separator
+ // returns true if c is a newline character
+ static bool RE_CALL is_separator(charT c);
+
+ // is_combining
+ // returns true if the character is a unicode
+ // combining character
+ static bool RE_CALL is_combining(charT c);
+
+ // is_class
+ // returns true if the character is a member
+ // of the specified character class
+ static bool RE_CALL is_class(charT c, jm_uintfast32_t f
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale&
+ #endif
+ );
+
+ // toi
+ // converts c to integer
+ static int RE_CALL toi(charT c
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale&
+ #endif
+ );
+
+ // toi
+ // converts multi-character value to int
+ // updating first as required
+ static int RE_CALL toi(const charT*& first, const charT* last, int radix
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale&
+ #endif
+ );
+
+ // lookup_classname
+ // parses a class declaration of the form [:class:]
+ // On entry first points to the first character of the class name.
+ //
+ static jm_uintfast32_t RE_CALL lookup_classname(const charT* first, const charT* last
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale&
+ #endif
+ );
+
+ // lookup_collatename
+ // parses a collating element declaration of the form [.collating_name.]
+ // On entry first points to the first character of the collating element name.
+ //
+ static bool RE_CALL lookup_collatename(re_str<charT>& s, const charT* first, const charT* last
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale&
+ #endif
+ );
+
+};
+
+JM_TEMPLATE_SPECIALISE
+class char_regex_traits<char>
+{
+public:
+ typedef char char_type;
+ typedef unsigned char uchar_type;
+ typedef unsigned int size_type;
+ static size_t RE_CALL length(const char_type* p)
+ {
+ return strlen(p);
+ }
+ static unsigned int RE_CALL syntax_type(size_type c
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ return JM_USE_FACET(l, regfacet<char>).syntax_type((char)c);
+ #else
+ return re_syntax_map[c];
+ #endif
+ }
+ static char RE_CALL translate(char c, bool icase
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ return icase ? JM_USE_FACET(l, __JM_STD::ctype<char>).tolower((char_type)c) : c;
+ #else
+ return icase ? re_lower_case_map[(size_type)(uchar_type)c] : c;
+ #endif
+ }
+ static void RE_CALL transform(re_str<char>& out, const re_str<char>& in
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+#ifndef RE_LOCALE_CPP
+ re_transform(out, in);
+#else
+ out = JM_USE_FACET(l, __JM_STD::collate<char>).transform(in.c_str(), in.c_str() + in.size()).c_str();
+#endif
+ }
+
+ static void RE_CALL transform_primary(re_str<char>& out, const re_str<char>& in
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ transform(out, in MAYBE_PASS_LOCALE(l));
+#ifdef RE_LOCALE_W32
+ re_trunc_primary(out);
+#else
+ unsigned n = in.size() + out.size() / 4;
+ if(n < out.size())
+ out[n] = 0;
+#endif
+ }
+
+ static bool RE_CALL is_separator(char c)
+ {
+ return JM_MAKE_BOOL((c == '\n') || (c == '\r'));
+ }
+
+ static bool RE_CALL is_combining(char)
+ {
+ return false;
+ }
+
+ static bool RE_CALL is_class(char c, jm_uintfast32_t f
+#ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+#endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ if(JM_USE_FACET(l, __JM_STD::ctype<char>).is((__JM_STD::ctype<char>::mask)(f & char_class_all_base), c))
+ return true;
+ if((f & char_class_underscore) && (c == '_'))
+ return true;
+ if((f & char_class_blank) && ((c == ' ') || (c == '\t')))
+ return true;
+ return false;
+ #else
+ return JM_MAKE_BOOL(re_class_map[(size_type)(uchar_type)c] & f);
+ #endif
+ }
+ static int RE_CALL toi(char c
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ return re_toi(c MAYBE_PASS_LOCALE(l));
+ }
+ static int RE_CALL toi(const char*& first, const char* last, int radix
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ return re_toi(first, last, radix MAYBE_PASS_LOCALE(l));
+ }
+
+ static jm_uintfast32_t RE_CALL lookup_classname(const char* first, const char* last
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ return JM_USE_FACET(l, regfacet<char>).lookup_classname(first, last);
+ #else
+ return re_lookup_class(first, last);
+ #endif
+ }
+
+ static bool RE_CALL lookup_collatename(re_str<char>& s, const char* first, const char* last
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ re_str<char> n(first, last);
+ return JM_USE_FACET(l, regfacet<char>).lookup_collatename(s, n);
+ #else
+ return re_lookup_collate(s, first, last);
+ #endif
+ }
+};
+
+#ifndef JM_NO_WCSTRING
+JM_TEMPLATE_SPECIALISE
+class char_regex_traits<wchar_t>
+{
+public:
+ typedef wchar_t char_type;
+ typedef unsigned short uchar_type;
+ typedef unsigned int size_type;
+ static size_t RE_CALL length(const char_type* p)
+ {
+ return wcslen(p);
+ }
+ static unsigned int RE_CALL syntax_type(size_type c
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ return JM_USE_FACET(l, regfacet<wchar_t>).syntax_type((wchar_t)c);
+ #else
+ return re_get_syntax_type(c);
+ #endif
+ }
+ static wchar_t RE_CALL translate(wchar_t c, bool icase
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ return icase ? JM_USE_FACET(l, __JM_STD::ctype<wchar_t>).tolower((char_type)c) : c;
+ #else
+ return icase ? ((c < 256) ? re_lower_case_map_w[(uchar_type)c] : re_wtolower(c)) : c;
+ #endif
+ }
+
+ static void RE_CALL transform(re_str<wchar_t>& out, const re_str<wchar_t>& in
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+#ifndef RE_LOCALE_CPP
+ re_transform(out, in);
+#else
+ out = JM_USE_FACET(l, __JM_STD::collate<wchar_t>).transform(in.c_str(), in.c_str() + in.size()).c_str();
+#endif
+ }
+
+ static void RE_CALL transform_primary(re_str<wchar_t>& out, const re_str<wchar_t>& in
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ transform(out, in MAYBE_PASS_LOCALE(l));
+#ifdef RE_LOCALE_W32
+ re_trunc_primary(out);
+#else
+ unsigned n = in.size() + out.size() / 4;
+ if(n < out.size())
+ out[n] = 0;
+#endif
+ }
+
+ static bool RE_CALL is_separator(wchar_t c)
+ {
+ return JM_MAKE_BOOL((c == L'\n') || (c == L'\r') || (c == (wchar_t)0x2028) || (c == (wchar_t)0x2029));
+ }
+
+ static bool RE_CALL is_combining(wchar_t c)
+ {
+ return re_is_combining(c);
+ }
+
+ static bool RE_CALL is_class(wchar_t c, jm_uintfast32_t f
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ if(JM_USE_FACET(l, __JM_STD::ctype<wchar_t>).is((__JM_STD::ctype<wchar_t>::mask)(f & char_class_all_base), c))
+ return true;
+ if((f & char_class_underscore) && (c == '_'))
+ return true;
+ if((f & char_class_blank) && ((c == ' ') || (c == '\t')))
+ return true;
+ if((f & char_class_unicode) && (c > (size_type)(uchar_type)255))
+ return true;
+ return false;
+ #else
+ return JM_MAKE_BOOL(((uchar_type)c < 256) ? (re_unicode_classes[(size_type)(uchar_type)c] & f) : re_iswclass(c, f));
+ #endif
+ }
+ static int RE_CALL toi(wchar_t c
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ return re_toi(c MAYBE_PASS_LOCALE(l));
+ }
+ static int RE_CALL toi(const wchar_t*& first, const wchar_t* last, int radix
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ return re_toi(first, last, radix MAYBE_PASS_LOCALE(l));
+ }
+
+ static jm_uintfast32_t RE_CALL lookup_classname(const wchar_t* first, const wchar_t* last
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ return JM_USE_FACET(l, regfacet<wchar_t>).lookup_classname(first, last);
+ #else
+ return re_lookup_class(first, last);
+ #endif
+ }
+
+
+ static bool RE_CALL lookup_collatename(re_str<wchar_t>& s, const wchar_t* first, const wchar_t* last
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ re_str<wchar_t> n(first, last);
+ return JM_USE_FACET(l, regfacet<wchar_t>).lookup_collatename(s, n);
+ #else
+ return re_lookup_collate(s, first, last);
+ #endif
+ }
+};
+#endif
+
+//
+// class char_regex_traits_i
+// provides case insensitive traits classes:
+template <class charT>
+class char_regex_traits_i : public char_regex_traits<charT> {};
+
+JM_TEMPLATE_SPECIALISE
+class char_regex_traits_i<char> : public char_regex_traits<char>
+{
+public:
+ typedef char char_type;
+ typedef unsigned char uchar_type;
+ typedef unsigned int size_type;
+ typedef char_regex_traits<char> base_type;
+
+ static char RE_CALL translate(char c, bool
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ return JM_USE_FACET(l, __JM_STD::ctype<char>).tolower((char_type)c);
+ #else
+ return re_lower_case_map[(size_type)(uchar_type)c];
+ #endif
+ }
+};
+
+#ifndef JM_NO_WCSTRING
+JM_TEMPLATE_SPECIALISE
+class char_regex_traits_i<wchar_t> : public char_regex_traits<wchar_t>
+{
+public:
+ typedef wchar_t char_type;
+ typedef unsigned short uchar_type;
+ typedef unsigned int size_type;
+ typedef char_regex_traits<wchar_t> base_type;
+
+ static wchar_t RE_CALL translate(wchar_t c, bool
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ #ifdef RE_LOCALE_CPP
+ return JM_USE_FACET(l, __JM_STD::ctype<wchar_t>).tolower((char_type)c);
+ #else
+ return (c < 256) ? re_lower_case_map_w[(uchar_type)c] : re_wtolower(c);
+ #endif
+ }
+ static jm_uintfast32_t RE_CALL lookup_classname(const wchar_t* first, const wchar_t* last
+ #ifdef RE_LOCALE_CPP
+ , const __JM_STD::locale& l
+ #endif
+ )
+ {
+ jm_uintfast32_t result = char_regex_traits<wchar_t>::lookup_classname(first, last MAYBE_PASS_LOCALE(l));
+ if((result & char_class_upper) == char_class_upper)
+ result |= char_class_alpha;
+ return result;
+ }
+};
+#endif
+
+enum mask_type
+{
+ mask_take = 1,
+ mask_skip = 2,
+ mask_any = mask_skip | mask_take,
+ mask_all = mask_any
+};
+
+struct __narrow_type{};
+struct __wide_type{};
+
+template <class charT>
+class is_byte;
+
+JM_TEMPLATE_SPECIALISE
+class is_byte<char>
+{
+public:
+ typedef __narrow_type width_type;
+};
+
+JM_TEMPLATE_SPECIALISE
+class is_byte<unsigned char>
+{
+public:
+ typedef __narrow_type width_type;
+};
+
+JM_TEMPLATE_SPECIALISE
+class is_byte<signed char>
+{
+public:
+ typedef __narrow_type width_type;
+};
+
+template <class charT>
+class is_byte
+{
+public:
+ typedef __wide_type width_type;
+};
+
+
+//
+// compiled structures
+//
+// the following defs describe the format of the compiled string
+//
+
+//
+// enum syntax_element_type
+// describes the type of a record
+enum syntax_element_type
+{
+ syntax_element_startmark = 0,
+ syntax_element_endmark = syntax_element_startmark + 1,
+ syntax_element_literal = syntax_element_endmark + 1,
+ syntax_element_start_line = syntax_element_literal + 1,
+ syntax_element_end_line = syntax_element_start_line + 1,
+ syntax_element_wild = syntax_element_end_line + 1,
+ syntax_element_match = syntax_element_wild + 1,
+ syntax_element_word_boundary = syntax_element_match + 1,
+ syntax_element_within_word = syntax_element_word_boundary + 1,
+ syntax_element_word_start = syntax_element_within_word + 1,
+ syntax_element_word_end = syntax_element_word_start + 1,
+ syntax_element_buffer_start = syntax_element_word_end + 1,
+ syntax_element_buffer_end = syntax_element_buffer_start + 1,
+ syntax_element_backref = syntax_element_buffer_end + 1,
+ syntax_element_long_set = syntax_element_backref + 1,
+ syntax_element_set = syntax_element_long_set + 1,
+ syntax_element_jump = syntax_element_set + 1,
+ syntax_element_alt = syntax_element_jump + 1,
+ syntax_element_rep = syntax_element_alt + 1,
+ syntax_element_combining = syntax_element_rep + 1,
+ syntax_element_soft_buffer_end = syntax_element_combining + 1,
+ syntax_element_restart_continue = syntax_element_soft_buffer_end + 1
+};
+
+union offset_type
+{
+ re_syntax_base* p;
+ unsigned i;
+};
+
+//
+// struct re_syntax_base
+// base class for all syntax types:
+struct re_syntax_base
+{
+ syntax_element_type type;
+ offset_type next;
+ unsigned int can_be_null;
+};
+
+//
+// struct re_brace
+// marks start or end of (...)
+struct re_brace : public re_syntax_base
+{
+ unsigned int index;
+};
+
+//
+// struct re_literal
+// marks a literal string and
+// is followed by an array of charT[length]:
+struct re_literal : public re_syntax_base
+{
+ unsigned int length;
+};
+
+//
+// struct re_long_set
+// provides data for sets [...] containing
+// wide characters
+struct re_set_long : public re_syntax_base
+{
+ unsigned int csingles, cranges, cequivalents;
+ jm_uintfast32_t cclasses;
+ bool isnot;
+};
+
+//
+// struct re_set
+// provides a map of bools for sets containing
+// narrow, single byte characters.
+struct re_set : public re_syntax_base
+{
+ unsigned char __map[256];
+};
+
+//
+// struct re_jump
+// provides alternative next destination
+struct re_jump : public re_syntax_base
+{
+ offset_type alt;
+ unsigned char __map[256];
+};
+
+//
+// struct re_repeat
+// provides repeat expressions
+struct re_repeat : public re_jump
+{
+ unsigned min, max;
+ int id;
+ bool leading;
+};
+
+
+//
+// enum re_jump_size_type
+// provides compiled size of re_jump
+// allowing for trailing alignment
+// provide this so we know how many
+// bytes to insert
+enum re_jump_size_type
+{
+ re_jump_size = (sizeof(re_jump) + sizeof(padding) - 1) & ~(sizeof(padding) - 1),
+ re_repeater_size = (sizeof(re_repeat) + sizeof(padding) - 1) & ~(sizeof(padding) - 1)
+};
+
+
+//
+// class basic_regex
+// handles error codes and flags
+
+class JM_IX_DECL regbase
+{
+protected:
+#ifdef RE_LOCALE_CPP
+ __JM_STD::locale locale_inst;
+#endif
+ jm_uintfast32_t _flags;
+ unsigned int code;
+public:
+ enum flag_type
+ {
+ escape_in_lists = 1, // '\' special inside [...]
+ char_classes = escape_in_lists << 1, // [[:CLASS:]] allowed
+ intervals = char_classes << 1, // {x,y} allowed
+ limited_ops = intervals << 1, // all of + ? and | are normal characters
+ newline_alt = limited_ops << 1, // \n is the same as |
+ bk_plus_qm = newline_alt << 1, // uses \+ and \?
+ bk_braces = bk_plus_qm << 1, // uses \{ and \}
+ bk_parens = bk_braces << 1, // uses \( and \)
+ bk_refs = bk_parens << 1, // \d allowed
+ bk_vbar = bk_refs << 1, // uses \|
+ use_except = bk_vbar << 1, // exception on error
+ failbit = use_except << 1, // error flag
+ literal = failbit << 1, // all characters are literals
+ icase = literal << 1, // characters are matched regardless of case
+ nocollate = icase << 1, // don't use locale specific collation
+
+ basic = char_classes | intervals | limited_ops | bk_braces | bk_parens | bk_refs,
+ extended = char_classes | intervals | bk_refs,
+ normal = escape_in_lists | char_classes | intervals | bk_refs | nocollate
+ };
+
+ enum restart_info
+ {
+ restart_any = 0,
+ restart_word = 1,
+ restart_line = 2,
+ restart_buf = 3,
+ restart_continue = 4,
+ restart_lit = 5,
+ restart_fixed_lit = 6
+ };
+
+ unsigned int RE_CALL error_code()const
+ {
+ return code;
+ }
+
+ void RE_CALL fail(unsigned int err);
+
+ jm_uintfast32_t RE_CALL flags()const
+ {
+ return _flags;
+ }
+#ifdef RE_LOCALE_CPP
+ __JM_STD::string RE_CALL errmsg()const
+ {
+ return re_get_error_str(code, locale_inst);
+ }
+#else
+ const char* RE_CALL errmsg()const
+ {
+ return re_get_error_str(code);
+ }
+#endif
+
+ regbase();
+ regbase(const regbase& b);
+
+ #ifdef RE_LOCALE_CPP
+ __JM_STD::locale RE_CALL imbue(const __JM_STD::locale& l);
+
+ const __JM_STD::locale& RE_CALL locale()const
+ {
+ return locale_inst;
+ }
+ #endif
+};
+
+//
+// some forward declarations:
+
+template <class iterator, class Allocator JM_DEF_ALLOC_PARAM(iterator) >
+class reg_match;
+
+template <class iterator, class Allocator>
+class __priv_match_data;
+
+
+//
+// class reg_expression
+// represents the compiled
+// regular expression:
+//
+
+#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
+//
+// Ugly ugly hack,
+// template don't merge if they contain switch statements so declare these
+// templates in unnamed namespace (ie with internal linkage), each translation
+// unit then gets its own local copy, it works seemlessly but bloats the app.
+namespace{
+#endif
+
+template <class charT, class traits JM_TRICKY_DEFAULT_PARAM(char_regex_traits<charT>), class Allocator JM_DEF_ALLOC_PARAM(charT) >
+class reg_expression : public regbase
+{
+public:
+ // typedefs:
+ typedef Allocator alloc_type;
+ typedef typename REBIND_TYPE(charT, alloc_type)::size_type size_type;
+ typedef charT value_type;
+ typedef charT char_type;
+ typedef traits traits_type;
+ typedef typename traits_type::size_type traits_size_type;
+ typedef typename traits_type::uchar_type traits_uchar_type;
+
+private:
+#if defined(RE_LOCALE_C) || defined(RE_LOCALE_W32)
+ re_initialiser<charT> locale_initialiser;
+#endif
+ raw_storage<Allocator> data;
+ unsigned _restart_type;
+ unsigned marks;
+ int repeats;
+ unsigned char* startmap;
+ charT* _expression;
+ unsigned int _leading_len;
+ const charT* _leading_string;
+ unsigned int _leading_string_len;
+ kmp_info<charT>* pkmp;
+
+ void RE_CALL compile_maps();
+ void RE_CALL compile_map(re_syntax_base* node, unsigned char* __map, unsigned int* pnull, unsigned char mask, re_syntax_base* terminal = NULL)const;
+ bool RE_CALL probe_start(re_syntax_base* node, charT c, re_syntax_base* terminal)const;
+ bool RE_CALL probe_start_null(re_syntax_base* node, re_syntax_base* terminal)const;
+ void RE_CALL fixup_apply(re_syntax_base* b, unsigned cbraces);
+ void RE_CALL move_offsets(re_syntax_base* j, unsigned size);
+ re_syntax_base* RE_CALL compile_set(const charT*& first, const charT* last);
+ re_syntax_base* RE_CALL compile_set_aux(jstack<re_str<charT>, Allocator>& singles, jstack<re_str<charT>, Allocator>& ranges, jstack<jm_uintfast32_t, Allocator>& classes, jstack<re_str<charT>, Allocator>& equivalents, bool isnot, const __narrow_type&);
+ re_syntax_base* RE_CALL compile_set_aux(jstack<re_str<charT>, Allocator>& singles, jstack<re_str<charT>, Allocator>& ranges, jstack<jm_uintfast32_t, Allocator>& classes, jstack<re_str<charT>, Allocator>& equivalents, bool isnot, const __wide_type&);
+ re_syntax_base* RE_CALL compile_set_simple(re_syntax_base* dat, unsigned long cls, bool isnot = false);
+ unsigned int RE_CALL parse_inner_set(const charT*& first, const charT* last);
+
+ re_syntax_base* RE_CALL add_simple(re_syntax_base* dat, syntax_element_type type, unsigned int size = sizeof(re_syntax_base));
+ re_syntax_base* RE_CALL add_literal(re_syntax_base* dat, charT c);
+ charT RE_CALL parse_escape(const charT*& first, const charT* last);
+ void RE_CALL parse_range(const charT*& first, const charT* last, unsigned& min, unsigned& max);
+ bool RE_CALL skip_space(const charT*& first, const charT* last);
+ unsigned int RE_CALL probe_restart(re_syntax_base* dat);
+ unsigned int RE_CALL fixup_leading_rep(re_syntax_base* dat, re_syntax_base* end);
+
+public:
+ unsigned int RE_CALL set_expression(const charT* p, const charT* end, jm_uintfast32_t f = regbase::normal);
+ unsigned int RE_CALL set_expression(const charT* p, jm_uintfast32_t f = regbase::normal) { return set_expression(p, p + traits_type::length(p), f); }
+ reg_expression(const Allocator& a = Allocator());
+ reg_expression(const charT* p, jm_uintfast32_t f = regbase::normal, const Allocator& a = Allocator());
+ reg_expression(const charT* p1, const charT* p2, jm_uintfast32_t f = regbase::normal, const Allocator& a = Allocator());
+ reg_expression(const charT* p, size_type len, jm_uintfast32_t f, const Allocator& a = Allocator());
+ reg_expression(const reg_expression&);
+ ~reg_expression();
+ reg_expression& RE_CALL operator=(const reg_expression&);
+
+#ifndef JM_NO_MEMBER_TEMPLATES
+
+ template <class ST, class SA>
+ unsigned int RE_CALL set_expression(const __JM_STD::basic_string<charT, ST, SA>& p, jm_uintfast32_t f = regbase::normal)
+ { return set_expression(p.data(), p.data() + p.size(), f); }
+
+ template <class ST, class SA>
+ reg_expression(const __JM_STD::basic_string<charT, ST, SA>& p, jm_uintfast32_t f = regbase::normal, const Allocator& a = Allocator())
+ : data(a), pkmp(0) { set_expression(p, f); }
+
+#elif !defined(JM_NO_STRING_DEF_ARGS)
+ unsigned int RE_CALL set_expression(const __JM_STD::basic_string<charT>& p, jm_uintfast32_t f = regbase::normal)
+ { return set_expression(p.data(), p.data() + p.size(), f); }
+
+ reg_expression(const __JM_STD::basic_string<charT>& p, jm_uintfast32_t f = regbase::normal, const Allocator& a = Allocator())
+ : data(a), pkmp(0) { set_expression(p, f); }
+
+#endif
+
+
+ bool RE_CALL operator==(const reg_expression&);
+ bool RE_CALL operator<(const reg_expression&);
+ alloc_type RE_CALL allocator()const;
+ const charT* RE_CALL expression()const { return _expression; }
+ unsigned RE_CALL mark_count()const { return marks; }
+
+#if !defined(JM_NO_TEMPLATE_FRIEND) && (!defined(JM_NO_TEMPLATE_SWITCH_MERGE) || defined(JM_NO_NAMESPACES))
+#if 0
+ template <class Predicate, class I, class charT, class traits, class A, class A2>
+ friend unsigned int reg_grep2(Predicate foo, I first, I last, const reg_expression<charT, traits, A>& e, unsigned flags, A2 a);
+
+ template <class I, class A, class charT, class traits, class A2>
+ friend bool query_match(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, unsigned flags);
+
+ template <class I, class A, class charT, class traits, class A2>
+ friend bool query_match_aux(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e,
+ unsigned flags, __priv_match_data<I, A>& pd, I* restart);
+
+ template <class I, class A, class charT, class traits, class A2>
+ friend bool reg_search(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, unsigned flags);
+private:
+#endif
+#endif
+
+ int RE_CALL repeat_count() const { return repeats; }
+ unsigned int RE_CALL restart_type()const { return _restart_type; }
+ const re_syntax_base* RE_CALL first()const { return (const re_syntax_base*)data.data(); }
+ const unsigned char* RE_CALL get_map()const { return startmap; }
+ unsigned int RE_CALL leading_length()const { return _leading_len; }
+ const kmp_info<charT>* get_kmp()const { return pkmp; }
+ static bool RE_CALL can_start(charT c, const unsigned char* __map, unsigned char mask, const __wide_type&);
+ static bool RE_CALL can_start(charT c, const unsigned char* __map, unsigned char mask, const __narrow_type&);
+};
+
+#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
+} // namespace
+#endif
+
+
+//
+// class reg_match and reg_match_base
+// handles what matched where
+
+template <class iterator>
+struct sub_match
+{
+ iterator first;
+ iterator second;
+ bool matched;
+#ifndef JM_NO_MEMBER_TEMPLATES
+ template <class charT, class traits, class Allocator>
+ operator __JM_STD::basic_string<charT, traits, Allocator> ()const;
+#elif !defined(JM_NO_STRING_DEF_ARGS)
+ operator __JM_STD::basic_string<char> ()const;
+ operator __JM_STD::basic_string<wchar_t> ()const;
+#endif
+ operator int()const;
+ operator unsigned int()const;
+ operator short()const
+ {
+ return (short)(int)(*this);
+ }
+ operator unsigned short()const
+ {
+ return (unsigned short)(unsigned int)(*this);
+ }
+ sub_match() { matched = false; }
+ sub_match(iterator i) : first(i), second(i), matched(false) {}
+};
+
+#ifndef JM_NO_MEMBER_TEMPLATES
+template <class iterator>
+template <class charT, class traits, class Allocator>
+sub_match<iterator>::operator __JM_STD::basic_string<charT, traits, Allocator> ()const
+{
+#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
+ if(typeid(charT) != typeid(*first))
+ throw __JM_STD::bad_cast();
+#endif
+ __JM_STD::basic_string<charT, traits, Allocator> result;
+ iterator i = first;
+ while(i != second)
+ {
+ result.append(1, *i);
+ ++i;
+ }
+ return result;
+}
+#elif !defined(JM_NO_STRING_DEF_ARGS)
+template <class iterator>
+sub_match<iterator>::operator __JM_STD::basic_string<char> ()const
+{
+#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
+ if(typeid(char) != typeid(*first))
+ throw __JM_STD::bad_cast();
+#endif
+ __JM_STD::basic_string<char> result;
+ iterator i = first;
+ while(i != second)
+ {
+ result.append(1, *i);
+ ++i;
+ }
+ return result;
+}
+template <class iterator>
+sub_match<iterator>::operator __JM_STD::basic_string<wchar_t> ()const
+{
+#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
+ if(typeid(wchar_t) != typeid(*first))
+ throw __JM_STD::bad_cast();
+#endif
+ __JM_STD::basic_string<wchar_t> result;
+ iterator i = first;
+ while(i != second)
+ {
+ result.append(1, *i);
+ ++i;
+ }
+ return result;
+}
+#endif
+template <class iterator>
+sub_match<iterator>::operator int()const
+{
+ iterator i = first;
+ int neg = 1;
+ if((i != second) && (*i == '-'))
+ {
+ neg = -1;
+ ++i;
+ }
+ neg *= (int)re_toi(i, second, 10 MAYBE_PASS_LOCALE(__JM_STD::locale()));
+#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
+ if(i != second)
+ {
+ throw __JM_STD::bad_cast();
+ }
+#endif
+ return neg;
+}
+template <class iterator>
+sub_match<iterator>::operator unsigned int()const
+{
+ iterator i = first;
+ unsigned int result = (int)re_toi(i, second, 10 MAYBE_PASS_LOCALE(__JM_STD::locale()));
+#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
+ if(i != second)
+ {
+ throw __JM_STD::bad_cast();
+ }
+#endif
+ return result;
+}
+
+
+template <class iterator, class Allocator JM_DEF_ALLOC_PARAM(iterator) >
+class reg_match_base
+{
+public:
+ typedef Allocator alloc_type;
+ typedef typename REBIND_TYPE(iterator, Allocator)::size_type size_type;
+ typedef JM_MAYBE_TYPENAME REBIND_TYPE(char, Allocator) c_alloc;
+ typedef iterator value_type;
+
+protected:
+ struct reference : public c_alloc
+ {
+ unsigned int cmatches;
+ unsigned count;
+ sub_match<iterator> head, tail, null;
+ unsigned int lines;
+ iterator line_pos;
+ reference(const Allocator& a) : c_alloc(a) { }
+ };
+
+ reference* ref;
+
+ void RE_CALL cow();
+
+ // protected contructor for derived class...
+ reg_match_base(bool){}
+ void RE_CALL free();
+
+public:
+
+ reg_match_base(const Allocator& a = Allocator());
+
+ reg_match_base(const reg_match_base& m)
+ {
+ ref = m.ref;
+ ++(ref->count);
+ }
+
+ reg_match_base& RE_CALL operator=(const reg_match_base& m);
+
+ ~reg_match_base()
+ {
+ free();
+ }
+
+ size_type RE_CALL size()const
+ {
+ return ref->cmatches;
+ }
+
+ const sub_match<iterator>& RE_CALL operator[](int n) const
+ {
+ if((n >= 0) && ((unsigned int)n < ref->cmatches))
+ return *(sub_match<iterator>*)((char*)ref + sizeof(reference) + sizeof(sub_match<iterator>)*n);
+ return (n == -1) ? ref->head : (n == -2) ? ref->tail : ref->null;
+ }
+
+ Allocator RE_CALL allocator()const;
+
+ size_t RE_CALL length()const
+ {
+ jm_assert(ref->cmatches);
+ size_t n = 0;
+ JM_DISTANCE(((sub_match<iterator>*)(ref+1))->first, ((sub_match<iterator>*)(ref+1))->second, n);
+ return n;
+ }
+
+ unsigned int RE_CALL line()const
+ {
+ return ref->lines;
+ }
+
+ iterator RE_CALL line_start()const
+ {
+ return ref->line_pos;
+ }
+
+ void swap(reg_match_base& that)
+ {
+ reference* t = that.ref;
+ that.ref = ref;
+ ref = t;
+ }
+
+ friend class reg_match<iterator, Allocator>;
+#if !defined(JM_NO_TEMPLATE_FRIEND) && (!defined(JM_NO_TEMPLATE_SWITCH_MERGE) || defined(JM_NO_NAMESPACES))
+private:
+ template <class Predicate, class I, class charT, class traits, class A, class A2>
+ friend unsigned int reg_grep2(Predicate foo, I first, I last, const reg_expression<charT, traits, A>& e, unsigned flags, A2 a);
+
+ template <class I, class A, class charT, class traits, class A2>
+ friend bool query_match(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, unsigned flags);
+
+ template <class I, class A, class charT, class traits, class A2>
+ friend bool query_match_aux(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e,
+ unsigned flags, __priv_match_data<I, A>& pd, I* restart);
+
+ template <class I, class A, class charT, class traits, class A2>
+ friend bool reg_search(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, unsigned flags);
+#endif
+ void RE_CALL set_size(size_type n);
+ void RE_CALL set_size(size_type n, iterator i, iterator j);
+ void RE_CALL maybe_assign(const reg_match_base& m);
+ void RE_CALL init_fail(iterator i, iterator j);
+
+ void RE_CALL set_first(iterator i)
+ {
+ cow();
+ ((sub_match<iterator>*)(ref+1))->first = i;
+ ref->head.second = i;
+ ref->head.matched = (ref->head.first == ref->head.second) ? false : true;
+ }
+
+ void RE_CALL set_first(iterator i, size_t pos)
+ {
+ cow();
+ ((sub_match<iterator>*)((char*)ref + sizeof(reference) + sizeof(sub_match<iterator>) * pos))->first = i;
+ if(pos == 0)
+ {
+ ref->head.second = i;
+ ref->head.matched = (ref->head.first == ref->head.second) ? false : true;
+ }
+ }
+
+ void RE_CALL set_second(iterator i)
+ {
+ cow();
+ ((sub_match<iterator>*)(ref+1))->second = i;
+ ((sub_match<iterator>*)(ref+1))->matched = true;
+ ref->tail.first = i;
+ ref->tail.matched = (ref->tail.first == ref->tail.second) ? false : true;
+ }
+
+ void RE_CALL set_second(iterator i, size_t pos)
+ {
+ cow();
+ ((sub_match<iterator>*)((char*)ref + sizeof(reference) + sizeof(sub_match<iterator>) * pos))->second = i;
+ ((sub_match<iterator>*)((char*)ref + sizeof(reference) + sizeof(sub_match<iterator>) * pos))->matched = true;
+ if(pos == 0)
+ {
+ ref->tail.first = i;
+ ref->tail.matched = (ref->tail.first == ref->tail.second) ? false : true;
+ }
+ }
+
+ void RE_CALL set_line(unsigned int i, iterator pos)
+ {
+ ref->lines = i;
+ ref->line_pos = pos;
+ }
+};
+
+template <class iterator, class Allocator>
+reg_match_base<iterator, Allocator>::reg_match_base(const Allocator& a)
+{
+ ref = (reference*)c_alloc(a).allocate(sizeof(sub_match<iterator>) + sizeof(reference));
+#ifndef JM_NO_EXCEPTIONS
+ try
+ {
+#endif
+ new (ref) reference(a);
+ ref->cmatches = 1;
+ ref->count = 1;
+ // construct the sub_match<iterator>:
+#ifndef JM_NO_EXCEPTIONS
+ try
+ {
+#endif
+ new ((sub_match<iterator>*)(ref+1)) sub_match<iterator>();
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ jm_destroy(ref);
+ throw;
+ }
+#endif
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ c_alloc(a).deallocate((char*)(void*)ref, sizeof(sub_match<iterator>) + sizeof(reference));
+ throw;
+ }
+#endif
+}
+
+template <class iterator, class Allocator>
+Allocator RE_CALL reg_match_base<iterator, Allocator>::allocator()const
+{
+ return *((c_alloc*)ref);
+}
+
+template <class iterator, class Allocator>
+inline reg_match_base<iterator, Allocator>& RE_CALL reg_match_base<iterator, Allocator>::operator=(const reg_match_base<iterator, Allocator>& m)
+{
+ if(ref != m.ref)
+ {
+ free();
+ ref = m.ref;
+ ++(ref->count);
+ }
+ return *this;
+}
+
+
+template <class iterator, class Allocator>
+void RE_CALL reg_match_base<iterator, Allocator>::free()
+{
+ if(--(ref->count) == 0)
+ {
+ c_alloc a(*ref);
+ sub_match<iterator>* p1, *p2;
+ p1 = (sub_match<iterator>*)(ref+1);
+ p2 = p1 + ref->cmatches;
+ while(p1 != p2)
+ {
+ jm_destroy(p1);
+ ++p1;
+ }
+ jm_destroy(ref);
+ a.deallocate((char*)(void*)ref, sizeof(sub_match<iterator>) * ref->cmatches + sizeof(reference));
+ }
+}
+
+template <class iterator, class Allocator>
+void RE_CALL reg_match_base<iterator, Allocator>::set_size(size_type n)
+{
+ if(ref->cmatches != n)
+ {
+ reference* newref = (reference*)ref->allocate(sizeof(sub_match<iterator>) * n + sizeof(reference));
+#ifndef JM_NO_EXCEPTIONS
+ try
+ {
+#endif
+ new (newref) reference(*ref);
+ newref->count = 1;
+ newref->cmatches = n;
+ sub_match<iterator>* p1, *p2;
+ p1 = (sub_match<iterator>*)(newref+1);
+ p2 = p1 + newref->cmatches;
+#ifndef JM_NO_EXCEPTIONS
+ try
+ {
+#endif
+ while(p1 != p2)
+ {
+ new (p1) sub_match<iterator>();
+ ++p1;
+ }
+ free();
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ p2 = (sub_match<iterator>*)(newref+1);
+ while(p2 != p1)
+ {
+ jm_destroy(p2);
+ ++p2;
+ }
+ jm_destroy(ref);
+ throw;
+ }
+#endif
+ ref = newref;
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * n + sizeof(reference));
+ throw;
+ }
+#endif
+ }
+}
+
+template <class iterator, class Allocator>
+void RE_CALL reg_match_base<iterator, Allocator>::set_size(size_type n, iterator i, iterator j)
+{
+ if(ref->cmatches != n)
+ {
+ reference* newref = (reference*)ref->allocate(sizeof(sub_match<iterator>) * n + sizeof(reference));;
+#ifndef JM_NO_EXCEPTIONS
+ try{
+#endif
+ new (newref) reference(*ref);
+ newref->count = 1;
+ newref->cmatches = n;
+ sub_match<iterator>* p1, *p2;
+ p1 = (sub_match<iterator>*)(newref+1);
+ p2 = p1 + newref->cmatches;
+#ifndef JM_NO_EXCEPTIONS
+ try
+ {
+#endif
+ while(p1 != p2)
+ {
+ new (p1) sub_match<iterator>(j);
+ ++p1;
+ }
+ free();
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ p2 = (sub_match<iterator>*)(newref+1);
+ while(p2 != p1)
+ {
+ jm_destroy(p2);
+ ++p2;
+ }
+ jm_destroy(ref);
+ throw;
+ }
+#endif
+ ref = newref;
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * n + sizeof(reference));
+ throw;
+ }
+#endif
+ }
+ else
+ {
+ cow();
+ // set iterators to be i, matched to false:
+ sub_match<iterator>* p1, *p2;
+ p1 = (sub_match<iterator>*)(ref+1);
+ p2 = p1 + ref->cmatches;
+ while(p1 != p2)
+ {
+ p1->first = j;
+ p1->second = j;
+ p1->matched = false;
+ ++p1;
+ }
+ }
+ ref->head.first = i;
+ ref->tail.second = j;
+ ref->head.matched = ref->tail.matched = true;
+ ref->null.first = ref->null.second = j;
+ ref->null.matched = false;
+}
+
+template <class iterator, class Allocator>
+inline void RE_CALL reg_match_base<iterator, Allocator>::init_fail(iterator i, iterator j)
+{
+ set_size(ref->cmatches, i, j);
+}
+
+template <class iterator, class Allocator>
+void RE_CALL reg_match_base<iterator, Allocator>::maybe_assign(const reg_match_base<iterator, Allocator>& m)
+{
+ sub_match<iterator>* p1, *p2;
+ p1 = (sub_match<iterator>*)(ref+1);
+ p2 = (sub_match<iterator>*)(m.ref+1);
+ unsigned int len1, len2;
+ unsigned int i;
+ for(i = 0; i < ref->cmatches; ++i)
+ {
+ len1 = len2 = 0;
+ JM_DISTANCE(p1->first, p1->second, len1);
+ JM_DISTANCE(p2->first, p2->second, len2);
+ if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
+ break;
+ if((p1->matched == true) && (p2->matched == false))
+ return;
+ ++p1;
+ ++p2;
+ }
+ if(i == ref->cmatches)
+ return;
+ if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) )
+ *this = m;
+}
+
+template <class iterator, class Allocator>
+void RE_CALL reg_match_base<iterator, Allocator>::cow()
+{
+ if(ref->count > 1)
+ {
+ reference* newref = (reference*)ref->allocate(sizeof(sub_match<iterator>) * ref->cmatches + sizeof(reference));
+#ifndef JM_NO_EXCEPTIONS
+ try{
+#endif
+ new (newref) reference(*ref);
+ newref->count = 1;
+ sub_match<iterator>* p1, *p2, *p3;
+ p1 = (sub_match<iterator>*)(newref+1);
+ p2 = p1 + newref->cmatches;
+ p3 = (sub_match<iterator>*)(ref+1);
+#ifndef JM_NO_EXCEPTIONS
+ try{
+#endif
+ while(p1 != p2)
+ {
+ new (p1) sub_match<iterator>(*p3);
+ ++p1;
+ ++p3;
+ }
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ p2 = (sub_match<iterator>*)(newref+1);
+ while(p2 != p1)
+ {
+ jm_destroy(p2);
+ ++p2;
+ }
+ jm_destroy(ref);
+ throw;
+ }
+#endif
+ --(ref->count);
+ ref = newref;
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * ref->cmatches + sizeof(reference));
+ throw;
+ }
+#endif
+ }
+}
+
+//
+// class reg_match
+// encapsulates reg_match_base, does a deep copy rather than
+// reference counting to ensure thread safety when copying
+// other reg_match instances
+
+template <class iterator, class Allocator>
+class reg_match : public reg_match_base<iterator, Allocator>
+{
+public:
+ reg_match(const Allocator& a = Allocator())
+ : reg_match_base<iterator, Allocator>(a){}
+
+ reg_match(const reg_match_base<iterator, Allocator>& m)
+ : reg_match_base<iterator, Allocator>(m){}
+
+ reg_match& operator=(const reg_match_base<iterator, Allocator>& m)
+ {
+ // shallow copy
+ reg_match_base<iterator, Allocator>::operator=(m);
+ return *this;
+ }
+
+ reg_match(const reg_match& m);
+ reg_match& operator=(const reg_match& m);
+
+};
+
+template <class iterator, class Allocator>
+reg_match<iterator, Allocator>::reg_match(const reg_match<iterator, Allocator>& m)
+ : reg_match_base<iterator, Allocator>(false)
+{
+ reg_match_base<iterator, Allocator>::ref = (typename reg_match_base<iterator, Allocator>::reference *)m.ref->allocate(sizeof(sub_match<iterator>) * m.ref->cmatches + sizeof(typename reg_match_base<iterator, Allocator>::reference));
+#ifndef JM_NO_EXCEPTIONS
+ try{
+#endif
+ new (reg_match_base<iterator, Allocator>::ref) typename reg_match_base<iterator, Allocator>::reference(*m.ref);
+ reg_match_base<iterator, Allocator>::ref->count = 1;
+ sub_match<iterator>* p1, *p2, *p3;
+ p1 = (sub_match<iterator>*)(reg_match_base<iterator, Allocator>::ref+1);
+ p2 = p1 + reg_match_base<iterator, Allocator>::ref->cmatches;
+ p3 = (sub_match<iterator>*)(m.ref+1);
+#ifndef JM_NO_EXCEPTIONS
+ try{
+#endif
+ while(p1 != p2)
+ {
+ new (p1) sub_match<iterator>(*p3);
+ ++p1;
+ ++p3;
+ }
+#ifndef JM_NO_EXCEPTIONS
+ }
+ catch(...)
+ {
+ p2 = (sub_match<iterator>*)(reg_match_base<iterator, Allocator>::ref+1);
+ while(p2 != p1)
+ {
+ jm_destroy(p2);
+ ++p2;
+ }
+ jm_destroy(ref);
+ throw;
+ }
+ }
+ catch(...)
+ {
+ m.ref->deallocate((char*)(void*)reg_match_base<iterator, Allocator>::ref, sizeof(sub_match<iterator>) * m.ref->cmatches + sizeof(typename reg_match_base<iterator, Allocator>::reference));
+ throw;
+ }
+#endif
+}
+
+template <class iterator, class Allocator>
+reg_match<iterator, Allocator>& reg_match<iterator, Allocator>::operator=(const reg_match<iterator, Allocator>& m)
+{
+ reg_match<iterator, Allocator> t(m);
+ this->swap(t);
+ return *this;
+}
+
+
+template <class iterator, class charT, class traits_type, class Allocator>
+iterator RE_CALL re_is_set_member(iterator next,
+ iterator last,
+ re_set_long* set,
+ const reg_expression<charT, traits_type, Allocator>& e);
+
+JM_END_NAMESPACE // namespace regex
+
+#include <jm/regcomp.h>
+
+JM_NAMESPACE(__JM)
+
+typedef reg_expression<char, char_regex_traits<char>, JM_DEF_ALLOC(char)> regex;
+#ifndef JM_NO_WCSTRING
+typedef reg_expression<wchar_t, char_regex_traits<wchar_t>, JM_DEF_ALLOC(wchar_t)> wregex;
+#endif
+
+typedef reg_match<const char*, regex::alloc_type> cmatch;
+#ifndef JM_NO_WCSTRING
+typedef reg_match<const wchar_t*, wregex::alloc_type> wcmatch;
+#endif
+
+JM_END_NAMESPACE // namespace regex
+
+#include <jm/regmatch.h>
+#include <jm/regfmt.h>
+
+#if !defined(JM_NO_NAMESPACES) && !defined(JM_NO_USING)
+
+#ifndef JM_NO_EXCEPTIONS
+using __JM::bad_expression;
+#endif
+using __JM::char_regex_traits;
+using __JM::char_regex_traits_i;
+using __JM::regbase;
+using __JM::reg_expression;
+using __JM::reg_match;
+using __JM::reg_match_base;
+using __JM::sub_match;
+using __JM::regex;
+using __JM::cmatch;
+#ifndef JM_NO_WCSTRING
+using __JM::wregex;
+using __JM::wcmatch;
+#endif
+using __JM::query_match;
+using __JM::reg_search;
+using __JM::reg_grep;
+using __JM::reg_format;
+using __JM::reg_merge;
+using __JM::jm_def_alloc;
+
+#endif
+
+#endif // __cplusplus
+
+#endif // include
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+