diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/tfstats/regexp/include/jm | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/tfstats/regexp/include/jm')
20 files changed, 10114 insertions, 0 deletions
diff --git a/utils/tfstats/regexp/include/jm/cregex.h b/utils/tfstats/regexp/include/jm/cregex.h new file mode 100644 index 0000000..f628522 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/cregex.h @@ -0,0 +1,309 @@ +//========= 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 cregex.h + * VERSION 2.12 + */ + +#ifndef CREGEX_H +#define CREGEX_H + +#include <jm/jm_cfg.h> + +/* include these defs only for POSIX compatablity */ + +typedef int regoff_t; + +typedef struct +{ + unsigned int re_magic; + unsigned int re_nsub; /* number of parenthesized subexpressions */ + const char* re_endp; /* end pointer for REG_PEND */ + void* guts; /* none of your business :-) */ + unsigned int eflags; /* none of your business :-) */ +} regex_tA; + +#ifndef JM_NO_WCSTRING +typedef struct +{ + unsigned int re_magic; + unsigned int re_nsub; /* number of parenthesized subexpressions */ + const wchar_t* re_endp; /* end pointer for REG_PEND */ + void* guts; /* none of your business :-) */ + unsigned int eflags; /* none of your business :-) */ +} regex_tW; +#endif + +typedef struct +{ + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +} regmatch_t; + +/* regcomp() flags */ +#define REG_BASIC 0000 +#define REG_EXTENDED 0001 +#define REG_ICASE 0002 +#define REG_NOSUB 0004 +#define REG_NEWLINE 0010 +#define REG_NOSPEC 0020 +#define REG_PEND 0040 +#define REG_DUMP 0200 +#define REG_NOCOLLATE 0400 + +#define REG_ASSERT 15 +#define REG_INVARG 16 +#define REG_ATOI 255 /* convert name to number (!) */ +#define REG_ITOA 0400 /* convert number to name (!) */ + +/* regexec() flags */ +#define REG_NOTBOL 00001 +#define REG_NOTEOL 00002 +#define REG_STARTEND 00004 + +#ifdef __cplusplus +extern "C" { +#endif + +JM_IX_DECL int RE_CCALL regcompA(regex_tA*, const char*, int); +JM_IX_DECL unsigned int RE_CCALL regerrorA(int, const regex_tA*, char*, unsigned int); +JM_IX_DECL int RE_CCALL regexecA(const regex_tA*, const char*, unsigned int, regmatch_t*, int); +JM_IX_DECL void RE_CCALL regfreeA(regex_tA*); + +#ifndef JM_NO_WCSTRING +JM_IX_DECL int RE_CCALL regcompW(regex_tW*, const wchar_t*, int); +JM_IX_DECL unsigned int RE_CCALL regerrorW(int, const regex_tW*, wchar_t*, unsigned int); +JM_IX_DECL int RE_CCALL regexecW(const regex_tW*, const wchar_t*, unsigned int, regmatch_t*, int); +JM_IX_DECL void RE_CCALL regfreeW(regex_tW*); +#endif + +#ifdef UNICODE +#define regcomp regcompW +#define regerror regerrorW +#define regexec regexecW +#define regfree regfreeW +#define regex_t regex_tW +#else +#define regcomp regcompA +#define regerror regerrorA +#define regexec regexecA +#define regfree regfreeA +#define regex_t regex_tA +#endif + + +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus +JM_NAMESPACE(__JM) +#endif + +/* regerror() flags */ +typedef enum +{ + REG_NOERROR = 0, /* Success. */ + REG_NOMATCH = 1, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + REG_BADPAT = 2, /* Invalid pattern. */ + REG_ECOLLATE = 3, /* Undefined collating element. */ + REG_ECTYPE = 4, /* Invalid character class name. */ + REG_EESCAPE = 5, /* Trailing backslash. */ + REG_ESUBREG = 6, /* Invalid back reference. */ + REG_EBRACK = 7, /* Unmatched left bracket. */ + REG_EPAREN = 8, /* Parenthesis imbalance. */ + REG_EBRACE = 9, /* Unmatched \{. */ + REG_BADBR = 10, /* Invalid contents of \{\}. */ + REG_ERANGE = 11, /* Invalid range end. */ + REG_ESPACE = 12, /* Ran out of memory. */ + REG_BADRPT = 13, /* No preceding re for repetition op. */ + REG_EEND = 14, /* unexpected end of expression */ + REG_ESIZE = 15, /* expression too big */ + REG_ERPAREN = 16, /* unmatched right parenthesis */ + REG_EMPTY = 17, /* empty expression */ + REG_E_MEMORY = 18, /* out of memory */ + REG_E_UNKNOWN = 19 /* unknown error */ +} reg_errcode_t; + +enum match_flags +{ + match_default = 0, + match_not_bol = 1, // first is not start of line + match_not_eol = match_not_bol << 1, // last is not end of line + match_not_bob = match_not_eol << 1, // first is not start of buffer + match_not_eob = match_not_bob << 1, // last is not end of buffer + match_not_bow = match_not_eob << 1, // first is not start of word + match_not_eow = match_not_bow << 1, // last is not end of word + match_not_dot_newline = match_not_eow << 1, // \n is not matched by '.' + match_not_dot_null = match_not_dot_newline << 1, // '\0' is not matched by '.' + match_prev_avail = match_not_dot_null << 1, // *--first is a valid expression + match_init = match_prev_avail << 1, // internal use + match_any = match_init << 1, // don't care what we match + match_not_null = match_any << 1, // string can't be null + match_continuous = match_not_null << 1, // each grep match must continue from + // uninterupted from the previous one + match_stop = match_continuous << 1 // stop after first match (grep) +}; + + + +#ifdef __cplusplus +JM_END_NAMESPACE +#endif + +// +// C++ high level wrapper goes here: +// +#if defined(__cplusplus) && !defined(JM_NO_STRING_H) +#include <string> +#include <vector> +JM_NAMESPACE(__JM) + +class RegExData; +class RegEx; +struct pred1; +struct pred2; +struct pred3; +struct pred4; + +typedef bool (*GrepCallback)(const RegEx& expression); +typedef bool (*GrepFileCallback)(const char* file, const RegEx& expression); +typedef bool (*FindFilesCallback)(const char* file); + +class JM_IX_DECL RegEx +{ +private: + RegExData* pdata; +public: + RegEx(); + RegEx(const RegEx& o); + ~RegEx(); + RegEx(const char* c, bool icase = false); + RegEx(const __JM_STD::string& s, bool icase = false); + RegEx& operator=(const RegEx& o); + RegEx& operator=(const char* p); + RegEx& operator=(const __JM_STD::string& s){ return this->operator=(s.c_str()); } + unsigned int SetExpression(const char* p, bool icase = false); + unsigned int SetExpression(const __JM_STD::string& s, bool icase = false){ return SetExpression(s.c_str(), icase); } + __JM_STD::string Expression()const; + // + // now matching operators: + // + bool Match(const char* p, unsigned int flags = match_default); + bool Match(const __JM_STD::string& s, unsigned int flags = match_default) { return Match(s.c_str(), flags); } + bool Search(const char* p, unsigned int flags = match_default); + bool Search(const __JM_STD::string& s, unsigned int flags = match_default) { return Search(s.c_str(), flags); } + unsigned int Grep(GrepCallback cb, const char* p, unsigned int flags = match_default); + unsigned int Grep(GrepCallback cb, const __JM_STD::string& s, unsigned int flags = match_default) { return Grep(cb, s.c_str(), flags); } + unsigned int Grep(__JM_STD::vector<__JM_STD::string>& v, const char* p, unsigned int flags = match_default); + unsigned int Grep(__JM_STD::vector<__JM_STD::string>& v, const __JM_STD::string& s, unsigned int flags = match_default) { return Grep(v, s.c_str(), flags); } + unsigned int Grep(__JM_STD::vector<unsigned int>& v, const char* p, unsigned int flags = match_default); + unsigned int Grep(__JM_STD::vector<unsigned int>& v, const __JM_STD::string& s, unsigned int flags = match_default) { return Grep(v, s.c_str(), flags); } + unsigned int GrepFiles(GrepFileCallback cb, const char* files, bool recurse = false, unsigned int flags = match_default); + unsigned int GrepFiles(GrepFileCallback cb, const __JM_STD::string& files, bool recurse = false, unsigned int flags = match_default) { return GrepFiles(cb, files.c_str(), recurse, flags); } + unsigned int FindFiles(FindFilesCallback cb, const char* files, bool recurse = false, unsigned int flags = match_default); + unsigned int FindFiles(FindFilesCallback cb, const __JM_STD::string& files, bool recurse = false, unsigned int flags = match_default) { return FindFiles(cb, files.c_str(), recurse, flags); } + // + // now operators for returning what matched in more detail: + // + unsigned int Position(int i = 0)const; + unsigned int Length(int i = 0)const; + unsigned int Line()const; + unsigned int Marks()const; + __JM_STD::string What(int i = 0)const; + __JM_STD::string operator[](int i)const { return What(i); } + + friend struct pred1; + friend struct pred2; + friend struct pred3; + friend struct pred4; +}; + + +JM_END_NAMESPACE + +#if !defined(JM_NO_NAMESPACES) && !defined(JM_NO_USING) && defined(__cplusplus) + +using __JM::RegEx; +using __JM::GrepCallback; +using __JM::GrepFileCallback; +using __JM::FindFilesCallback; + +#endif + +#endif // __cplusplus + +#if !defined(JM_NO_NAMESPACES) && !defined(JM_NO_USING) && defined(__cplusplus) + +using __JM::match_flags; +using __JM::reg_errcode_t; + +using __JM::REG_NOERROR; +using __JM::REG_NOMATCH; +using __JM::REG_BADPAT; +using __JM::REG_ECOLLATE; +using __JM::REG_ECTYPE; +using __JM::REG_EESCAPE; +using __JM::REG_ESUBREG; +using __JM::REG_EBRACK; +using __JM::REG_EPAREN; +using __JM::REG_EBRACE; +using __JM::REG_BADBR; +using __JM::REG_ERANGE; +using __JM::REG_ESPACE; +using __JM::REG_BADRPT; +using __JM::REG_EEND; +using __JM::REG_ESIZE; +using __JM::REG_ERPAREN; +using __JM::REG_EMPTY; +using __JM::REG_E_MEMORY; +using __JM::REG_E_UNKNOWN; +using __JM::match_default; +using __JM::match_not_bol; +using __JM::match_not_eol; +using __JM::match_not_bob; +using __JM::match_not_eob; +using __JM::match_not_bow; +using __JM::match_not_eow; +using __JM::match_not_dot_newline; +using __JM::match_not_dot_null; +using __JM::match_prev_avail; +using __JM::match_init; +using __JM::match_any; +using __JM::match_not_null; +using __JM::match_continuous; +using __JM::match_stop; + +#endif + + +#endif + + + + + diff --git a/utils/tfstats/regexp/include/jm/fileiter.h b/utils/tfstats/regexp/include/jm/fileiter.h new file mode 100644 index 0000000..b886a1d --- /dev/null +++ b/utils/tfstats/regexp/include/jm/fileiter.h @@ -0,0 +1,368 @@ +//========= 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 fileiter.h + * VERSION 2.12 + * + * this file declares various platform independent file and directory + * iterators, plus binary file input in the form of class map_file. + * + */ + + +#ifndef __FILEITER_H +#define __FILEITER_H + +#include <jm/jm_cfg.h> + +#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32)) && !defined(JM_NO_WIN32) + +#define FI_W32 +#include <windows.h> + +JM_NAMESPACE(__JM) + +typedef WIN32_FIND_DATA _fi_find_data; +typedef HANDLE _fi_find_handle; + +JM_END_NAMESPACE + +#define _fi_invalid_handle INVALID_HANDLE_VALUE +#define _fi_dir FILE_ATTRIBUTE_DIRECTORY + +#else + +#include <stdio.h> +#include <ctype.h> +#ifndef JM_NO_STL +#include <iterator> +#include <list> +#if defined(__SUNPRO_CC) && !defined(JM_NO_NAMESPACES) +using __JM_STD::list; +#endif +#endif +#include <assert.h> +#include <dirent.h> + +#ifndef MAX_PATH +#define MAX_PATH 256 +#endif + +JM_NAMESPACE(__JM) + +struct _fi_find_data +{ + unsigned dwFileAttributes; + char cFileName[MAX_PATH]; +}; + +struct _fi_priv_data; + +typedef _fi_priv_data* _fi_find_handle; +#define _fi_invalid_handle NULL +#define _fi_dir 1 + +_fi_find_handle _fi_FindFirstFile(const char* lpFileName, _fi_find_data* lpFindFileData); +bool _fi_FindNextFile(_fi_find_handle hFindFile, _fi_find_data* lpFindFileData); +bool _fi_FindClose(_fi_find_handle hFindFile); + +JM_END_NAMESPACE + +#ifdef FindFirstFile + #undef FindFirstFile +#endif +#ifdef FindNextFile + #undef FindNextFile +#endif +#ifdef FindClose + #undef FindClose +#endif + +#define FindFirstFile _fi_FindFirstFile +#define FindNextFile _fi_FindNextFile +#define FindClose _fi_FindClose + +#endif + +JM_NAMESPACE(__JM) + +#ifdef FI_W32 // win32 mapfile + +class JM_IX_DECL mapfile +{ + HANDLE hfile; + HANDLE hmap; + const char* _first; + const char* _last; +public: + + typedef const char* iterator; + + mapfile(){ hfile = hmap = 0; _first = _last = 0; } + mapfile(const char* file){ hfile = hmap = 0; _first = _last = 0; open(file); } + ~mapfile(){ close(); } + void open(const char* file); + void close(); + const char* begin(){ return _first; } + const char* end(){ return _last; } + size_t size(){ return _last - _first; } + bool valid(){ return (hfile != 0) && (hfile != INVALID_HANDLE_VALUE); } +}; + + +#elif !defined(JM_NO_STL) // use POSIX API to emulate the memory map: + +class JM_IX_DECL mapfile_iterator; + +class JM_IX_DECL mapfile +{ + typedef char* pointer; + FILE* hfile; + long int _size; + pointer* _first; + pointer* _last; + mutable __JM_STD::list<pointer*> condemed; + enum sizes + { + buf_size = 4096 + }; + void lock(pointer* node)const; + void unlock(pointer* node)const; +public: + + typedef mapfile_iterator iterator; + + mapfile(){ hfile = 0; _size = 0; _first = _last = 0; } + mapfile(const char* file){ hfile = 0; _size = 0; _first = _last = 0; open(file); } + ~mapfile(){ close(); } + void open(const char* file); + void close(); + iterator begin()const; + iterator end()const; + unsigned long size()const{ return _size; } + bool valid()const{ return hfile != 0; } + friend class mapfile_iterator; +}; + +class JM_IX_DECL mapfile_iterator : public JM_RA_ITERATOR(char, long) +{ + typedef mapfile::pointer pointer; + pointer* node; + const mapfile* file; + unsigned long offset; + long position()const + { + return file ? ((node - file->_first) * mapfile::buf_size + offset) : 0; + } + void position(long pos) + { + if(file) + { + node = file->_first + (pos / mapfile::buf_size); + offset = pos % mapfile::buf_size; + } + } +public: + mapfile_iterator() { node = 0; file = 0; offset = 0; } + mapfile_iterator(const mapfile* f, long position) + { + file = f; + node = f->_first + position / mapfile::buf_size; + offset = position % mapfile::buf_size; + if(file) + file->lock(node); + } + mapfile_iterator(const mapfile_iterator& i) + { + file = i.file; + node = i.node; + offset = i.offset; + if(file) + file->lock(node); + } + ~mapfile_iterator() + { + if(file && node) + file->unlock(node); + } + mapfile_iterator& operator = (const mapfile_iterator& i); + char operator* ()const + { + assert(node >= file->_first); + assert(node < file->_last); + return file ? *(*node + sizeof(int) + offset) : char(0); + } + mapfile_iterator& operator++ (); + mapfile_iterator operator++ (int); + mapfile_iterator& operator-- (); + mapfile_iterator operator-- (int); + + mapfile_iterator& operator += (long off) + { + position(position() + off); + return *this; + } + mapfile_iterator& operator -= (long off) + { + position(position() - off); + return *this; + } + + friend inline bool operator==(const mapfile_iterator& i, const mapfile_iterator& j) + { + return (i.file == j.file) && (i.node == j.node) && (i.offset == j.offset); + } +#ifndef JM_NO_NOT_EQUAL + friend inline bool operator!=(const mapfile_iterator& i, const mapfile_iterator& j) + { + return !(i == j); + } +#endif + friend inline bool operator<(const mapfile_iterator& i, const mapfile_iterator& j) + { + return i.position() < j.position(); + } + + friend mapfile_iterator operator + (const mapfile_iterator& i, long off); + friend mapfile_iterator operator - (const mapfile_iterator& i, long off); + friend inline long operator - (const mapfile_iterator& i, const mapfile_iterator& j) + { + return i.position() - j.position(); + } +}; + +#endif + +// _fi_sep determines the directory separator, either '\\' or '/' +JM_IX_DECL extern const char* _fi_sep; + +struct file_iterator_ref +{ + _fi_find_handle hf; + _fi_find_data _data; + long count; +}; + + +class JM_IX_DECL file_iterator : public JM_INPUT_ITERATOR(const char*, __JM_STDC::ptrdiff_t) +{ + char* _root; + char* _path; + char* ptr; + file_iterator_ref* ref; + +public: + file_iterator(); + file_iterator(const char* wild); + ~file_iterator(); + file_iterator(const file_iterator&); + file_iterator& operator=(const file_iterator&); + const char* root() { return _root; } + const char* path() { return _path; } + _fi_find_data* data() { return &(ref->_data); } + void next(); + file_iterator& operator++() { next(); return *this; } + file_iterator operator++(int); + const char* operator*() { return path(); } + + friend inline bool operator == (const file_iterator& f1, const file_iterator& f2) + { + return ((f1.ref->hf == _fi_invalid_handle) && (f1.ref->hf == _fi_invalid_handle)); + } +#ifndef JM_NO_NOT_EQUAL + friend inline bool operator != (const file_iterator& f1, const file_iterator& f2) + { + return !(f1 == f2); + } +#endif +}; + +inline bool operator < (const file_iterator& f1, const file_iterator& f2) +{ + return false; +} + + +class JM_IX_DECL directory_iterator : public JM_INPUT_ITERATOR(const char*, __JM_STDC::ptrdiff_t) +{ + char* _root; + char* _path; + char* ptr; + file_iterator_ref* ref; + +public: + directory_iterator(); + directory_iterator(const char* wild); + ~directory_iterator(); + directory_iterator(const directory_iterator& other); + directory_iterator& operator=(const directory_iterator& other); + + const char* root() { return _root; } + const char* path() { return _path; } + _fi_find_data* data() { return &(ref->_data); } + void next(); + directory_iterator& operator++() { next(); return *this; } + directory_iterator operator++(int); + const char* operator*() { return path(); } + + static const char* separator() { return _fi_sep; } + + friend inline bool operator == (const directory_iterator& f1, const directory_iterator& f2) + { + return ((f1.ref->hf == _fi_invalid_handle) && (f1.ref->hf == _fi_invalid_handle)); + } + +#ifndef JM_NO_NOT_EQUAL + friend inline bool operator != (const directory_iterator& f1, const directory_iterator& f2) + { + return !(f1 == f2); + } +#endif +}; + +inline bool operator < (const directory_iterator& f1, const directory_iterator& f2) +{ + return false; +} + +JM_END_NAMESPACE + +#if !defined(JM_NO_NAMESPACES) && !defined(JM_NO_USING) + +using __JM::directory_iterator; +using __JM::file_iterator; +using __JM::mapfile; + +#endif + + +#endif // __WINITER_H + + + + + + + + diff --git a/utils/tfstats/regexp/include/jm/jm_cfg.h b/utils/tfstats/regexp/include/jm/jm_cfg.h new file mode 100644 index 0000000..49f150c --- /dev/null +++ b/utils/tfstats/regexp/include/jm/jm_cfg.h @@ -0,0 +1,1057 @@ +//========= 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 jm_cfg.h + * VERSION 2.12 + */ + +#ifndef JM_CFG_H +#define JM_CFG_H + +/************************************************************************ + +The purpose of this header is to provide compiler and STL configuration +options. Options fall into three categaries (namespaces, compiler and STL), +throughout, the defaults assume that the compiler and STL are fully C++ standard +compliant, features that are not supported on your system may be selectively +turned off by defining the appropriate macros. Borland C++, Borland C++ Builder, +and Microsoft Visual C++ should be auto-recognised and configured. The HP aCC and +SunPro C++ compiler should also be supported - but run configure for best results. +The SGI, HP, Microsoft and Rogue Wave STL's should be auto-recognised and configured. +Do not change this file unless you really really have to, add options to +<jm_opt.h> instead. See <jm_opt.h> for a full list of macros and their usage. + +************************************************************************/ + +#include <jm/jm_opt.h> +#include <stdlib.h> +#include <stddef.h> + +/* this will increase in future versions: */ +#define JM_VERSION 212 + +#ifndef JM_AUTO_CONFIGURE +#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) + #define JM_PLATFORM_W32 +#endif + +#ifdef __BORLANDC__ + + #if __BORLANDC__ < 0x500 + #define JM_NO_NAMESPACES + #define JM_NO_BOOL + #define JM_NO_MUTABLE + #endif + + #if __BORLANDC__ < 0x520 + #define JM_NO_WCSTRING + #define JM_NO_INT64 + // Early versions of Borlands namespace code can't cope with iterators + // that are in different namespaces from STL code. + #define __JM std + #define JM_NO_NOT_EQUAL + #endif + + #if __BORLANDC__ < 0x530 + #define JM_NO_WCTYPE_H + #define JM_NO_WCHAR_H + #define JM_OLD_IOSTREAM + #define __JM_STDC + #define JM_NO_TRICKY_DEFAULT_PARAM + #define JM_NO_EXCEPTION_H + #ifndef __WIN32__ + #define JM_NO_WCSTRING + #endif + #define JM_NO_LOCALE_H + #define JM_NO_TEMPLATE_RETURNS + #define JM_TEMPLATE_SPECIALISE + #endif + + #if __BORLANDC__ < 0x540 + #define JM_NO_MEMBER_TEMPLATES + // inline contructors exhibit strange behaviour + // under Builder 3 and C++ 5.x when throwing exceptions + #define INLINE_EXCEPTION_BUG + #define JM_NESTED_TEMPLATE_DECL + #define JM_NO_PARTIAL_FUNC_SPEC + #define JM_NO_STRING_DEF_ARGS + #define JM_NO_TYPEINFO // bad_cast etc not in namespace std. + #endif + // + // Builder 4 seems to have broken template friend support: + #define JM_NO_TEMPLATE_FRIEND + + #ifndef _CPPUNWIND + #define JM_NO_EXCEPTIONS + #endif + + #ifdef _Windows + #define JM_PLATFORM_WINDOWS + #else + #define JM_PLATFORM_DOS + #endif + + #ifndef __WIN32__ + #define RE_CALL + #define RE_CCALL + #else + #define RE_CALL __fastcall + #define RE_CCALL __stdcall + #endif + + #define JM_INT64t __int64 + #define JM_IMM64(val) val##i64 + #define JM_NO_CAT + + #ifdef __MT__ + #define JM_THREADS + #endif + + // + // import export options: + #ifdef _RTLDLL + #ifdef RE_BUILD_DLL + #define JM_IX_DECL __declspec( dllexport ) + #else + #define JM_IX_DECL __declspec( dllimport ) + #endif + #endif + #include <jm/re_lib.h> +#endif + +#ifdef _MSC_VER + #define RE_CALL __fastcall + #define RE_CCALL __stdcall + + #if _MSC_VER < 1100 + #define JM_NO_NAMESPACES + #define JM_NO_DEFAULT_PARAM + #define JM_NO_BOOL + #define JM_NO_MUTABLE + #define JM_NO_WCSTRING + #define JM_NO_LOCALE_H + #define JM_NO_TEMPLATE_RETURNS + #define JM_NO_INT64 + #endif + + #if _MSC_VER < 1200 + #define JM_TEMPLATE_SPECIALISE + #define JM_NESTED_TEMPLATE_DECL + #endif + + #ifndef _CPPUNWIND + #define JM_NO_EXCEPTIONS + #endif + + #define __JM_STDC + #define JM_PLATFORM_WINDOWS + // + // no support for nested template classes yet.... + // although this part of VC6 is badly documented + #define JM_NO_MEMBER_TEMPLATES + #define JM_INT64t __int64 + #define JM_IMM64(val) val##i64 + #define JM_NO_CAT + #define JM_NO_PARTIAL_FUNC_SPEC + #define JM_NO_TEMPLATE_FRIEND + + #ifdef _MT + #define JM_THREADS + #endif + +#pragma warning(disable: 4786) +#pragma warning(disable: 4800) +#pragma warning(disable: 4200) + + // + // import export options: + #ifdef _DLL + #ifdef RE_BUILD_DLL + #define JM_IX_DECL __declspec( dllexport ) + #else + #define JM_IX_DECL __declspec( dllimport ) + #endif + #endif + #include <jm/re_lib.h> +#endif + +#ifdef __GNUC__ + #if (__GNUC__ < 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ < 91)) + #define JM_NO_NAMESPACES + #define JM_NO_MUTABLE + #define JM_NO_MEMBER_TEMPLATES + #define JM_NO_PARTIAL_FUNC_SPEC + #define JM_NO_TEMPLATE_FRIEND + #endif + #ifndef __STL_USE_NAMESPACES + #define JM_NO_EXCEPTION_H + #endif + #define JM_INT64t long long + #define JM_IMM64(val) val##LL + + #ifdef _WIN32 + #define JM_PLATFORM_WINDOWS + #define JM_NO_WCTYPE_H + //#define JM_NO_TEMPLATE_SWITCH_MERGE + #endif + #define JM_NO_CAT + #define OLD_IOSTREAM + #define JM_NESTED_TEMPLATE_DECL + #define JM_NO_TEMPLATE_TYPENAME + +#endif + +#ifdef __SUNPRO_CC + #if (__SUNPRO_CC < 0x500) + #define JM_NO_NAMESPACES + #define JM_NO_MUTABLE + #define JM_NO_MEMBER_TEMPLATES + #define OLD_IOSTREAM + #endif + #ifndef __STL_USE_NAMESPACES + #define JM_NO_EXCEPTION_H + #endif + #define JM_INT64t long long + #define JM_IMM64(val) val##LL + #define JM_NESTED_TEMPLATE_DECL + #define JM_NO_TEMPLATE_TYPENAME + #define JM_NO_SWPRINTF + #define JM_NO_TEMPLATE_FRIEND +#endif + +#ifdef __HP_aCC + // putative HP aCC support, run configure for + // support tailored to your system.... + #define JM_NO_NAMESPACES + #define JM_NO_MUTABLE + #define JM_NO_MEMBER_TEMPLATES + #define OLD_IOSTREAM + #ifndef __STL_USE_NAMESPACES + #define JM_NO_EXCEPTION_H + #endif + #define JM_INT64t long long + #define JM_IMM64(val) val##LL + #define JM_NESTED_TEMPLATE_DECL + #define JM_NO_TEMPLATE_TYPENAME + #define JM_NO_TEMPLATE_FRIEND +#endif + + + +#endif // JM_AUTO_CONFIGURE + +#ifndef JM_NO_WCSTRING +#ifndef JM_NO_WCTYPE_H +#include <wctype.h> +#endif +#ifndef JM_NO_WCHAR_H +#include <wchar.h> +#endif +#endif + +#ifdef JM_NO_NAMESPACES +#define JM_MAYBE_ACCESS_SPEC :: +#else +#define JM_MAYBE_ACCESS_SPEC __JM:: +#endif + +#if !defined(JM_INT64t) || !defined(JM_IMM64) +#define JM_NO_INT64 +#endif + +#ifndef JM_INT32 +typedef unsigned int jm_uintfast32_t; +#else +typedef JM_INT32 jm_uintfast32_t; +#endif + +#ifndef JM_TEMPLATE_SPECIALISE +#define JM_TEMPLATE_SPECIALISE template <> +#endif + +#ifndef JM_NESTED_TEMPLATE_DECL +#define JM_NESTED_TEMPLATE_DECL template +#endif + +#ifndef JM_IX_DECL +#define JM_IX_DECL +#endif + +#ifndef MB_CUR_MAX +// yuk! +// better make a conservative guess! +#define MB_CUR_MAX 10 +#endif + + +/* everything else is C++: */ + +#ifdef __cplusplus + +/* define macro's to make default parameter declaration easier: */ + +#ifdef JM_NO_DEFAULT_PARAM + #define JM_DEFAULT_PARAM(x) + #define JM_TRICKY_DEFAULT_PARAM(x) +#elif defined(JM_NO_TRICKY_DEFAULT_PARAM) + #define JM_DEFAULT_PARAM(x) = x + #define JM_TRICKY_DEFAULT_PARAM(x) +#else + #define JM_DEFAULT_PARAM(x) = x + #define JM_TRICKY_DEFAULT_PARAM(x) = x +#endif + +/* STL configuration goes here: */ + +#ifndef JM_AUTO_CONFIGURE +#ifdef JM_NO_STL + #define JM_NO_EXCEPTION_H + #define JM_NO_ITERATOR_H + #define JM_NO_MEMORY_H + #define JM_NO_LOCALE_H + #define JM_NO_STRING_H +#endif + +#ifndef JM_NO_EXCEPTION_H + #include <exception> +#endif + +#ifndef JM_NO_ITERATOR_H + #include <iterator> + + #if defined(__SGI_STL_INTERNAL_ITERATOR_H) || defined(__SGI_STL_ITERATOR_H) + #define JM_NO_LOCALE_H + #define OLD_IOSTREAM + + /* we are using SGI's STL + some of these (__JM_STDC) + may be guesswork: */ + #if !defined(__STL_MEMBER_TEMPLATE_CLASSES) || !defined(__STL_MEMBER_TEMPLATES) + #define JM_NO_MEMBER_TEMPLATES + #endif + + #if !defined( __JM_STD) + #if defined (__STL_USE_NAMESPACES) + #define __JM_STD __STD + #else + #define __JM_STD + #endif + #endif + #ifndef __JM_STDC + #define __JM_STDC + #endif + #ifdef __STL_NO_BOOL + #define JM_NO_BOOL + #endif + #ifdef __STL_LIMITED_DEFAULT_TEMPLATES + #define JM_NO_TRICKY_DEFAULT_PARAM + #define JM_NO_STRING_DEF_ARGS + #endif + #ifndef __STL_USE_EXCEPTIONS + #define JM_NO_EXCEPTIONS + #endif + + #include <algo.h> + #include <alloc.h> + + #define JM_ALGO_INCLUDED + + #define JM_DISTANCE(i, j, n) __JM_STD::distance(i, j, n) + #define JM_OUTPUT_ITERATOR(T, D) __JM_STD::output_iterator + #define JM_INPUT_ITERATOR(T, D) __JM_STD::input_iterator<T, D> + #define JM_FWD_ITERATOR(T, D) __JM_STD::forward_iterator<T, D> + #define JM_BIDI_ITERATOR(T, D) __JM_STD::bidirectional_iterator<T, D> + #define JM_RA_ITERATOR(T, D) __JM_STD::random_access_iterator<T, D> + + #ifdef __STL_USE_STD_ALLOCATORS + + /* new style allocator's with nested template classes */ + + #define REBIND_INSTANCE(x, y, inst) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other(inst) + #define REBIND_TYPE(x, y) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other + #define JM_DEF_ALLOC_PARAM(x) JM_TRICKY_DEFAULT_PARAM( __JM_STD::allocator<x> ) + #define JM_DEF_ALLOC(x) __JM_STD::allocator<x> + + #else /* __STL_USE_STD_ALLOCATORS */ + + /* old style byte allocator's, no nested templates */ + #define JM_OLD_ALLOCATORS + #define REBIND_INSTANCE(x, y, inst) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y>(inst) + #define REBIND_TYPE(x, y) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y> + #define JM_DEF_ALLOC_PARAM(x) JM_DEFAULT_PARAM( __JM_STD::alloc ) + #define JM_DEF_ALLOC(x) __JM_STD::alloc + #define JM_NEED_BINDER + + #endif /* __STL_USE_STD_ALLOCATORS */ + + #define JM_STL_DONE + #define JM_NO_NOT_EQUAL + + #elif defined(__STD_ITERATOR__) + + /* Rogue Wave STL */ + + #if defined(RWSTD_NO_MEMBER_TEMPLATES) || defined(RWSTD_NO_MEM_CLASS_TEMPLATES) + #define JM_NO_MEMBER_TEMPLATES + #endif + #ifdef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE + #define JM_NO_TEMPLATE_RETURNS + #endif + + #ifdef _RWSTD_NO_NAMESPACE + #define __JM_STD + #define __JM_STDC + #else + #define __JM_STD std + #endif + + #ifdef RWSTD_NO_EXCEPTIONS + #define JM_NO_EXCEPTIONS + #endif + + #ifdef RWSTD_NO_MUTABLE + #define JM_NO_MUTABLE + #endif + + #ifdef RWSTD_NO_DEFAULT_TEMPLATES + #define JM_NO_DEFAULT_PARAM + #define JM_NO_TRICKY_DEFAULT_PARAM + #define JM_NO_STRING_DEF_ARGS + #endif + + #ifdef _RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES + #define JM_NO_TRICKY_DEFAULT_PARAM + #define JM_NO_STRING_DEF_ARGS + #endif + + #ifdef RWSTD_NO_BOOL + #define JM_NO_BOOL + #endif + + #if _RWSTD_VER > 0x020000 + #ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC + #define JM_DISTANCE(i, j, n) __JM_STD::distance(i, j, n) + #else + #define JM_DISTANCE(i, j, n) (n = __JM_STD::distance(i, j)) + #endif + #define JM_OUTPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D, T*, T&> + #define JM_INPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D, T*, T&> + #define JM_FWD_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D, T*, T&> + #define JM_BIDI_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D, T*, T&> + #define JM_RA_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D, T*, T&> + #else + #define JM_DISTANCE(i, j, n) __JM_STD::distance(i, j, n) + #define JM_OUTPUT_ITERATOR(T, D) __JM_STD::output_iterator + #if _RWSTD_VER >= 0x0200 + #define JM_INPUT_ITERATOR(T, D) __JM_STD::input_iterator<T> + #else + #define JM_INPUT_ITERATOR(T, D) __JM_STD::input_iterator<T, D> + #endif + #define JM_FWD_ITERATOR(T, D) __JM_STD::forward_iterator<T, D> + #define JM_BIDI_ITERATOR(T, D) __JM_STD::bidirectional_iterator<T, D> + #define JM_RA_ITERATOR(T, D) __JM_STD::random_access_iterator<T, D> + #endif + + #include <memory> + + #ifdef _RWSTD_ALLOCATOR + + /* new style allocator */ + + #define REBIND_INSTANCE(x, y, inst) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other(inst) + #define REBIND_TYPE(x, y) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other + #define JM_DEF_ALLOC_PARAM(x) JM_TRICKY_DEFAULT_PARAM( __JM_STD::allocator<x> ) + #define JM_DEF_ALLOC(x) __JM_STD::allocator<x> + + #else + /* + // old style allocator + // this varies a great deal between versions, and there is no way + // that I can tell of differentiating between them, so use our + // own default allocator... + */ + #define JM_OLD_ALLOCATORS + #define REBIND_INSTANCE(x, y, inst) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y>(inst) + #define REBIND_TYPE(x, y) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y> + #define JM_DEF_ALLOC_PARAM(x) JM_DEFAULT_PARAM( jm_def_alloc ) + #define JM_DEF_ALLOC(x) jm_def_alloc + + #define JM_NEED_BINDER + #define JM_NEED_ALLOC + + #endif + + #define JM_STL_DONE + #define JM_NO_OI_ASSIGN + + #elif defined (ITERATOR_H) + + /* HP STL */ + + #define __JM_STD + #define __JM_STDC + #define JM_NO_LOCALE_H + + #include <algo.h> + #define JM_ALGO_INCLUDED + + #define JM_DISTANCE(i, j, n) __JM_STD::distance(i, j, n) + #define JM_OUTPUT_ITERATOR(T, D) __JM_STD::output_iterator + #define JM_INPUT_ITERATOR(T, D) __JM_STD::input_iterator<T, D> + #define JM_FWD_ITERATOR(T, D) __JM_STD::forward_iterator<T, D> + #define JM_BIDI_ITERATOR(T, D) __JM_STD::bidirectional_iterator<T, D> + #define JM_RA_ITERATOR(T, D) __JM_STD::random_access_iterator<T, D> + + /* old style allocator */ + #define JM_OLD_ALLOCATORS + #define REBIND_INSTANCE(x, y, inst) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y>(inst) + #define REBIND_TYPE(x, y) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y> + #define JM_DEF_ALLOC_PARAM(x) JM_DEFAULT_PARAM( jm_def_alloc ) + #define JM_DEF_ALLOC(x) jm_def_alloc + + #define JM_NEED_BINDER + #define JM_NEED_ALLOC + #define JM_NO_NOT_EQUAL + + #define JM_STL_DONE + + #elif defined (_MSC_VER) + + /* assume we're using MS's own STL (VC++ 5/6) */ + #define __JM_STD std + #define __JM_STDC + #define JM_NO_OI_ASSIGN + + #define JM_DISTANCE(i, j, n) n = __JM_STD::distance(i, j) + #define JM_OUTPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D> + #define JM_INPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D> + #define JM_FWD_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D> + #define JM_BIDI_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D> + #define JM_RA_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D> + + /* MS's allocators are rather ambiguous about their properties + at least as far as MSDN is concerned, so play safe: */ + #define JM_OLD_ALLOCATORS + #define REBIND_INSTANCE(x, y, inst) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y>(inst) + #define REBIND_TYPE(x, y) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y> + #define JM_DEF_ALLOC_PARAM(x) JM_DEFAULT_PARAM( jm_def_alloc ) + #define JM_DEF_ALLOC(x) jm_def_alloc + + #define JM_NEED_BINDER + #define JM_NEED_ALLOC + + #define JM_STL_DONE + + #define JM_USE_FACET(l, type) __JM_STD::use_facet(l, (type*)0, true) + #define JM_HAS_FACET(l, type) __JM_STD::has_facet(l, (type*)0) + + + + #else + + /* unknown STL version + try the defaults: */ + + #define JM_DISTANCE(i, j, n) __JM_STD::distance(i, j, n) + /* these may be suspect for older libraries */ + #define JM_OUTPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D, T*, T&> + #define JM_INPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D, T*, T&> + #define JM_FWD_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D, T*, T&> + #define JM_BIDI_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D, T*, T&> + #define JM_RA_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D, T*, T&> + + #endif /* <iterator> config */ + +#else /* no <iterator> at all */ + + #define JM_DISTANCE(i, j, n) (n = j - i) + #define JM_OUTPUT_ITERATOR(T, D) dummy_iterator_base<T> + #define JM_INPUT_ITERATOR(T, D) dummy_iterator_base<T> + #define JM_FWD_ITERATOR(T, D) dummy_iterator_base<T> + #define JM_BIDI_ITERATOR(T, D) dummy_iterator_base<T> + #define JM_RA_ITERATOR(T, D) dummy_iterator_base<T> + + +#endif + +/* now do allocator if not already done */ + +#ifndef JM_STL_DONE + + #ifdef JM_NO_MEMORY_H + + /* old style allocator */ + + #define JM_OLD_ALLOCATORS + + #define REBIND_INSTANCE(x, y, inst) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y>(inst) + #define REBIND_TYPE(x, y) JM_MAYBE_ACCESS_SPEC re_alloc_binder<x, y> + #define JM_DEF_ALLOC_PARAM(x) JM_DEFAULT_PARAM( jm_def_alloc ) + #define JM_DEF_ALLOC(x) jm_def_alloc + + #define JM_NEED_BINDER + #define JM_NEED_ALLOC + + #else + + /* new style allocator's with nested template classes */ + + #define REBIND_INSTANCE(x, y, inst) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other(inst) + #define REBIND_TYPE(x, y) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other + #define JM_DEF_ALLOC_PARAM(x) JM_TRICKY_DEFAULT_PARAM( __JM_STD::allocator<x> ) + #define JM_DEF_ALLOC(x) __JM_STD::allocator<x> + + #endif + +#endif +#endif // JM_AUTO_CONFIGURE + + + +/* namespace configuration goes here: */ +#ifdef JM_NO_NAMESPACES + + #ifdef __JM_STD + #undef __JM_STD + #endif + + #ifdef __JM_STDC + #undef __JM_STDC + #endif + + #ifdef __JM + #undef __JM + #endif + + #define __JM + #define __JM_STD + #define __JM_STDC + #define JM_NAMESPACE(x) + #define JM_END_NAMESPACE + #define JM_USING(x) + +#else + + #ifndef __JM_STD + #define __JM_STD std + #endif + + #ifndef __JM_STDC + #define __JM_STDC std + #endif + + #ifndef __JM + #define __JM jm + #endif + + #define JM_NAMESPACE(x) namespace x{ + #define JM_END_NAMESPACE }; + #define JM_USING(x) using namespace x; + +#endif + +/* locale configuration goes here */ +#if !defined(JM_NO_LOCALE_H) && defined(RE_LOCALE_CPP) + #include <locale> + #define LOCALE_INSTANCE(i) __JM_STD::locale i; + #define MAYBE_PASS_LOCALE(i) , i + #ifndef JM_NO_TEMPLATE_RETURNS + #ifndef JM_USE_FACET + #define JM_USE_FACET(l, type) __JM_STD::use_facet< type >(l) + #endif + #ifndef JM_HAS_FACET + #define JM_HAS_FACET(l, type) __JM_STD::has_facet< type >(l) + #endif + #else + #ifndef JM_USE_FACET + #define JM_USE_FACET(l, type) __JM_STD::use_facet(l, (type*)0) + #endif + #ifndef JM_HAS_FACET + #define JM_HAS_FACET(l, type) __JM_STD::has_facet(l, (type*)0) + #endif + #endif +#else + #define LOCALE_INSTANCE(i) + #define MAYBE_PASS_LOCALE(i) +#endif + +/* compiler configuration goes here: */ + +#ifdef JM_NO_MUTABLE + #define JM_MUTABLE +#else + #define JM_MUTABLE mutable +#endif + +#if defined( JM_NO_BOOL) && !defined(bool) + #define bool int + #define true 1 + #define false 0 +#endif + +#ifndef RE_CALL +#define RE_CALL +#endif + +#ifndef RE_CCALL +#define RE_CCALL +#endif + +#ifndef RE_DECL +#define RE_DECL +#endif + +#if defined(JM_NO_DEFAULT_PARAM) || defined(JM_NO_TRICKY_DEFAULT_PARAM) +#define JM_NO_STRING_DEF_ARGS +#endif + + + +/* add our class def's if they are needed: */ + +JM_NAMESPACE(__JM) + +// add our destroy functions: + +template <class T> +inline void RE_CALL jm_destroy(T* t) +{ + t->~T(); +} + +inline void RE_CALL jm_destroy(char* t){} +inline void RE_CALL jm_destroy(short* t){} +inline void RE_CALL jm_destroy(unsigned short* t){} +inline void RE_CALL jm_destroy(int* t){} +inline void RE_CALL jm_destroy(unsigned int* t){} +inline void RE_CALL jm_destroy(long* t){} +inline void RE_CALL jm_destroy(unsigned long* t){} + + +template <class T> +inline void RE_CALL jm_construct(void* p, const T& t) +{ + new (p) T(t); +} + + +template<class T, class Allocator> +class re_alloc_binder : public Allocator +{ +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef __JM_STDC::ptrdiff_t difference_type; + + re_alloc_binder(const Allocator& i); + re_alloc_binder(const re_alloc_binder& o) : Allocator(o) {} + + T* RE_CALL allocate(size_t n, size_t /* hint */ = 0) + { return 0 == n ? 0 : (T*) this->Allocator::allocate(n * sizeof(T)); } + void RE_CALL deallocate(T *p, size_t n) + { if (0 != n) this->Allocator::deallocate((char*)p, n * sizeof (T)); } + + pointer RE_CALL address(reference x) const { return &x; } + const_pointer RE_CALL address(const_reference x) const { return &x; } + static size_type RE_CALL max_size() { return -1; } + static void RE_CALL construct(pointer p, const T& val) { jm_construct(p, val); } + void RE_CALL destroy(pointer p) { jm_destroy(p); } + + const Allocator& RE_CALL instance()const { return *this; } + +#ifndef JM_NO_MEMBER_TEMPLATES + + template <class U> + struct rebind + { + typedef re_alloc_binder<U, Allocator> other; + }; + + template <class U> + RE_CALL re_alloc_binder(const re_alloc_binder<U, Allocator>& o) throw() + : Allocator(o.instance()) + { + } +#endif +}; + +template<class T, class Allocator> +inline re_alloc_binder<T, Allocator>::re_alloc_binder(const Allocator &i) + : Allocator(i) +{} + + +// +// class jm_def_alloc +// basically a standard allocator that only allocates bytes... +// think of it as allocator<char>, with a non-standard +// rebind::other typedef. +// +class jm_def_alloc +{ +public: + typedef char value_type; + typedef char* pointer; + typedef const char* const_pointer; + typedef char& reference; + typedef const char& const_reference; + typedef size_t size_type; + typedef __JM_STDC::ptrdiff_t difference_type; + + pointer RE_CALL address(reference x) const { return &x; } + const_pointer RE_CALL address(const_reference x) const { return &x; } + static size_type RE_CALL max_size() { return (size_type)-1; } + static void RE_CALL construct(pointer , const char& ) { } + void RE_CALL destroy(pointer ) { } + static void * RE_CALL allocate(size_t n, size_t /* hint */ = 0) + { + return ::operator new(n); + } + static void RE_CALL deallocate(void *p, size_t /*n*/ ) + { + ::operator delete(p); + } + +#ifndef JM_NO_MEMBER_TEMPLATES + template <class U> + struct rebind + { + typedef re_alloc_binder<U, jm_def_alloc> other; + }; + + template <class U> + RE_CALL jm_def_alloc(const re_alloc_binder<U, jm_def_alloc>& ) throw() { } +#endif + jm_def_alloc(const jm_def_alloc&) {} + jm_def_alloc() {} +}; + +template <class T> +struct dummy_iterator_base +{ + typedef T value_type; + typedef __JM_STDC::ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; + //typedef Category iterator_category; +}; + +// we need to absolutely sure that int values are correctly +// translated to bool (true or false) values... +// note that the original HP STL redefines the bool type regardless +// of whether the compiler supports it.... yuk + +#if defined(JM_NO_BOOL) || defined(ITERATOR_H) || defined(bool) +#define JM_MAKE_BOOL(x) boolify(x) + +template <class I> +inline bool RE_CALL boolify(I val) +{ + return val ? true : false; +} + +#else +#define JM_MAKE_BOOL(x) x +#endif + +// class auto_array: +// +// encapsulates objects allocated with ::operator new[]() +// interface the same as auto_ptr, but no stream operators +// since we don't know how big the array is. +// +// Usage: auto_array<char> buf = new char[256]; +// + +template<class X> +class auto_array +{ +public: // construct/copy/destroy: + + auto_array(X* p =0) + { ptr = p; } + + auto_array(const auto_array& ap) + { ptr = const_cast<auto_array&>(ap).release(); } + + void RE_CALL operator=(const auto_array&); + + ~auto_array(); + + // members: + + X& RE_CALL operator*() const; + X* RE_CALL operator->() const; + X* RE_CALL get() const; + X& RE_CALL operator[](int i); + X* RE_CALL release(); + + // operator not part of the spec: + RE_CALL operator X*()const + { return ptr; } + +private: // data: + + X* ptr; +}; + +template <class X> +inline void RE_CALL auto_array<X>::operator=(const auto_array<X>& ap) +{ + delete[] ptr; + ptr = const_cast<auto_array<X>&>(ap).release(); +} + +template <class X> +inline auto_array<X>::~auto_array() +{ + delete[] ptr; +} + +template <class X> +inline X& RE_CALL auto_array<X>::operator*() const +{ + return *ptr; +} + +template <class X> +inline X* RE_CALL auto_array<X>::operator->() const +{ + return ptr; +} + +template <class X> +inline X* RE_CALL auto_array<X>::get() const +{ + return ptr; +} + +template <class X> +inline X& RE_CALL auto_array<X>::operator[](int i) +{ + return ptr[i]; +} + +template <class X> +inline X* RE_CALL auto_array<X>::release() +{ + X* tmp = ptr; + ptr = NULL; + return tmp; +} + + +JM_END_NAMESPACE + +#if !defined(INLINE_EXCEPTION_BUG) || defined(JM_NO_TEMPLATE_MERGE) + #define CONSTRUCTOR_INLINE inline +#else + #define CONSTRUCTOR_INLINE +#endif + +#if defined(JM_PLATFORM_W32) && !defined(RE_LOCALE_W32) && !defined(RE_LOCALE_C) && !defined(RE_LOCALE_CPP) && !defined(JM_NO_W32) +#define RE_LOCALE_W32 +#endif + +#if !defined(RE_LOCALE_W32) && !defined(RE_LOCALE_C) && !defined(RE_LOCALE_CPP) +#define RE_LOCALE_C +#endif + +#if defined(JM_OLD_ALLOCATORS) && defined(JM_NO_TEMPLATE_TYPENAME) +#define JM_MAYBE_TYPENAME +#else +#define JM_MAYBE_TYPENAME typename +#endif + +#ifdef RE_LOCALE_W32 +#include <windows.h> +#endif + + +/* now do debugging stuff: */ + +#ifdef JM_DEBUG + +#ifdef OLD_IOSTREAM +#include <iostream.h> +#else +#include <iostream> +using std::cout; +using std::cin; +using std::cerr; +#endif + + #ifndef jm_assert + #define jm_assert(x) if((x) == 0){ cerr << "Assertion failed: " << #x << " in file " << __FILE__ << "and line " << __LINE__ << endl; exit(-1); } + #endif + #ifndef jm_trace + #define jm_trace(x) cerr << x; + #endif + + #ifdef __BORLANDC__ + #pragma message "macro __jm_std: " __JM_STD + #pragma message "macro __jm_stdc: " __JM_STDC + #pragma message "macro namespace: " JM_NAMESPACE(__JM_STD) + #pragma message "macro allocator: " JM_DEF_ALLOC_PARAM(wchar_t) + #pragma message "macro jm_input_iterator: " JM_INPUT_ITERATOR(char, __JM_STDC::ptrdiff_t) + #pragma message "macro jm_output_iterator: " JM_OUTPUT_ITERATOR(char, __JM_STDC::ptrdiff_t) + #pragma message "macro jm_fwd_iterator: " JM_FWD_ITERATOR(char, __JM_STDC::ptrdiff_t) + #pragma message "macro jm_bidi_iterator: " JM_BIDI_ITERATOR(char, __JM_STDC::ptrdiff_t) + #pragma message "macro jm_ra_iterator: " JM_RA_ITERATOR(char, __JM_STDC::ptrdiff_t) + #ifdef RE_LOCALE_CPP + #pragma message "locale support enabled" + #endif + #endif + +#else + + #define jm_assert(x) + #define jm_trace(x) + +#endif + +#endif /* __cplusplus */ + + +#endif + + + + + + + + + + + + + + + + + diff --git a/utils/tfstats/regexp/include/jm/jm_opt.h b/utils/tfstats/regexp/include/jm/jm_opt.h new file mode 100644 index 0000000..0c53a50 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/jm_opt.h @@ -0,0 +1,414 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#ifndef JM_OPT_H +#define JM_OPT_H + +/* #define JM_AUTO_CONFIGURE */ +#ifdef JM_AUTO_CONFIGURE + +/* Namespace Options: */ + +/* JM_NO_NAMESPACES Define if your compiler does not support namespaces */ +/* #define JM_NO_NAMESPACES */ + +/* __JM Defines the namespace used for this library, + defaults to "jm", but can be changed by defining + __JM on the command line. */ +/* #define __JM */ + +/* __JM_STD Defines the namespace used by the underlying STL + (if any), defaults to "std", can be changed by + defining __JM_STD on the command line. */ +/* #define __JM_STD */ + + +/* __JM_STDC Defines the namespace used by the C Library defs. + Defaults to "std" as recomended by the latest + draft standard, can be redefined by defining + __JM_STDC on the command line. */ +/* #define __JM_STDC */ + + + +/* Compiler options: */ + +/* JM_NO_EXCEPTIONS Disables exception handling support. */ +/* #define JM_NO_EXCEPTIONS */ + +/* JM_NO_MUTABLE Disables use of mutable keyword. */ +/* #define JM_NO_MUTABLE */ + +/* JM_INT32 The type for 32-bit integers - what C calls intfast32_t */ +/* #define JM_INT32 */ + +/* JM_NO_DEFAULT_PARAM If templates can not have default parameters. */ +/* #define JM_NO_DEFAULT_PARAM */ + +/* JM_NO_TRICKY_DEFAULT_PARAM If templates can not have derived default parameters. */ +/* #define JM_NO_TRICKY_DEFAULT_PARAM */ + +/* JM_NO_TEMPLATE_TYPENAME If class scope typedefs of the form: + typedef typename X<T> Y; + where T is a template parameter to this, + do not compile unless the typename is omitted. */ +/* #define JM_NO_TEMPLATE_TYPENAME */ + +/* JM_NO_TEMPLATE_FRIEND If template friend declarations are not supported */ +/* #define JM_NO_TEMPLATE_FRIEND */ + +/* JM_PLATFORM_WINDOWS Platform is MS Windows. */ +/* #define JM_PLATFORM_WINDOWS */ + +/* JM_PLATFORM_DOS Platform if MSDOS. */ +/* #define JM_PLATFORM_DOS */ + +/* JM_PLATFORM_W32 Platform is MS Win32 */ +/* #define JM_PLATFORM_W32 */ + +/* JM_NO_WIN32 Disable Win32 support even when present */ +/* #define JM_NO_WIN32 */ + +/* JM_NO_BOOL If bool is not a distict type. */ +/* #define JM_NO_BOOL */ + +/* JM_NO_WCHAR_H If there is no <wchar.h> */ +/* #define JM_NO_WCHAR_H */ + +/* JM_NO_WCTYPE_H If there is no <wctype.h> */ +/* #define JM_NO_WCTYPE_H */ + +/* JM_NO_WCSTRING If there are no wcslen and wcsncmp functions available. */ +/* #define JM_NO_WCSTRING */ + +/* JM_NO_SWPRINTF If there is no swprintf available. */ +/* #define JM_NO_SWPRINTF */ + +/* JM_NO_WSPRINTF If there is no wsprintf available. */ +/* #define JM_NO_WSPRINTF */ + +/* JM_NO_MEMBER_TEMPLATES If member function templates or nested template classes are not allowed. */ +/* #define JM_NO_MEMBER_TEMPLATES */ + +/* JM_NO_TEMPLATE_RETURNS If template functions based on return type are not supported. */ +/* #define JM_NO_TEMPLATE_RETURNS */ + +/* JM_NO_PARTIAL_FUNC_SPEC If partial template function specialisation is not supported */ +/* #define JM_NO_PARTIAL_FUNC_SPEC */ + +/* JM_NO_INT64 If 64bit integers are not supported. */ +/* JM_INT64t The type of a 64-bit signed integer if available. */ +/* JM_IMM64(val) Declares a 64-bit immediate value by appending any + necessary suffix to val. */ +/* JM_INT64_T 0 = NA + 1 = short + 2 = int + 3 = long + 4 = int64_t + 5 = long long + 6 = __int64 */ +/* #define JM_INT64_T */ + +/* JM_NO_CAT Define if the compiler does not support POSIX style + message categories (catopen catgets catclose). */ +/* #define JM_NO_CAT */ + +/* JM_THREADS Define if the compiler supports multiple threads in + the current translation mode. */ +/* #define JM_THREADS */ + +/* JM_TEMPLATE_SPECIALISE Defaults to template<> , ie the template specialisation + prefix, can be redefined to nothing for older compilers. */ +/* #define JM_TEMPLATE_SPECIALISE */ + +/* JM_NESTED_TEMPLATE_DECL Defaults to template, the standard prefix when accessing + nested template classes, can be redefined to nothing if + the compiler does not support this. */ +/* #define JM_NESTED_TEMPLATE_DECL */ + +/* JM_NO_TEMPLATE_INST If explicit template instantiation with the "template class X<T>" + syntax is not supported */ +/* #define JM_NO_TEMPLATE_INST */ + +/* JM_NO_TEMPLATE_MERGE If template in separate translation units don't merge at link time */ +/* #define JM_NO_TEMPLATE_MERGE */ + +/* JM_NO_TEMPLATE_MERGE_A If template merging from library archives is not supported */ +/* #define JM_NO_TEMPLATE_MERGE_A */ + +/* JM_NO_TEMPLATE_SWITCH_MERGE If merging of templates containing switch statements is not supported */ +/* #define JM_NO_TEMPLATE_SWITCH_MERGE */ + +/* RE_CALL Optionally define a calling convention for C++ functions */ +/* #define RE_CALL */ + +/* RE_CCALL Optionally define a calling convention for C functions */ +/* #define RE_CCALL */ + +/* JM_SIZEOF_SHORT sizeof(short) */ +/* #define JM_SIZEOF_SHORT */ + +/* JM_SIZEOF_INT sizeof(int) */ +/* #define JM_SIZEOF_INT */ + +/* JM_SIZEOF_LONG sizeof(long) */ +/* #define JM_SIZEOF_LONG */ + +/* JM_SIZEOF_WCHAR_T sizeof(wchar_t) */ +/* #define JM_SIZEOF_WCHAR_T */ + + +/* STL options: */ + +/* JM_NO_EXCEPTION_H Define if you do not a compliant <exception> + header file. */ +/* #define JM_NO_EXCEPTION_H */ + +/* JM_NO_ITERATOR_H Define if you do not have a version of <iterator>. */ +/* #define JM_NO_ITERATOR_H */ + +/* JM_NO_MEMORY_H Define if <memory> does not fully comply with the + latest standard, and is not auto-recognised, + that means nested template classes + which hardly any compilers support at present. */ +/* #define JM_NO_MEMORY_H */ + +/* JM_NO_LOCALE_H Define if there is no verion of the standard + <locale> header available. */ +/* #define JM_NO_LOCALE_H */ + +/* JM_NO_STL Disables the use of any supporting STL code. */ +/* #define JM_NO_STL */ + +/* JM_NO_NOT_EQUAL Disables the generation of operator!= if this + clashes with the STL version. */ + +/* JM_NO_STRING_H Define if <string> not available */ +/* #define JM_NO_STRING_H */ + +/* JM_NO_STRING_DEF_ARGS Define if std::basic_string<charT> not allowed - in + other words if the template is missing its required + default arguments. */ +/* #define JM_NO_STRING_DEF_ARGS */ + +/* JM_NO_TYPEINFO Define if <typeinfo> is absent or non-standard */ +/* #define JM_NO_TYPEINFO */ + +/* JM_USE_ALGO If <algo.h> not <algorithm> is present */ +/* #define JM_USE_ALGO */ + +/* JM_OLD_IOSTREAM If the new iostreamm classes are not available */ +/* #define JM_OLD_IOSTREAM */ + +/* JM_DISTANCE_T For std::distance: + 0 = NA + 1 = std::distance(i, j, n) + 2 = n = std::distance(i, j) */ +/* #define JM_DISTANCE_T */ + +/* JM_ITERATOR_T Defines generic standard iterator type if available, use this as + a shortcut to define all the other iterator types. + 1 = __JM_STD::iterator<__JM_STD::tag_type, T, D, T*, T&> + 2 = __JM_STD::iterator<__JM_STD::tag_type, T, D> */ +/* #define JM_ITERATOR_T */ + +/* JM_OI_T For output iterators: + 0 = NA + 1 = __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D, T*, T&> + 2 = __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D> + 3 = __JM_STD::output_iterator */ +/* #define JM_OI_T */ + +/* JM_II_T For input iterators: + 0 = NA + 1 = __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D, T*, T&> + 2 = __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D> + 3 = __JM_STD::input_iterator<T, D> + 4 = __JM_STD::input_iterator<T> */ +/* #define JM_II_T */ + +/* JM_FI_T For forward iterators: + 0 = NA + 1 = __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D, T*, T&> + 2 = __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D> + 3 = __JM_STD::forward_iterator<T, D> */ +/* #define JM_FI_T */ + +/* JM_BI_T For bidirectional iterators: + 0 = NA + 1 = __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D, T*, T&> + 2 = __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D> + 3 = __JM_STD::bidirectional_iterator<T, D> */ +/* #define JM_BI_T */ + +/* JM_RI_T For random access iterators: + 0 = NA + 1 = __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D, T*, T&> + 2 = __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D> + 3 = __JM_STD::random_access_iterator<T, D> */ +/* #define JM_RI_T */ + +/* JM_NO_OI_ASSIGN If output iterators ostream_iterator<>, back_insert_iterator<> and + front_insert_iterator<> do not have assignment operators */ +/* #define JM_NO_OI_ASSIGN */ + + +#if JM_INT64_T == 0 +#define JM_NO_INT64 +#elif JM_INT64_T == 1 +#define JM_INT64t short +#define JM_IMM64(val) val +#elif JM_INT64_T == 2 +#define JM_INT64t int +#define JM_IMM64(val) val +#elif JM_INT64_T == 3 +#define JM_INT64t long +#define JM_IMM64(val) val##L +#elif JM_INT64_T == 4 +#define JM_INT64t int64_t +#define JM_IMM64(val) INT64_C(val) +#elif JM_INT64_T == 5 +#define JM_INT64t long long +#define JM_IMM64(val) val##LL +#elif JM_INT64_T == 6 +#define JM_INT64t __int64 +#define JM_IMM64(val) val##i64 +#else +syntax error: unknown value for JM_INT64_T +#endif + +#if JM_DISTANCE_T == 0 +# define JM_DISTANCE(i, j, n) n = j - i +#elif JM_DISTANCE_T == 1 +# define JM_DISTANCE(i, j, n) n = __JM_STD::distance(i, j) +#elif JM_DISTANCE_T == 2 +# define JM_DISTANCE(i, j, n) (n = 0, __JM_STD::distance(i, j, n)) +#else +syntax erorr +#endif + +#ifdef JM_ITERATOR_T +#ifndef JM_OI_T +#define JM_OI_T JM_ITERATOR_T +#endif +#ifndef JM_II_T +#define JM_II_T JM_ITERATOR_T +#endif +#ifndef JM_FI_T +#define JM_FI_T JM_ITERATOR_T +#endif +#ifndef JM_BI_T +#define JM_BI_T JM_ITERATOR_T +#endif +#ifndef JM_RI_T +#define JM_RI_T JM_ITERATOR_T +#endif +#endif + +#if JM_OI_T == 0 +# define JM_OUTPUT_ITERATOR(T, D) dummy_iterator_base<T> +#elif JM_OI_T == 1 +# define JM_OUTPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D, T*, T&> +#elif JM_OI_T == 2 +# define JM_OUTPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D> +#elif JM_OI_T == 3 +# define JM_OUTPUT_ITERATOR(T, D) __JM_STD::output_iterator +#else +syntax error +#endif + +#if JM_II_T == 0 +# define JM_INPUT_ITERATOR(T, D) dummy_iterator_base<T> +#elif JM_II_T == 1 +#define JM_INPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D, T*, T&> +#elif JM_II_T == 2 +#define JM_INPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D> +#elif JM_II_T == 3 +# define JM_INPUT_ITERATOR(T, D) __JM_STD::input_iterator<T, D> +#elif JM_II_T == 4 +# define JM_INPUT_ITERATOR(T, D) __JM_STD::input_iterator<T> +#else +syntax error +#endif + +#if JM_FI_T == 0 +# define JM_FWD_ITERATOR(T, D) dummy_iterator_base<T> +#elif JM_FI_T == 1 +# define JM_FWD_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D, T*, T&> +#elif JM_FI_T == 2 +# define JM_FWD_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D> +#elif JM_FI_T == 3 +# define JM_FWD_ITERATOR(T, D) __JM_STD::forward_iterator<T, D> +#else +syntax error +#endif + +#if JM_BI_T == 0 +# define JM_BIDI_ITERATOR(T, D) dummy_iterator_base<T> +#elif JM_BI_T == 1 +# define JM_BIDI_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D, T*, T&> +#elif JM_BI_T == 2 +# define JM_BIDI_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D> +#elif JM_BI_T == 3 +# define JM_BIDI_ITERATOR(T, D) __JM_STD::bidirectional_iterator<T, D> +#else +syntax error +#endif + +#if JM_RI_T == 0 +# define JM_RA_ITERATOR(T, D) dummy_iterator_base<T> +#elif JM_RI_T == 1 +# define JM_RA_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D, T*, T&> +#elif JM_RI_T == 2 +# define JM_RA_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D> +#elif JM_RI_T == 3 +# define JM_RA_ITERATOR(T, D) __JM_STD::random_access_iterator<T, D> +#else +syntax error +#endif + + +#ifndef JM_NO_EXCEPTION_H +#include <exception> +#endif + +#ifndef JM_NO_ITERATOR_H +#include <iterator> +#ifdef JM_USE_ALGO +#include <algo.h> +#else +#include <algorithm> +#endif +#endif + +#ifdef JM_NO_MEMORY_H + #define JM_OLD_ALLOCATORS + #define REBIND_INSTANCE(x, y, inst) re_alloc_binder<x, y>(inst) + #define REBIND_TYPE(x, y) re_alloc_binder<x, y> + #define JM_DEF_ALLOC_PARAM(x) JM_DEFAULT_PARAM( jm_def_alloc ) + #define JM_DEF_ALLOC(x) jm_def_alloc + + #define JM_NEED_BINDER + #define JM_NEED_ALLOC +#else +#include <memory> + #define REBIND_INSTANCE(x, y, inst) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other(inst) + #define REBIND_TYPE(x, y) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other + #define JM_DEF_ALLOC_PARAM(x) JM_TRICKY_DEFAULT_PARAM( __JM_STD::allocator<x> ) + #define JM_DEF_ALLOC(x) __JM_STD::allocator<x> +#endif + + +#endif // JM_AUTO_CONFIGURE + + +#endif /* JM_OPT_H */ + + + + diff --git a/utils/tfstats/regexp/include/jm/jstack.h b/utils/tfstats/regexp/include/jm/jstack.h new file mode 100644 index 0000000..fca5058 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/jstack.h @@ -0,0 +1,209 @@ +//========= 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 jstack.h + * VERSION 2.12 + */ + +#ifndef __JSTACH_H +#define __JSTACK_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +JM_NAMESPACE(__JM) + +// +// class jstack +// simplified stack optimised for push/peek/pop +// operations, we could use std::stack<std::vector<T>> instead... +// +template <class T, class Allocator JM_DEF_ALLOC_PARAM(T) > +class jstack +{ +private: + typedef JM_MAYBE_TYPENAME REBIND_TYPE(unsigned char, Allocator) alloc_type; + typedef typename REBIND_TYPE(T, Allocator)::size_type size_type; + struct node + { + node* next; + T* start; // first item + T* end; // last item + T* last; // end of storage + }; + + // + // empty base member optimisation: + struct data : public alloc_type + { + unsigned char buf[sizeof(T)*16]; + data(const Allocator& a) : alloc_type(a){} + }; + + data alloc_inst; + mutable node* stack; + mutable node* unused; + node base; + size_type block_size; + + void RE_CALL pop_aux()const; + void RE_CALL push_aux(); + +public: + jstack(size_type n = 64, const Allocator& a = Allocator()); + + ~jstack(); + + node* RE_CALL get_node() + { + node* new_stack = (node*)alloc_inst.allocate(sizeof(node) + sizeof(T) * block_size); + new_stack->last = (T*)(new_stack+1); + new_stack->start = new_stack->end = new_stack->last + block_size; + new_stack->next = 0; + return new_stack; + } + + bool RE_CALL empty() + { + return (stack->start == stack->end) && (stack->next == 0); + } + + bool RE_CALL good() + { + return (stack->start != stack->end) || (stack->next != 0); + } + + T& RE_CALL peek() + { + if(stack->start == stack->end) + pop_aux(); + return *stack->end; + } + + const T& RE_CALL peek()const + { + if(stack->start == stack->end) + pop_aux(); + return *stack->end; + } + + void RE_CALL pop() + { + if(stack->start == stack->end) + pop_aux(); + jm_destroy(stack->end); + ++(stack->end); + } + + void RE_CALL pop(T& t) + { + if(stack->start == stack->end) + pop_aux(); + t = *stack->end; + jm_destroy(stack->end); + ++(stack->end); + } + + void RE_CALL push(const T& t) + { + if(stack->end == stack->last) + push_aux(); + --(stack->end); + jm_construct(stack->end, t); + } + +}; + +template <class T, class Allocator> +jstack<T, Allocator>::jstack(size_type n, const Allocator& a) + : alloc_inst(a) +{ + unused = 0; + block_size = n; + stack = &base; + base.last = (T*)alloc_inst.buf; + base.end = base.start = base.last + 16; + base.next = 0; +} + +template <class T, class Allocator> +void RE_CALL jstack<T, Allocator>::push_aux() +{ + // make sure we have spare space on TOS: + register node* new_node; + if(unused) + { + new_node = unused; + unused = new_node->next; + new_node->next = stack; + stack = new_node; + } + else + { + new_node = get_node(); + new_node->next = stack; + stack = new_node; + } +} + +template <class T, class Allocator> +void RE_CALL jstack<T, Allocator>::pop_aux()const +{ + // make sure that we have a valid item + // on TOS: + jm_assert(stack->next); + register node* p = stack; + stack = p->next; + p->next = unused; + unused = p; +} + +template <class T, class Allocator> +jstack<T, Allocator>::~jstack() +{ + node* condemned; + while(good()) + pop(); + while(unused) + { + condemned = unused; + unused = unused->next; + alloc_inst.deallocate((unsigned char*)condemned, sizeof(node) + sizeof(T) * block_size); + } + while(stack != &base) + { + condemned = stack; + stack = stack->next; + alloc_inst.deallocate((unsigned char*)condemned, sizeof(node) + sizeof(T) * block_size); + } +} + +JM_END_NAMESPACE + +#endif + + + + + diff --git a/utils/tfstats/regexp/include/jm/re_cls.h b/utils/tfstats/regexp/include/jm/re_cls.h new file mode 100644 index 0000000..5dd8f8e --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_cls.h @@ -0,0 +1,79 @@ +//========= 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 re_cls.h + * VERSION 2.12 + * This is an internal header file, do not include directly. + * character class lookup, for regular + * expression library. + */ + +#ifndef RE_CLS_H +#define RE_CLS_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +#ifndef RE_STR_H +#include <jm/re_str.h> +#endif + +JM_NAMESPACE(__JM) + +#define re_classes_max 14 + +void RE_CALL re_init_classes(); +void RE_CALL re_free_classes(); +void RE_CALL re_update_classes(); +JM_IX_DECL jm_uintfast32_t RE_CALL __re_lookup_class(const char* p); + +inline jm_uintfast32_t RE_CALL re_lookup_class(const char* first, const char* last) +{ + re_str<char> s(first, last); + return __re_lookup_class(s.c_str()); +} + +#ifndef JM_NO_WCSTRING +inline jm_uintfast32_t RE_CALL re_lookup_class(const wchar_t* first, const wchar_t* last) +{ + re_str<wchar_t> s(first, last); + unsigned int len = re_strnarrow((char*)NULL, 0, s.c_str()); + auto_array<char> buf(new char[len]); + re_strnarrow((char*)buf, len, s.c_str()); + len = __re_lookup_class((char*)buf); + return len; +} +#endif + +#ifdef RE_LOCALE_CPP + +extern jm_uintfast32_t re_char_class_id[]; +extern const char* re_char_class_names[]; + +#endif + +JM_END_NAMESPACE + +#endif + diff --git a/utils/tfstats/regexp/include/jm/re_coll.h b/utils/tfstats/regexp/include/jm/re_coll.h new file mode 100644 index 0000000..d3fa3d0 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_coll.h @@ -0,0 +1,61 @@ +//========= 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 re_coll.h + * VERSION 2.12 + * This is an internal header file, do not include directly + */ + +#ifndef RE_COLL_H +#define RE_COLL_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +#ifndef RE_STR_H +#include <re_str.h> +#endif + +JM_NAMESPACE(__JM) + +JM_IX_DECL bool RE_CALL re_lookup_def_collate_name(re_str<char>& buf, const char* name); + +void RE_CALL re_init_collate(); +void RE_CALL re_free_collate(); +void RE_CALL re_update_collate(); +JM_IX_DECL bool RE_CALL __re_lookup_collate(re_str<char>& buf, const char* p); + +inline bool RE_CALL re_lookup_collate(re_str<char>& buf, const char* first, const char* last) +{ + re_str<char> s(first, last); + return __re_lookup_collate(buf, s.c_str()); +} + +#ifndef JM_NO_WCSTRING +JM_IX_DECL bool RE_CALL re_lookup_collate(re_str<wchar_t>& out, const wchar_t* first, const wchar_t* last); +#endif + +JM_END_NAMESPACE + +#endif diff --git a/utils/tfstats/regexp/include/jm/re_kmp.h b/utils/tfstats/regexp/include/jm/re_kmp.h new file mode 100644 index 0000000..65d1e90 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_kmp.h @@ -0,0 +1,112 @@ +//========= 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 re_kmp.h + * VERSION 2.12 + * Knuth-Morris-Pratt search. + */ + + +#ifndef __RE_KMP_H +#define __RE_KMP_H + +#ifdef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + + +JM_NAMESPACE(__JM) + +template <class charT> +struct kmp_info +{ + unsigned int size; + unsigned int len; + const charT* pstr; + int kmp_next[1]; +}; + +template <class charT, class Allocator> +void kmp_free(kmp_info<charT>* pinfo, Allocator a) +{ + typedef JM_MAYBE_TYPENAME REBIND_TYPE(char, Allocator) atype; + atype(a).deallocate((char*)pinfo, pinfo->size); +} + +template <class iterator, class charT, class Trans, class Allocator> +kmp_info<charT>* kmp_compile(iterator first, iterator last, charT, Trans translate, Allocator a +#ifdef RE_LOCALE_CPP + , const __JM_STD::locale& l +#endif + ) +{ + typedef JM_MAYBE_TYPENAME REBIND_TYPE(char, Allocator) atype; + int i, j, m; + i = 0; + m = 0; + JM_DISTANCE(first, last, m); + ++m; + unsigned int size = sizeof(kmp_info<charT>) + sizeof(int)*m + sizeof(charT)*m; + --m; + // + // allocate struct and fill it in: + // + kmp_info<charT>* pinfo = (kmp_info<charT>*)atype(a).allocate(size); + pinfo->size = size; + pinfo->len = m; + charT* p = (charT*)((char*)pinfo + sizeof(kmp_info<charT>) + sizeof(int)*(m+1)); + pinfo->pstr = p; + while(first != last) + { + *p = translate(*first MAYBE_PASS_LOCALE(l)); + ++first; + ++p; + } + *p = 0; + // + // finally do regular kmp compile: + // + j = pinfo->kmp_next[0] = -1; + while (i < m) + { + while ((j > -1) && (pinfo->pstr[i] != pinfo->pstr[j])) + j = pinfo->kmp_next[j]; + ++i; + ++j; + if (pinfo->pstr[i] == pinfo->pstr[j]) + pinfo->kmp_next[i] = pinfo->kmp_next[j]; + else + pinfo->kmp_next[i] = j; + } + + return pinfo; +} + + +JM_END_NAMESPACE // namespace regex + +#endif // __RE_KMP_H + + + + diff --git a/utils/tfstats/regexp/include/jm/re_lib.h b/utils/tfstats/regexp/include/jm/re_lib.h new file mode 100644 index 0000000..4e87eb9 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_lib.h @@ -0,0 +1,155 @@ +//========= 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 re_lib.h + * VERSION 2.12 + * Automatic library file inclusion. + */ + + +#ifndef RE_LIB_H +#define RE_LIB_H + +#if defined(_MSC_VER) && !defined(RE_BUILD_DLL) + #ifdef _DLL + #ifdef _DEBUG + #pragma comment(lib, "mre200dl.lib") + #else // DEBUG + #pragma comment(lib, "mre200l.lib") + #endif // _DEBUG + #else // _DLL + #ifdef _MT + #ifdef _DEBUG + #pragma comment(lib, "mre200dm.lib") + #else //_DEBUG + #pragma comment(lib, "mre200m.lib") + #endif //_DEBUG + #else //_MT + #ifdef _DEBUG + #pragma comment(lib, "mre200d.lib") + #else //_DEBUG + #pragma comment(lib, "mre200.lib") + #endif //_DEBUG + #endif //_MT + #endif //_DLL +#endif //_MSC_VER + + +#if defined(__BORLANDC__) && !defined(RE_BUILD_DLL) + #if (__BORLANDC__ > 0x520) && !defined(_NO_VCL) + #define JM_USE_VCL + #endif + + #if __BORLANDC__ <= 0x520 + + #ifdef JM_USE_VCL + + #ifdef _RTLDLL + #pragma comment(lib, "b2re200lv.lib") + #else + #pragma comment(lib, "b2re200v.lib") + #endif + + #else // VCL + + #ifdef _RTLDLL + #ifdef __MT__ + #pragma comment(lib, "b2re200lm.lib") + #else // __MT__ + #pragma comment(lib, "b2re200l.lib") + #endif // __MT__ + #else //_RTLDLL + #ifdef __MT__ + #pragma comment(lib, "b2re200m.lib") + #else // __MT__ + #pragma comment(lib, "b2re200.lib") + #endif // __MT__ + #endif // _RTLDLL + + #endif // VCL + + #elif __BORLANDC__ <= 0x530 + + #ifdef JM_USE_VCL + + #ifdef _RTLDLL + #pragma comment(lib, "b3re200lv.lib") + #else + #pragma comment(lib, "b3re200v.lib") + #endif + + #else // VCL + + #ifdef _RTLDLL + #ifdef __MT__ + #pragma comment(lib, "b3re200lm.lib") + #else // __MT__ + #pragma comment(lib, "b3re200l.lib") + #endif // __MT__ + #else //_RTLDLL + #ifdef __MT__ + #pragma comment(lib, "b3re200m.lib") + #else // __MT__ + #pragma comment(lib, "b3re200.lib") + #endif // __MT__ + #endif // _RTLDLL + + #endif // VCL + + #else // Version: 0x540 + + #ifdef JM_USE_VCL + + #ifdef _RTLDLL + #pragma comment(lib, "b4re200lv.lib") + #else + #pragma comment(lib, "b4re200v.lib") + #endif + + #else // VCL + + #ifdef _RTLDLL + #ifdef __MT__ + #pragma comment(lib, "b4re200lm.lib") + #else // __MT__ + #pragma comment(lib, "b4re200l.lib") + #endif // __MT__ + #else //_RTLDLL + #ifdef __MT__ + #pragma comment(lib, "b4re200m.lib") + #else // __MT__ + #pragma comment(lib, "b4re200.lib") + #endif // __MT__ + #endif // _RTLDLL + + #endif // VCL + + #endif + +#endif //__BORLANDC__ + + +#endif // RE_LIB_H + + + diff --git a/utils/tfstats/regexp/include/jm/re_lst.h b/utils/tfstats/regexp/include/jm/re_lst.h new file mode 100644 index 0000000..525d2dc --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_lst.h @@ -0,0 +1,184 @@ +//========= 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 re_lst.h + * VERSION 2.12 + * This is an internal header file, do not include directly. + * re_list support class, for regular + * expression library. + */ + +#ifndef RE_LST_H +#define RE_LST_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +#include <new.h> + +JM_NAMESPACE(__JM) + +template <class T, class Allocator> +class re_list +{ +public: + struct node + { + node* next; + T t; + node(const T& o) : t(o) {} + }; +public: + class iterator + { + node* pos; + public: + iterator() { pos = 0; } + ~iterator() {} + iterator(const iterator& i) { pos = i.pos; } + iterator(node* n) { pos = n; } + iterator& operator=(const iterator& i) + { + pos = i.pos; + return *this; + } + bool operator==(iterator& i) + { + return pos == i.pos; + } + bool operator!=(iterator& i) + { + return pos != i.pos; + } + T& operator*() { return pos->t; } + iterator& operator++() + { + pos = pos->next; + return *this; + } + iterator operator++(int) + { + iterator t(*this); + pos = pos->next; + return t; + } + const node* tell()const + { + return pos; + } + }; + + class const_iterator + { + const node* pos; + public: + const_iterator() { pos = 0; } + ~const_iterator() {} + const_iterator(const const_iterator& i) { pos = i.pos; } + const_iterator(const iterator& i) { pos = i.tell(); } + const_iterator(const node* n) { pos = n; } + const_iterator& operator=(const iterator& i) + { + pos = i.tell(); + return *this; + } + const_iterator& operator=(const const_iterator& i) + { + pos = i.pos; + return *this; + } + bool operator==(const_iterator& i) + { + return pos == i.pos; + } + bool operator!=(const_iterator& i) + { + return pos != i.pos; + } + const T& operator*() { return pos->t; } + const_iterator& operator++() + { + pos = pos->next; + return *this; + } + const_iterator operator++(int) + { + const_iterator t(*this); + pos = pos->next; + return t; + } + }; +private: + typedef JM_MAYBE_TYPENAME REBIND_TYPE(node, Allocator) node_alloc; + + struct data : public node_alloc + { + node* first; + data(const Allocator& a) : node_alloc(a), first(0) {} + }; + data alloc_inst; + +public: + re_list(const Allocator& a = Allocator()) : alloc_inst(a) {} + ~re_list() { clear(); } + iterator RE_CALL begin() { return iterator(alloc_inst.first); } + iterator RE_CALL end() { return iterator(0); } + const_iterator RE_CALL begin()const { return const_iterator(alloc_inst.first); } + const_iterator RE_CALL end()const { return const_iterator(0); } + void RE_CALL add(const T& t) + { + node* temp; + temp = alloc_inst.allocate(1); +#ifndef JM_NO_EXCEPTIONS + try{ +#endif + alloc_inst.construct(temp, t); +#ifndef JM_NO_EXCEPTIONS + }catch(...){ alloc_inst.deallocate(temp, 1); throw; } +#endif + temp->next = alloc_inst.first; + alloc_inst.first = temp; + } + void RE_CALL clear(); +}; + +template <class T, class Allocator> +void RE_CALL re_list<T, Allocator>::clear() +{ + node* temp; + while(alloc_inst.first) + { + temp = alloc_inst.first; + alloc_inst.first = alloc_inst.first->next; + alloc_inst.destroy(temp); + alloc_inst.deallocate(temp, 1); + } +} + + +JM_END_NAMESPACE + +#endif + + diff --git a/utils/tfstats/regexp/include/jm/re_mss.h b/utils/tfstats/regexp/include/jm/re_mss.h new file mode 100644 index 0000000..7ff4809 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_mss.h @@ -0,0 +1,90 @@ +//========= 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 re_mss.h + * VERSION 2.12 + * This is an internal header file, do not include directly. + * Message helper functions, for regular + * expression library. + */ + +#ifndef RE_MSS_H +#define RE_MSS_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +JM_NAMESPACE(__JM) + +// +// re_get_message +// returns required buffer size if len is zero +// otherwise fills in buf. +// + +JM_IX_DECL unsigned int RE_CALL re_get_default_message(char* buf, unsigned int len, unsigned int id); + +JM_IX_DECL unsigned int RE_CALL __re_get_message(char* buf, unsigned int len, unsigned int id); + +template <class charT> +unsigned int RE_CALL re_get_message(charT* buf, unsigned int len, unsigned int id) +{ + unsigned int size = __re_get_message((char*)0, 0, id); + if(len < size) + return size; + auto_array<char> cb(new char[size]); + __re_get_message((char*)cb, size, id); + size = re_strwiden(buf, len, (char*)cb); + return size; +} + +inline unsigned int RE_CALL re_get_message(char* buf, unsigned int len, unsigned int id) +{ + return __re_get_message(buf, len, id); +} + + +// +// declare message initialisers: +// +void RE_CALL re_message_init(); +void RE_CALL re_message_update(); +void RE_CALL re_message_free(); + +#ifdef RE_LOCALE_CPP + +__JM_STD::messages<char>::string_type RE_CALL re_get_def_message(unsigned int i); + +__JM_STD::messages<wchar_t>::string_type RE_CALL re_get_def_message_w(unsigned int i); + +extern const char *re_default_error_messages[]; + +#endif + + +JM_END_NAMESPACE + + +#endif + diff --git a/utils/tfstats/regexp/include/jm/re_nls.h b/utils/tfstats/regexp/include/jm/re_nls.h new file mode 100644 index 0000000..b6a293a --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_nls.h @@ -0,0 +1,371 @@ +//========= 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 re_nls.h + * VERSION 2.12 + * This is an internal header file, do not include directly + */ + +#ifndef RE_NLS_H +#define RE_NLS_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +#ifdef RE_LOCALE_CPP +#include <jm/regfac.h> +#endif + +#include <limits.h> + +JM_NAMESPACE(__JM) + +enum char_class_type +{ +#ifdef RE_LOCALE_CPP + char_class_none = 0, + char_class_alnum = __JM_STD::ctype_base::alnum, + char_class_alpha = __JM_STD::ctype_base::alpha, + char_class_cntrl = __JM_STD::ctype_base::cntrl, + char_class_digit = __JM_STD::ctype_base::digit, + char_class_graph = __JM_STD::ctype_base::graph, + char_class_lower = __JM_STD::ctype_base::lower, + char_class_print = __JM_STD::ctype_base::print, + char_class_punct = __JM_STD::ctype_base::punct, + char_class_space = __JM_STD::ctype_base::space, + char_class_upper = __JM_STD::ctype_base::upper, + char_class_xdigit = __JM_STD::ctype_base::xdigit, + char_class_blank = 1<<12, + char_class_underscore = 1<<13, + char_class_word = __JM_STD::ctype_base::alnum | char_class_underscore, + char_class_unicode = 1<<14, + char_class_all_base = char_class_alnum | char_class_alpha | char_class_cntrl + | char_class_digit | char_class_graph | char_class_lower + | char_class_print | char_class_punct | char_class_space + | char_class_upper | char_class_xdigit + +#elif defined(RE_LOCALE_W32) + char_class_none = 0, + char_class_alnum = C1_ALPHA | C1_DIGIT, + char_class_alpha = C1_ALPHA, + char_class_cntrl = C1_CNTRL, + char_class_digit = C1_DIGIT, + char_class_graph = C1_UPPER | C1_LOWER | C1_DIGIT | C1_PUNCT | C1_ALPHA, + char_class_lower = C1_LOWER, + char_class_print = C1_UPPER | C1_LOWER | C1_DIGIT | C1_PUNCT | C1_BLANK | C1_ALPHA, + char_class_punct = C1_PUNCT, + char_class_space = C1_SPACE, + char_class_upper = C1_UPPER, + char_class_xdigit = C1_XDIGIT, + char_class_blank = C1_BLANK, + char_class_underscore = 0x0200, + char_class_word = C1_ALPHA | C1_DIGIT | char_class_underscore, + char_class_unicode = 0x0400 +#else + char_class_none = 0, + char_class_alpha = 1, + char_class_cntrl = char_class_alpha << 1, + char_class_digit = char_class_cntrl << 1, + char_class_lower = char_class_digit << 1, + char_class_punct = char_class_lower << 1, + char_class_space = char_class_punct << 1, + char_class_upper = char_class_space << 1, + char_class_xdigit = char_class_upper << 1, + char_class_blank = char_class_xdigit << 1, + char_class_unicode = char_class_blank << 1, + char_class_underscore = char_class_unicode << 1, + + char_class_alnum = char_class_alpha | char_class_digit, + char_class_graph = char_class_alpha | char_class_digit | char_class_punct | char_class_underscore, + char_class_print = char_class_alpha | char_class_digit | char_class_punct | char_class_underscore | char_class_blank, + char_class_word = char_class_alpha | char_class_digit | char_class_underscore +#endif +}; + +// +// declare our initialise class and functions: +// + +template <class charT> +class re_initialiser +{ +public: + void update(); +}; + +JM_IX_DECL void RE_CALL re_init(); +JM_IX_DECL void RE_CALL re_update(); +JM_IX_DECL void RE_CALL re_free(); +JM_IX_DECL void RE_CALL re_init_w(); +JM_IX_DECL void RE_CALL re_update_w(); +JM_IX_DECL void RE_CALL re_free_w(); + +JM_TEMPLATE_SPECIALISE +class re_initialiser<char> +{ +public: + re_initialiser() { re_init(); } + ~re_initialiser() { re_free(); } + void RE_CALL update() { re_update(); } +}; + +#ifndef JM_NO_WCSTRING +JM_TEMPLATE_SPECIALISE +class re_initialiser<wchar_t> +{ +public: + re_initialiser() { re_init_w(); } + ~re_initialiser() { re_free_w(); } + void RE_CALL update() { re_update_w(); } +}; +#endif + +// +// start by declaring externals for RE_LOCALE_C +// and RE_LOCALE_W32: +// + +JM_IX_DECL extern unsigned char re_syntax_map[]; +JM_IX_DECL extern unsigned short re_class_map[]; +JM_IX_DECL extern char re_lower_case_map[]; +JM_IX_DECL extern char re_zero; +JM_IX_DECL extern char re_ten; + +#ifndef JM_NO_WCSTRING +JM_IX_DECL extern unsigned short re_unicode_classes[]; +JM_IX_DECL extern const wchar_t* re_lower_case_map_w; +JM_IX_DECL extern wchar_t re_zero_w; +JM_IX_DECL extern wchar_t re_ten_w; + +JM_IX_DECL wchar_t RE_CALL re_wtolower(wchar_t c); +JM_IX_DECL bool RE_CALL re_iswclass(wchar_t c, jm_uintfast32_t f); +#endif + +JM_IX_DECL const char* RE_CALL re_get_error_str(unsigned int id); +JM_IX_DECL unsigned int RE_CALL re_get_syntax_type(wchar_t c); + +#ifdef RE_LOCALE_CPP +__JM_STD::string RE_CALL re_get_error_str(unsigned int id, const __JM_STD::locale&); +#endif + +// +// add some API's for character manipulation: +// +inline char RE_CALL re_tolower(char c +#ifdef RE_LOCALE_CPP +, const __JM_STD::locale& l +#endif +) +{ +#ifdef RE_LOCALE_CPP + return JM_USE_FACET(l, __JM_STD::ctype<char>).tolower(c); +#else + return re_lower_case_map[(unsigned char)c]; +#endif +} + +#ifndef JM_NO_WCSTRING +inline wchar_t RE_CALL re_tolower(wchar_t c +#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(c); +#else + return c < 256 ? re_lower_case_map_w[c] : re_wtolower(c); +#endif +} +#endif + +inline bool RE_CALL re_istype(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 re_class_map[(unsigned char)c] & f; +#endif +} + +#ifndef JM_NO_WCSTRING +inline bool RE_CALL re_istype(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; + return false; +#else + return c < 256 ? re_unicode_classes[c] & f : re_iswclass(c, f); +#endif +} +#endif + +inline char RE_CALL re_get_zero(char +#ifdef RE_LOCALE_CPP +, const __JM_STD::locale& l +#endif +) +{ +#ifdef RE_LOCALE_CPP + return JM_USE_FACET(l, regfacet<char>).zero(); +#else + return re_zero; +#endif +} + +#ifndef JM_NO_WCSTRING +inline wchar_t RE_CALL re_get_zero(wchar_t +#ifdef RE_LOCALE_CPP +, const __JM_STD::locale& l +#endif +) +{ +#ifdef RE_LOCALE_CPP + return JM_USE_FACET(l, regfacet<wchar_t>).zero(); +#else + return re_zero_w; +#endif +} +#endif + +inline char RE_CALL re_get_ten(char +#ifdef RE_LOCALE_CPP +, const __JM_STD::locale& l +#endif +) +{ +#ifdef RE_LOCALE_CPP + return JM_USE_FACET(l, regfacet<char>).ten(); +#else + return re_ten; +#endif +} + +#ifndef JM_NO_WCSTRING +inline wchar_t RE_CALL re_get_ten(wchar_t +#ifdef RE_LOCALE_CPP +, const __JM_STD::locale& l +#endif +) +{ +#ifdef RE_LOCALE_CPP + return JM_USE_FACET(l, regfacet<wchar_t>).ten(); +#else + return re_ten_w; +#endif +} +#endif + +// +// re_toi: +// convert a single character to the int it represents: +// +template <class charT> +unsigned int RE_CALL re_toi(charT c +#ifdef RE_LOCALE_CPP +, const __JM_STD::locale& l +#endif +) +{ + if(re_istype(c, char_class_digit MAYBE_PASS_LOCALE(l))) + return c - re_get_zero(c MAYBE_PASS_LOCALE(l)); + if(re_istype(c, char_class_xdigit MAYBE_PASS_LOCALE(l))) + return 10 + re_tolower(c MAYBE_PASS_LOCALE(l)) - re_tolower(re_get_ten(c MAYBE_PASS_LOCALE(l)) MAYBE_PASS_LOCALE(l)); + return -1; // error!! +} + +// +// re_toi: +// parse an int from the input string +// update first to point to end of int +// on exit. +// +template <class charT> +unsigned int RE_CALL re_toi(const charT*& first, const charT*const last, int radix +#ifdef RE_LOCALE_CPP +, const __JM_STD::locale& l +#endif +) +{ + unsigned int maxval; + if(radix < 0) + { + // if radix is less than zero, then restrict + // return value to charT. NB assumes sizeof(charT) <= sizeof(int) + radix *= -1; + maxval = 1 << (sizeof(charT) * CHAR_BIT - 1); + maxval /= radix; + maxval *= 2; + maxval -= 1; + } + else + { + maxval = (unsigned int)-1; + maxval /= radix; + } + + unsigned int result = 0; + unsigned int type = (radix > 10) ? char_class_xdigit : char_class_digit; + while((first != last) && re_istype(*first, type MAYBE_PASS_LOCALE(l)) && (result <= maxval)) + { + result *= radix; + result += re_toi(*first MAYBE_PASS_LOCALE(l)); + ++first; + } + return result; +} + + +#ifndef JM_NO_WCSTRING +JM_IX_DECL bool RE_CALL re_is_combining(wchar_t c); +#endif + +extern const char* regex_message_catalogue; + +JM_IX_DECL const char* RE_CALL get_global_locale_name(int); + + +JM_END_NAMESPACE + +#endif + diff --git a/utils/tfstats/regexp/include/jm/re_raw.h b/utils/tfstats/regexp/include/jm/re_raw.h new file mode 100644 index 0000000..e270097 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_raw.h @@ -0,0 +1,185 @@ +//========= 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 re_raw.h + * VERSION 2.12 + */ + +#ifndef RE_RAW_H +#define RE_RAW_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +JM_NAMESPACE(__JM) + +union padding +{ + void* p; + unsigned int i; +}; + + +// +// class raw_storage +// basically this is a simplified vector<unsigned char> +// this is used by reg_expression for expression storage +// + +template <class Allocator> +class raw_storage +{ +public: + typedef Allocator alloc_type; + typedef typename REBIND_TYPE(unsigned char, alloc_type)::size_type size_type; + typedef JM_MAYBE_TYPENAME REBIND_TYPE(unsigned char, alloc_type) alloc_inst_type; + typedef typename REBIND_TYPE(unsigned char, alloc_type)::pointer pointer; +private: + // + // empty member optimisation: + struct alloc_data : public alloc_inst_type + { + pointer last; + alloc_data(const Allocator& a) : alloc_inst_type(a){} + } alloc_inst; + pointer start, end; +public: + + raw_storage(const Allocator& a = Allocator()); + raw_storage(size_type n, const Allocator& a = Allocator()); + + ~raw_storage() + { + alloc_inst.deallocate(start, (alloc_inst.last - start)); + } + + void RE_CALL resize(size_type n); + + void* RE_CALL extend(size_type n) + { + if(size_type(alloc_inst.last - end) < n) + resize(n + (end - start)); + register void* result = end; + end += n; + return result; + } + + void* RE_CALL insert(size_type pos, size_type n); + + size_type RE_CALL size() + { + return end - start; + } + + size_type RE_CALL capacity() + { + return alloc_inst.last - start; + } + + void* RE_CALL data()const + { + return start; + } + + size_type RE_CALL index(void* ptr) + { + return (unsigned char*)ptr - start; + } + + void RE_CALL clear() + { + end = start; + } + + void RE_CALL align() + { + // move end up to a boundary: + end = (unsigned char*)((long)(end + sizeof(padding) - 1) & ~((long)sizeof(padding) - 1)); + } + + Allocator RE_CALL allocator()const; +}; + +template <class Allocator> +CONSTRUCTOR_INLINE raw_storage<Allocator>::raw_storage(const Allocator& a) + : alloc_inst(a) +{ + start = end = alloc_inst.allocate(1024); + alloc_inst.last = start + 1024; +} + +template <class Allocator> +CONSTRUCTOR_INLINE raw_storage<Allocator>::raw_storage(size_type n, const Allocator& a) + : alloc_inst(a) +{ + start = end = alloc_inst.allocate(n); + alloc_inst.last = start + n; +} + +template <class Allocator> +Allocator RE_CALL raw_storage<Allocator>::allocator()const +{ + return alloc_inst; +} + +template <class Allocator> +void RE_CALL raw_storage<Allocator>::resize(size_type n) +{ + register size_type newsize = (alloc_inst.last - start) * 2; + register size_type datasize = end - start; + if(newsize < n) + newsize = n; + // extend newsize to WORD/DWORD boundary: + newsize = (newsize + (sizeof(padding) - 1)) & ~(sizeof(padding) - 1); + + // allocate and copy data: + register unsigned char* ptr = alloc_inst.allocate(newsize); + memcpy(ptr, start, datasize); + + // get rid of old buffer: + alloc_inst.deallocate(start, (alloc_inst.last - start)); + + // and set up pointers: + start = ptr; + end = ptr + datasize; + alloc_inst.last = ptr + newsize; +} + +template <class Allocator> +void* RE_CALL raw_storage<Allocator>::insert(size_type pos, size_type n) +{ + jm_assert(pos <= size_type(end - start)); + if(size_type(alloc_inst.last - end) < n) + resize(n + (end - start)); + register void* result = start + pos; + memmove(start + pos + n, start + pos, (end - start) - pos); + end += n; + return result; +} + +JM_END_NAMESPACE + +#endif + + diff --git a/utils/tfstats/regexp/include/jm/re_str.h b/utils/tfstats/regexp/include/jm/re_str.h new file mode 100644 index 0000000..387342b --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_str.h @@ -0,0 +1,301 @@ +//========= 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 re_str.h + * VERSION 2.12 + * This is an internal header file, do not include directly. + * String support and helper functions, for regular + * expression library. + */ + +#ifndef RE_STR_H +#define RE_STR_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +#include <string.h> + +JM_NAMESPACE(__JM) + +// +// start by defining some template function aliases for C API functions: +// + +template <class charT> +size_t RE_CALL re_strlen(const charT *s) +{ + size_t len = 0; + while(*s) + { + ++s; + ++len; + } + return len; +} + +template <class charT> +int RE_CALL re_strcmp(const charT *s1, const charT *s2) +{ + while(*s1 && *s2) + { + if(*s1 != *s2) + return *s1 - *s2; + ++s1; + ++s2; + } + return *s1 - *s2; +} + +template <class charT> +charT* RE_CALL re_strcpy(charT *s1, const charT *s2) +{ + charT* base = s1; + while(*s2) + { + *s1 = *s2; + ++s1; + ++s2; + } + *s1 = *s2; + return base; +} + +template <class charT> +unsigned int RE_CALL re_strwiden(charT *s1, unsigned int len, const char *s2) +{ + unsigned int result = 1 + re_strlen(s2); + if(result > len) + return result; + while(*s2) + { + *s1 = (unsigned char)*s2; + ++s2; + ++s1; + } + *s1 = (unsigned char)*s2; + return result; +} + +template <class charT> +unsigned int RE_CALL re_strnarrow(char *s1, unsigned int len, const charT *s2) +{ + unsigned int result = 1 + re_strlen(s2); + if(result > len) + return result; + while(*s2) + { + *s1 = (char)(unsigned char)*s2; + ++s2; + ++s1; + } + *s1 = (char)(unsigned char)*s2; + return result; +} + +inline size_t RE_CALL re_strlen(const char *s) +{ + return strlen(s); +} + +inline int RE_CALL re_strcmp(const char *s1, const char *s2) +{ + return strcmp(s1, s2); +} + +inline char* RE_CALL re_strcpy(char *s1, const char *s2) +{ + return strcpy(s1, s2); +} + +#ifndef JM_NO_WCSTRING + +inline size_t RE_CALL re_strlen(const wchar_t *s) +{ + return wcslen(s); +} + +inline int RE_CALL re_strcmp(const wchar_t *s1, const wchar_t *s2) +{ + return wcscmp(s1, s2); +} + +inline wchar_t* RE_CALL re_strcpy(wchar_t *s1, const wchar_t *s2) +{ + return wcscpy(s1, s2); +} + +#endif + +#if !defined(JM_NO_WCSTRING) || defined(JM_PLATFORM_W32) + +JM_IX_DECL unsigned int RE_CALL _re_strnarrow(char *s1, unsigned int len, const wchar_t *s2); +JM_IX_DECL unsigned int RE_CALL _re_strwiden(wchar_t *s1, unsigned int len, const char *s2); + + +inline unsigned int RE_CALL re_strnarrow(char *s1, unsigned int len, const wchar_t *s2) +{ + return _re_strnarrow(s1, len, s2); +} + +inline unsigned int RE_CALL re_strwiden(wchar_t *s1, unsigned int len, const char *s2) +{ + return _re_strwiden(s1, len, s2); +} + +#endif + +template <class charT> +charT* RE_CALL re_strdup(const charT* p) +{ + charT* buf = new charT[re_strlen(p) + 1]; + re_strcpy(buf, p); + return buf; +} + +template <class charT> +charT* RE_CALL re_strdup(const charT* p1, const charT* p2) +{ + unsigned int len = p2 - p1 + 1; + charT* buf = new charT[len]; + memcpy(buf, p1, (len - 1) * sizeof(charT)); + *(buf + len - 1) = 0; + return buf; +} + +template <class charT> +inline void RE_CALL re_strfree(charT* p) +{ + delete[] p; +} + +template <class charT> +class re_str +{ + charT* buf; +public: + re_str() + { + charT c = 0; + buf = re_strdup(&c); + } + ~re_str(); + re_str(const re_str& other); + re_str(const charT* p1); + re_str(const charT* p1, const charT* p2); + re_str(charT c); + + re_str& RE_CALL operator=(const re_str& other) + { + re_strfree(buf); + buf = re_strdup(other.buf); + return *this; + } + re_str& RE_CALL operator=(const charT* p) + { + re_strfree(buf); + buf = re_strdup(p); + return *this; + } + re_str& RE_CALL operator=(charT c) + { + re_strfree(buf); + buf = re_strdup(&c, &c+1); + return *this; + } + const charT* RE_CALL c_str()const { return buf; } + RE_CALL operator const charT*()const { return buf; } + unsigned int RE_CALL size()const { return re_strlen(buf); } + charT& RE_CALL operator[](unsigned int i) { return buf[i]; } + charT RE_CALL operator[](unsigned int i)const { return buf[i]; } + + bool RE_CALL operator==(const re_str& other)const { return re_strcmp(buf, other.buf) == 0; } + bool RE_CALL operator==(const charT* p)const { return re_strcmp(buf, p) == 0; } + bool RE_CALL operator==(const charT c)const + { + if((*buf) && (*buf == c) && (*(buf+1) == 0)) + return true; + return false; + } + bool RE_CALL operator!=(const re_str& other)const { return re_strcmp(buf, other.buf) != 0; } + bool RE_CALL operator!=(const charT* p)const { return re_strcmp(buf, p) != 0; } + bool RE_CALL operator!=(const charT c)const { return !(*this == c); } + + bool RE_CALL operator<(const re_str& other)const { return re_strcmp(buf, other.buf) < 0; } + bool RE_CALL operator<=(const re_str& other)const { return re_strcmp(buf, other.buf) <= 0; } + bool RE_CALL operator>(const re_str& other)const { return re_strcmp(buf, other.buf) > 0; } + bool RE_CALL operator>=(const re_str& other)const { return re_strcmp(buf, other.buf) >= 0; } + + bool RE_CALL operator<(const charT* p)const { return re_strcmp(buf, p) < 0; } + bool RE_CALL operator<=(const charT* p)const { return re_strcmp(buf, p) <= 0; } + bool RE_CALL operator>(const charT* p)const { return re_strcmp(buf, p) > 0; } + bool RE_CALL operator>=(const charT* p)const { return re_strcmp(buf, p) >= 0; } +}; + +template <class charT> +CONSTRUCTOR_INLINE re_str<charT>::~re_str() { re_strfree(buf); } + +template <class charT> +CONSTRUCTOR_INLINE re_str<charT>::re_str(const re_str<charT>& other) { buf = re_strdup(other.buf); } + +template <class charT> +CONSTRUCTOR_INLINE re_str<charT>::re_str(const charT* p1) { buf = re_strdup(p1); } + +template <class charT> +CONSTRUCTOR_INLINE re_str<charT>::re_str(const charT* p1, const charT* p2) { buf = re_strdup(p1, p2); } + +template <class charT> +CONSTRUCTOR_INLINE re_str<charT>::re_str(charT c) { buf = re_strdup(&c, &c+1); } + + +#ifndef JM_NO_WCSTRING +JM_IX_DECL void RE_CALL re_transform(re_str<wchar_t>& out, const re_str<wchar_t>& in); +#endif +JM_IX_DECL void RE_CALL re_transform(re_str<char>& out, const re_str<char>& in); + +template <class charT> +void RE_CALL re_trunc_primary(re_str<charT>& s) +{ + for(unsigned int i = 0; i < s.size(); ++i) + { + if(s[i] <= 1) + { + s[i] = 0; + break; + } + } +} + +#ifdef RE_LOCALE_C +#define TRANSFORM_ERROR (size_t)-1 +#else +#define TRANSFORM_ERROR 0 +#endif + + +JM_END_NAMESPACE + +#endif + + diff --git a/utils/tfstats/regexp/include/jm/re_thrd.h b/utils/tfstats/regexp/include/jm/re_thrd.h new file mode 100644 index 0000000..c0fc7b7 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/re_thrd.h @@ -0,0 +1,169 @@ +//========= 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 re_thrd.h + * VERSION 2.12 + * Thread synch helper functions, for regular + * expression library. + */ + +#ifndef RE_THRD_H +#define RE_THRD_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +#if defined(JM_PLATFORM_W32) && defined(JM_THREADS) +//#include <windows.h> +#endif + +#if !defined(JM_PLATFORM_W32) && defined(JM_THREADS) +#include <pthread.h> +#endif + + +JM_NAMESPACE(__JM) + +void RE_CALL re_init_threads(); +void RE_CALL re_free_threads(); + +#ifdef JM_THREADS + +#ifndef JM_PLATFORM_W32 + +typedef pthread_mutex_t CRITICAL_SECTION; + +inline void RE_CALL InitializeCriticalSection(CRITICAL_SECTION* ps) +{ + pthread_mutex_init(ps, NULL); +} + +inline void RE_CALL DeleteCriticalSection(CRITICAL_SECTION* ps) +{ + pthread_mutex_destroy(ps); +} + +inline void RE_CALL EnterCriticalSection(CRITICAL_SECTION* ps) +{ + pthread_mutex_lock(ps); +} + +inline void RE_CALL LeaveCriticalSection(CRITICAL_SECTION* ps) +{ + pthread_mutex_unlock(ps); +} + +#endif + +template <class Lock> +class lock_guard +{ + typedef Lock lock_type; +public: + lock_guard(lock_type& m, bool aq = true) + : mut(m), owned(false){ acquire(aq); } + + ~lock_guard() + { acquire(false); } + + void RE_CALL acquire(bool aq = true, DWORD timeout = INFINITE) + { + if(aq && !owned) + { + mut.acquire(true, timeout); + owned = true; + } + else if(!aq && owned) + { + mut.acquire(false); + owned = false; + } + } +private: + lock_type& mut; + bool owned; +}; + + +class critical_section +{ +public: + critical_section() + { InitializeCriticalSection(&hmutex);} + + critical_section(const critical_section&) + { InitializeCriticalSection(&hmutex);} + + const critical_section& RE_CALL operator=(const critical_section&) + {return *this;} + + ~critical_section() + {DeleteCriticalSection(&hmutex);} + +private: + + void RE_CALL acquire(bool aq, DWORD unused = INFINITE) + { if(aq) EnterCriticalSection(&hmutex); + else LeaveCriticalSection(&hmutex); + } + + CRITICAL_SECTION hmutex; + +public: + typedef lock_guard<critical_section> ro_guard; + typedef lock_guard<critical_section> rw_guard; + + friend lock_guard<critical_section>; +}; + +inline bool RE_CALL operator==(const critical_section&, const critical_section&) +{ + return false; +} + +inline bool RE_CALL operator<(const critical_section&, const critical_section&) +{ + return true; +} + +typedef lock_guard<critical_section> cs_guard; + +JM_IX_DECL extern critical_section* p_re_lock; +JM_IX_DECL extern unsigned int re_lock_count; + +#define JM_GUARD(inst) __JM::critical_section::rw_guard g(inst); + +#else // JM_THREADS + +#define JM_GUARD(inst) + +#endif // JM_THREADS + +JM_END_NAMESPACE + +#endif // sentry + + + + diff --git a/utils/tfstats/regexp/include/jm/regcomp.h b/utils/tfstats/regexp/include/jm/regcomp.h new file mode 100644 index 0000000..0065bba --- /dev/null +++ b/utils/tfstats/regexp/include/jm/regcomp.h @@ -0,0 +1,1888 @@ +//========= 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 regcomp.h + * VERSION 2.12 + * This is an internal header file, do not include directly + */ + +JM_NAMESPACE(__JM) + +template <class traits> +struct kmp_translator +{ + typedef typename traits::char_type char_type; + bool icase; + kmp_translator(bool c) : icase(c) {} + char_type operator()(char_type c +#ifdef RE_LOCALE_CPP + , const __JM_STD::locale& l +#endif + ) + { + return traits::translate(c, icase MAYBE_PASS_LOCALE(l)); + } +}; + +#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, class Allocator> +inline bool RE_CALL reg_expression<charT, traits, Allocator>::can_start(charT c, const unsigned char* __map, unsigned char mask, const __wide_type&) +{ + if((traits_size_type)(traits_uchar_type)c >= 256) + return true; + return JM_MAKE_BOOL(__map[(traits_uchar_type)c] & mask); +} + +template <class charT, class traits, class Allocator> +inline bool RE_CALL reg_expression<charT, traits, Allocator>::can_start(charT c, const unsigned char* __map, unsigned char mask, const __narrow_type&) +{ + return JM_MAKE_BOOL(__map[(traits_uchar_type)c] & mask); +} + +template <class charT, class traits, class Allocator> +CONSTRUCTOR_INLINE reg_expression<charT, traits, Allocator>::reg_expression(const Allocator& a) + : regbase(), data(a), pkmp(0) +{ +} + +template <class charT, class traits, class Allocator> +CONSTRUCTOR_INLINE reg_expression<charT, traits, Allocator>::reg_expression(const charT* p, jm_uintfast32_t f, const Allocator& a) + : data(a), pkmp(0) +{ + set_expression(p, f); +} + +template <class charT, class traits, class Allocator> +CONSTRUCTOR_INLINE reg_expression<charT, traits, Allocator>::reg_expression(const charT* p1, const charT* p2, jm_uintfast32_t f, const Allocator& a) + : data(a), pkmp(0) +{ + set_expression(p1, p2, f); +} + +template <class charT, class traits, class Allocator> +CONSTRUCTOR_INLINE reg_expression<charT, traits, Allocator>::reg_expression(const charT* p, size_type len, jm_uintfast32_t f, const Allocator& a) + : data(a), pkmp(0) +{ + set_expression(p, p + len, f); +} + +template <class charT, class traits, class Allocator> +reg_expression<charT, traits, Allocator>::reg_expression(const reg_expression<charT, traits, Allocator>& e) + : regbase(e), data(e.allocator()), pkmp(0) +{ + // + // we do a deep copy only if e is a valid expression, otherwise fail. + // + //_flags = 0; + //fail(e.error_code()); + if(error_code() == 0) + set_expression(e.expression(), e.flags()); +} + +template <class charT, class traits, class Allocator> +reg_expression<charT, traits, Allocator>::~reg_expression() +{ + if(pkmp) + kmp_free(pkmp, data.allocator()); +} + +template <class charT, class traits, class Allocator> +reg_expression<charT, traits, Allocator>& RE_CALL reg_expression<charT, traits, Allocator>::operator=(const reg_expression<charT, traits, Allocator>& e) +{ + // + // we do a deep copy only if e is a valid expression, otherwise fail. + // + if(this == &e) return *this; + _flags = 0; + fail(e.error_code()); + if(error_code() == 0) + set_expression(e.expression(), e.flags()); + return *this; +} + +template <class charT, class traits, class Allocator> +inline bool RE_CALL reg_expression<charT, traits, Allocator>::operator==(const reg_expression<charT, traits, Allocator>& e) +{ + return (_flags == e.flags()) && (re_strcmp(expression(), e.expression()) == 0); +} + +template <class charT, class traits, class Allocator> +bool RE_CALL reg_expression<charT, traits, Allocator>::operator<(const reg_expression<charT, traits, Allocator>& e) +{ + int i = re_strcmp(expression(), e.expression()); + if(i == 0) + return _flags < e.flags(); + return i < 0; +} + +template <class charT, class traits, class Allocator> +Allocator RE_CALL reg_expression<charT, traits, Allocator>::allocator()const +{ + return data.allocator(); +} + +template <class charT, class traits, class Allocator> +unsigned int RE_CALL reg_expression<charT, traits, Allocator>::parse_inner_set(const charT*& first, const charT* last) +{ + // + // we have an inner [...] construct + // + jm_assert(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*first MAYBE_PASS_LOCALE(locale_inst)) == syntax_open_set); + const charT* base = first; + while( (first != last) + && (traits_type::syntax_type((traits_size_type)(traits_uchar_type)*first MAYBE_PASS_LOCALE(locale_inst)) != syntax_close_set) ) + ++first; + if(first == last) + return 0; + ++first; + if((first-base) < 5) + return 0; + if(*(base+1) != *(first-2)) + return 0; + unsigned int result = traits_type::syntax_type((traits_size_type)(traits_uchar_type)*(base+1) MAYBE_PASS_LOCALE(locale_inst)); + if((result == syntax_colon) && ((first-base) == 5)) + { + return traits_type::syntax_type((traits_size_type)(traits_uchar_type)*(base+2) MAYBE_PASS_LOCALE(locale_inst)); + } + return ((result == syntax_colon) || (result == syntax_dot) || (result == syntax_equal)) ? result : 0; +} + + +template <class charT, class traits, class Allocator> +bool RE_CALL reg_expression<charT, traits, Allocator>::skip_space(const charT*& first, const charT* last) +{ + // + // returns true if we get to last: + // + while((first != last) && (traits_type::is_class(*first, char_class_space MAYBE_PASS_LOCALE(locale_inst)) == true)) + { + ++first; + } + return first == last; +} + +template <class charT, class traits, class Allocator> +void RE_CALL reg_expression<charT, traits, Allocator>::parse_range(const charT*& ptr, const charT* end, unsigned& min, unsigned& max) +{ + // + // we have {x} or {x,} or {x,y} NB no spaces inside braces + // anything else is illegal + // On input ptr points to "{" + // + ++ptr; + if(skip_space(ptr, end)) + { + fail(REG_EBRACE); + return; + } + if(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*ptr MAYBE_PASS_LOCALE(locale_inst)) != syntax_digit) + { + fail(REG_BADBR); + return; + } + min = traits_type::toi(ptr, end, 10 MAYBE_PASS_LOCALE(locale_inst)); + if(skip_space(ptr, end)) + { + fail(REG_EBRACE); + return; + } + if(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*ptr MAYBE_PASS_LOCALE(locale_inst)) == syntax_comma) + { + //we have a second interval: + ++ptr; + if(skip_space(ptr, end)) + { + fail(REG_EBRACE); + return; + } + if(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*ptr MAYBE_PASS_LOCALE(locale_inst)) == syntax_digit) + max = traits_type::toi(ptr, end, 10 MAYBE_PASS_LOCALE(locale_inst)); + else + max = (unsigned)-1; + } + else + max = min; + + // validate input: + if(skip_space(ptr, end)) + { + fail(REG_EBRACE); + return; + } + if(max < min) + { + fail(REG_ERANGE); + return; + } + if(_flags & bk_braces) + { + if(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*ptr MAYBE_PASS_LOCALE(locale_inst)) != syntax_slash) + { + fail(REG_BADBR); + return; + } + else + { + // back\ is OK now check the } + ++ptr; + if((ptr == end) || (traits_type::syntax_type((traits_size_type)(traits_uchar_type)*ptr MAYBE_PASS_LOCALE(locale_inst)) != syntax_close_brace)) + { + fail(REG_BADBR); + return; + } + } + } + else if(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*ptr MAYBE_PASS_LOCALE(locale_inst)) != syntax_close_brace) + { + fail(REG_BADBR); + return; + } +} + +template <class charT, class traits, class Allocator> +charT RE_CALL reg_expression<charT, traits, Allocator>::parse_escape(const charT*& first, const charT* last) +{ + charT c; + switch(traits_type::syntax_type(*first MAYBE_PASS_LOCALE(locale_inst))) + { + case syntax_a: + c = '\a'; + ++first; + break; + case syntax_f: + c = '\f'; + ++first; + break; + case syntax_n: + c = '\n'; + ++first; + break; + case syntax_r: + c = '\r'; + ++first; + break; + case syntax_t: + c = '\t'; + ++first; + break; + case syntax_v: + c = '\v'; + ++first; + break; + case syntax_x: + ++first; + if(first == last) + { + fail(REG_EESCAPE); + break; + } + // maybe have \x{ddd} + if(traits_type::syntax_type(*first MAYBE_PASS_LOCALE(locale_inst)) == syntax_open_brace) + { + ++first; + if(first == last) + { + fail(REG_EESCAPE); + break; + } + if(traits_type::is_class(*first, char_class_xdigit MAYBE_PASS_LOCALE(locale_inst)) == false) + { + fail(REG_BADBR); + break; + } + c = (charT)traits_type::toi(first, last, -16 MAYBE_PASS_LOCALE(locale_inst)); + if((first == last) || (traits_type::syntax_type(*first MAYBE_PASS_LOCALE(locale_inst)) != syntax_close_brace)) + { + fail(REG_BADBR); + } + ++first; + break; + } + else + { + if(traits_type::is_class(*first, char_class_xdigit MAYBE_PASS_LOCALE(locale_inst)) == false) + { + fail(REG_BADBR); + break; + } + c = (charT)traits_type::toi(first, last, -16 MAYBE_PASS_LOCALE(locale_inst)); + } + break; + case syntax_c: + ++first; + if(first == last) + { + fail(REG_EESCAPE); + break; + } + if(((traits_uchar_type)(*first) < (traits_uchar_type)'@') + || ((traits_uchar_type)(*first) > (traits_uchar_type)127) ) + { + fail(REG_EESCAPE); + return (charT)0; + } + c = (charT)((traits_uchar_type)(*first) - (traits_uchar_type)'@'); + ++first; + break; + case syntax_e: + c = (charT)27; + ++first; + break; + case syntax_digit: + c = (charT)traits_type::toi(first, last, -8 MAYBE_PASS_LOCALE(locale_inst)); + break; + default: + c = *first; + ++first; + } + return c; +} + +template <class charT, class traits, class Allocator> +void RE_CALL reg_expression<charT, traits, Allocator>::compile_maps() +{ + re_syntax_base* record = (re_syntax_base*)data.data(); + // always compile the first __map: + memset(startmap, 0, 256); + record->can_be_null = 0; + compile_map(record, startmap, NULL, mask_all); + + while(record->type != syntax_element_match) + { + if((record->type == syntax_element_alt) || (record->type == syntax_element_rep)) + { + memset(&(((re_jump*)record)->__map), 0, 256); + record->can_be_null = 0; + compile_map(record->next.p, ((re_jump*)record)->__map, &(record->can_be_null), mask_take, ((re_jump*)record)->alt.p); + compile_map(((re_jump*)record)->alt.p, ((re_jump*)record)->__map, &(record->can_be_null), mask_skip); + } + else + { + record->can_be_null = 0; + compile_map(record, NULL, &(record->can_be_null), mask_all); + } + record = record->next.p; + } + record->can_be_null = mask_all; +} + +template <class charT, class traits_type, class Allocator> +bool RE_CALL re_maybe_set_member(charT c, + re_set_long* set, + const reg_expression<charT, traits_type, Allocator>& e) +{ + const charT* p = (const charT*)(set+1); + bool icase = e.flags() & regbase::icase; + charT col = traits_type::translate(c, icase MAYBE_PASS_LOCALE(e.locale())); + for(unsigned int i = 0; i < set->csingles; ++i) + { + if(col == *p) + return set->isnot ? false : true; + + while(*p)++p; + ++p; // skip null + } + return set->isnot ? true : false; +} + +template <class charT, class traits, class Allocator> +bool RE_CALL reg_expression<charT, traits, Allocator>::probe_start( + re_syntax_base* node, charT cc, re_syntax_base* terminal) const +{ + unsigned int c; + + switch(node->type) + { + case syntax_element_startmark: + case syntax_element_endmark: + case syntax_element_start_line: + case syntax_element_word_boundary: + case syntax_element_buffer_start: + case syntax_element_restart_continue: + // doesn't tell us anything about the next character, so: + return probe_start(node->next.p, cc, terminal); + case syntax_element_literal: + // only the first character of the literal can match: + // note these have already been translated: + if(*(charT*)(((re_literal*)node)+1) == traits_type::translate(cc, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst))) + return true; + return false; + case syntax_element_end_line: + // next character (if there is one!) must be a newline: + if(traits_type::is_separator(traits_type::translate(cc, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst)))) + return true; + return false; + case syntax_element_wild: + return true; + case syntax_element_match: + return true; + case syntax_element_within_word: + case syntax_element_word_start: + return traits_type::is_class(traits_type::translate(cc, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst)), char_class_word MAYBE_PASS_LOCALE(locale_inst)); + case syntax_element_word_end: + // what follows must not be a word character, + return traits_type::is_class(traits_type::translate(cc, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst)), char_class_word MAYBE_PASS_LOCALE(locale_inst)) ? false : true; + case syntax_element_buffer_end: + // we can be null, nothing must follow, + // NB we assume that this is followed by + // syntax_element_match, if its not then we can + // never match anything anyway!! + return false; + case syntax_element_soft_buffer_end: + // we can be null, only newlines must follow, + // NB we assume that this is followed by + // syntax_element_match, if its not then we can + // never match anything anyway!! + return traits_type::is_separator(traits_type::translate(cc, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst))); + case syntax_element_backref: + // there's no easy way to determine this + // which is not to say it can't be done! + // for now: + return true; + case syntax_element_long_set: + // we can not be null, + // we need to add already translated values in the set + // to values in the __map + return re_maybe_set_member(cc, (re_set_long*)node, *this) || re_is_set_member((const charT*)&cc, (const charT*)(&cc+1), (re_set_long*)node, *this) != &cc; + case syntax_element_set: + // set all the elements that are set in corresponding set: + c = (traits_size_type)(traits_uchar_type)traits_type::translate(cc, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst)); + return ((re_set*)node)->__map[c] != 0; + case syntax_element_jump: + if(((re_jump*)node)->alt.p < node) + { + // backwards jump, + // caused only by end of repeat section, we'll treat this + // the same as a match, because the sub-expression has matched. + // this is only caused by NULL repeats as in "(a*)*" or "(\<)*" + // these are really nonsensence and make the matching code much + // harder, it would be nice to get rid of them altogether. + if(node->next.p == terminal) + return true; + else + return probe_start(((re_jump*)node)->alt.p, cc, terminal); + } + else + // take the jump and compile: + return probe_start(((re_jump*)node)->alt.p, cc, terminal); + case syntax_element_alt: + // we need to take the OR of the two alternatives: + return probe_start(((re_jump*)node)->alt.p, cc, terminal) || probe_start(node->next.p, cc, terminal); + case syntax_element_rep: + // we need to take the OR of the two alternatives + if(((re_repeat*)node)->min == 0) + return probe_start(node->next.p, cc, ((re_jump*)node)->alt.p) || probe_start(((re_jump*)node)->alt.p, cc, terminal); + else + return probe_start(node->next.p, cc, ((re_jump*)node)->alt.p); + case syntax_element_combining: + return !traits_type::is_combining(traits_type::translate(cc, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst))); + } + return false; +} + +template <class charT, class traits, class Allocator> +bool RE_CALL reg_expression<charT, traits, Allocator>::probe_start_null(re_syntax_base* node, re_syntax_base* terminal)const +{ + switch(node->type) + { + case syntax_element_startmark: + case syntax_element_endmark: + case syntax_element_start_line: + case syntax_element_word_boundary: + case syntax_element_buffer_start: + case syntax_element_restart_continue: + case syntax_element_end_line: + case syntax_element_word_end: + // doesn't tell us anything about the next character, so: + return probe_start_null(node->next.p, terminal); + case syntax_element_match: + case syntax_element_buffer_end: + case syntax_element_soft_buffer_end: + case syntax_element_backref: + return true; + case syntax_element_jump: + if(((re_jump*)node)->alt.p < node) + { + // backwards jump, + // caused only by end of repeat section, we'll treat this + // the same as a match, because the sub-expression has matched. + // this is only caused by NULL repeats as in "(a*)*" or "(\<)*" + // these are really nonsensence and make the matching code much + // harder, it would be nice to get rid of them altogether. + if(node->next.p == terminal) + return true; + else + return probe_start_null(((re_jump*)node)->alt.p, terminal); + } + else + // take the jump and compile: + return probe_start_null(((re_jump*)node)->alt.p, terminal); + case syntax_element_alt: + // we need to take the OR of the two alternatives: + return probe_start_null(((re_jump*)node)->alt.p, terminal) || probe_start_null(node->next.p, terminal); + case syntax_element_rep: + // only need to consider skipping the repeat: + return probe_start_null(((re_jump*)node)->alt.p, terminal); + } + return false; +} + +template <class charT, class traits, class Allocator> +void RE_CALL reg_expression<charT, traits, Allocator>::compile_map( + re_syntax_base* node, unsigned char* __map, + unsigned int* pnull, unsigned char mask, re_syntax_base* terminal)const +{ + if(__map) + { + for(unsigned int i = 0; i < 256; ++i) + { + if(probe_start(node, (charT)i, terminal)) + __map[i] |= mask; + } + } + if(pnull && probe_start_null(node, terminal)) + *pnull |= mask; +} + +template <class charT, class traits, class Allocator> +void RE_CALL reg_expression<charT, traits, Allocator>::move_offsets(re_syntax_base* j, unsigned size) +{ + // move all offsets starting with j->link forward by size + // called after an insert: + j = (re_syntax_base*)((const char*)data.data() + j->next.i); + while(true) + { + switch(j->type) + { + case syntax_element_rep: + ((re_jump*)j)->alt.i += size; + j->next.i += size; + break; + case syntax_element_jump: + case syntax_element_alt: + ((re_jump*)j)->alt.i += size; + j->next.i += size; + break; + default: + j->next.i += size; + break; + } + if(j->next.i == size) + break; + j = (re_syntax_base*)((const char*)data.data() + j->next.i); + } +} + +template <class charT, class traits, class Allocator> +re_syntax_base* RE_CALL reg_expression<charT, traits, Allocator>::compile_set_simple(re_syntax_base* dat, unsigned long cls, bool isnot) +{ + jstack<re_str<charT>, Allocator> singles(64, data.allocator()); + jstack<re_str<charT>, Allocator> ranges(64, data.allocator()); + jstack<jm_uintfast32_t, Allocator> classes(64, data.allocator()); + jstack<re_str<charT>, Allocator> equivalents(64, data.allocator()); + classes.push(cls); + if(dat) + { + data.align(); + dat->next.i = data.size(); + } + return compile_set_aux(singles, ranges, classes, equivalents, isnot, is_byte<charT>::width_type()); +} + +template <class charT, class traits, class Allocator> +re_syntax_base* RE_CALL reg_expression<charT, traits, Allocator>::compile_set(const charT*& first, const charT* last) +{ + jstack<re_str<charT>, Allocator> singles(64, data.allocator()); + jstack<re_str<charT>, Allocator> ranges(64, data.allocator()); + jstack<jm_uintfast32_t, Allocator> classes(64, data.allocator()); + jstack<re_str<charT>, Allocator> equivalents(64, data.allocator()); + bool has_digraphs = false; + jm_assert(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*first MAYBE_PASS_LOCALE(locale_inst)) == syntax_open_set); + ++first; + bool started = false; + bool done = false; + bool isnot = false; + + enum last_type + { + last_single, + last_none, + last_dash + }; + + unsigned l = last_none; + re_str<charT> s; + + while((first != last) && !done) + { + traits_size_type c = (traits_size_type)(traits_uchar_type)*first; + switch(traits_type::syntax_type(c MAYBE_PASS_LOCALE(locale_inst))) + { + case syntax_caret: + if(!started && !isnot) + { + isnot = true; + } + else + { + s = (charT)c; + goto char_set_literal; + } + break; + case syntax_open_set: + { + if((_flags & char_classes) == 0) + { + s = (charT)c; + goto char_set_literal; + } + // check to see if we really have a class: + const charT* base = first; + switch(parse_inner_set(first, last)) + { + case syntax_colon: + { + if(l == last_dash) + { + fail(REG_ERANGE); + return NULL; + } + jm_uintfast32_t id = traits_type::lookup_classname(base+2, first-2 MAYBE_PASS_LOCALE(locale_inst)); + if(_flags & regbase::icase) + { + if((id == char_class_upper) || (id == char_class_lower)) + { + id = char_class_alpha; + } + } + if(id == 0) + { + fail(REG_ECTYPE); + return NULL; + } + classes.push(id); + started = true; + l = last_none; + } + break; + case syntax_dot: + // + // we have a collating element [.collating-name.] + // + if(traits_type::lookup_collatename(s, base+2, first-2 MAYBE_PASS_LOCALE(locale_inst))) + { + --first; + if(s.size() > 1) + has_digraphs = true; + goto char_set_literal; + } + fail(REG_ECOLLATE); + return NULL; + case syntax_equal: + // + // we have an equivalence class [=collating-name=] + // + if(traits_type::lookup_collatename(s, base+2, first-2 MAYBE_PASS_LOCALE(locale_inst))) + { + unsigned i = 0; + while(s[i]) + { + s[i] = traits_type::translate(s[i], (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst)); + ++i; + } + re_str<charT> s2; + traits_type::transform_primary(s2, s MAYBE_PASS_LOCALE(locale_inst)); + equivalents.push(s2); + started = true; + l = last_none; + break; + } + fail(REG_ECOLLATE); + return NULL; + case syntax_left_word: + if((started == false) && (traits_type::syntax_type((traits_size_type)(traits_uchar_type)*first MAYBE_PASS_LOCALE(locale_inst)) == syntax_close_set)) + { + ++first; + return add_simple(0, syntax_element_word_start); + } + fail(REG_EBRACK); + return NULL; + case syntax_right_word: + if((started == false) && (traits_type::syntax_type((traits_size_type)(traits_uchar_type)*first MAYBE_PASS_LOCALE(locale_inst)) == syntax_close_set)) + { + ++first; + return add_simple(0, syntax_element_word_end); + } + fail(REG_EBRACK); + return NULL; + default: + if(started == false) + { + unsigned int t = traits_type::syntax_type((traits_size_type)(traits_uchar_type)*(base+1) MAYBE_PASS_LOCALE(locale_inst)); + if((t != syntax_colon) && (t != syntax_dot) && (t != syntax_equal)) + { + first = base; + s = (charT)c; + goto char_set_literal; + } + } + fail(REG_EBRACK); + return NULL; + } + if(first == last) + { + fail(REG_EBRACK); + return NULL; + } + continue; + } + case syntax_close_set: + if(started == false) + { + s = (charT)c; + goto char_set_literal; + } + done = true; + break; + case syntax_dash: + if(!started) + { + s = (charT)c; + goto char_set_literal; + } + ++first; + if(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*first MAYBE_PASS_LOCALE(locale_inst)) == syntax_close_set) + { + --first; + s = (charT)c; + goto char_set_literal; + } + if((singles.empty() == true) || (l != last_single)) + { + fail(REG_ERANGE); + return NULL; + } + ranges.push(singles.peek()); + if(singles.peek().size() <= 1) // leave digraphs and ligatures in place + singles.pop(); + l = last_dash; + continue; + case syntax_slash: + if(_flags & regbase::escape_in_lists) + { + ++first; + if(first == last) + continue; + switch(traits_type::syntax_type(*first MAYBE_PASS_LOCALE(locale_inst))) + { + case syntax_w: + if(l == last_dash) + { + fail(REG_ERANGE); + return NULL; + } + classes.push(char_class_word); + started = true; + l = last_none; + ++first; + continue; + case syntax_d: + if(l == last_dash) + { + fail(REG_ERANGE); + return NULL; + } + classes.push(char_class_digit); + started = true; + l = last_none; + ++first; + continue; + case syntax_s: + if(l == last_dash) + { + fail(REG_ERANGE); + return NULL; + } + classes.push(char_class_space); + started = true; + l = last_none; + ++first; + continue; + case syntax_l: + if(l == last_dash) + { + fail(REG_ERANGE); + return NULL; + } + classes.push(char_class_lower); + started = true; + l = last_none; + ++first; + continue; + case syntax_u: + if(l == last_dash) + { + fail(REG_ERANGE); + return NULL; + } + classes.push(char_class_upper); + started = true; + l = last_none; + ++first; + continue; + case syntax_W: + case syntax_D: + case syntax_S: + case syntax_U: + case syntax_L: + fail(REG_EESCAPE); + return NULL; + default: + c = parse_escape(first, last); + --first; + s = (charT)c; + goto char_set_literal; + } + } + else + { + s = (charT)c; + goto char_set_literal; + } + default: + s = (charT)c; + char_set_literal: + unsigned i = 0; + while(s[i]) + { + s[i] = traits_type::translate(s[i], (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst)); + ++i; + } + started = true; + if(l == last_dash) + { + ranges.push(s); + l = last_none; + if(s.size() > 1) // add ligatures to singles list as well + singles.push(s); + } + else + { + singles.push(s); + l = last_single; + } + } + ++first; + } + if(!done) + return NULL; + + re_syntax_base* result; + if(has_digraphs) + result = compile_set_aux(singles, ranges, classes, equivalents, isnot, __wide_type()); + else + result = compile_set_aux(singles, ranges, classes, equivalents, isnot, is_byte<charT>::width_type()); + #ifdef __BORLANDC__ + // delayed throw: + if((result == 0) && (_flags & regbase::use_except)) + fail(code); + #endif + return result; +} + +template <class charT, class traits, class Allocator> +re_syntax_base* RE_CALL reg_expression<charT, traits, Allocator>::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&) +{ + size_type base = data.size(); + data.extend(sizeof(re_set_long)); + unsigned int csingles = 0; + unsigned int cranges = 0; + jm_uintfast32_t cclasses = 0; + unsigned int cequivalents = 0; + bool nocollate_state = flags() & regbase::nocollate; + + while(singles.empty() == false) + { + ++csingles; + const re_str<charT>& s = singles.peek(); + unsigned len = (re_strlen(s.c_str()) + 1) * sizeof(charT); + memcpy((charT*)data.extend(len), s.c_str(), len); + //*(charT*)data.extend(sizeof(charT)) = charT(singles.peek()); + singles.pop(); + } + while(ranges.empty() == false) + { + re_str<charT> c1, c2; + if(nocollate_state) + c1 = ranges.peek(); + else + traits_type::transform(c1, ranges.peek() MAYBE_PASS_LOCALE(locale_inst)); + ranges.pop(); + if(nocollate_state) + c2 = ranges.peek(); + else + traits_type::transform(c2, ranges.peek() MAYBE_PASS_LOCALE(locale_inst)); + ranges.pop(); + if(c1 < c2) + { + // for some reason bc5 crashes when throwing exceptions + // from here - probably an EH-compiler bug, but hard to + // be sure... + // delay throw to later: + #ifdef __BORLANDC__ + jm_uintfast32_t f = _flags; + _flags &= ~regbase::use_except; + #endif + fail(REG_ERANGE); + #ifdef __BORLANDC__ + _flags = f; + #endif + return NULL; + } + ++cranges; + unsigned len = (re_strlen(c1.c_str()) + 1) * sizeof(charT); + memcpy(data.extend(len), c1.c_str(), len); + len = (re_strlen(c2.c_str()) + 1) * sizeof(charT); + memcpy(data.extend(len), c2.c_str(), len); + } + while(classes.empty() == false) + { + cclasses |= classes.peek(); + classes.pop(); + } + while(equivalents.empty() == false) + { + ++cequivalents; + const re_str<charT>& s = equivalents.peek(); + unsigned len = (re_strlen(s.c_str()) + 1) * sizeof(charT); + memcpy((charT*)data.extend(len), s.c_str(), len); + equivalents.pop(); + } + + re_set_long* dat = (re_set_long*)((unsigned char*)data.data() + base); + dat->type = syntax_element_long_set; + dat->csingles = csingles; + dat->cranges = cranges; + dat->cclasses = cclasses; + dat->cequivalents = cequivalents; + dat->isnot = isnot; + dat->next.i = -1; + return dat; +} + +template <class charT, class traits, class Allocator> +re_syntax_base* RE_CALL reg_expression<charT, traits, Allocator>::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_set* dat = (re_set*)data.extend(sizeof(re_set)); + memset(dat, 0, sizeof(re_set)); + + while(singles.empty() == false) + { + dat->__map[(traits_size_type)(traits_uchar_type)*(singles.peek().c_str())] = mask_all; + singles.pop(); + } + while(ranges.empty() == false) + { + re_str<charT> c1, c2, c3, c4; + + if(flags() & regbase::nocollate) + c1 = ranges.peek(); + else + traits_type::transform(c1, ranges.peek() MAYBE_PASS_LOCALE(locale_inst)); + ranges.pop(); + if(flags() & regbase::nocollate) + c2 = ranges.peek(); + else + traits_type::transform(c2, ranges.peek() MAYBE_PASS_LOCALE(locale_inst)); + ranges.pop(); + + if(c1 < c2) + { + // for some reason bc5 crashes when throwing exceptions + // from here - probably an EH-compiler bug, but hard to + // be sure... + // delay throw to later: + #ifdef __BORLANDC__ + jm_uintfast32_t f = _flags; + _flags &= ~regbase::use_except; + #endif + fail(REG_ERANGE); + #ifdef __BORLANDC__ + _flags = f; + #endif + return NULL; + } + for(unsigned int i = 0; i < 256; ++i) + { + c4 = (charT)i; + if(flags() & regbase::nocollate) + c3 = c4; + else + traits_type::transform(c3, c4 MAYBE_PASS_LOCALE(locale_inst)); + if((c3 <= c1) && (c3 >= c2)) + dat->__map[i] = mask_all; + } + } + while(equivalents.empty() == false) + { + re_str<charT> c1, c2; + for(unsigned int i = 0; i < 256; ++i) + { + c2 = (charT)i; + traits_type::transform_primary(c1, c2 MAYBE_PASS_LOCALE(locale_inst)); + if(c1 == equivalents.peek()) + dat->__map[i] = mask_all; + } + equivalents.pop(); + } + + jm_uintfast32_t flags = 0; + while(classes.empty() == false) + { + flags |= classes.peek(); + classes.pop(); + } + if(flags) + { + for(unsigned int i = 0; i < 256; ++i) + { + if(traits_type::is_class(charT(i), flags MAYBE_PASS_LOCALE(locale_inst))) + dat->__map[(traits_uchar_type)traits_type::translate((charT)i, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst))] = mask_all; + } + } + + if(isnot) + { + for(unsigned int i = 0; i < 256; ++i) + { + dat->__map[i] = !dat->__map[i]; + } + } + + dat->type = syntax_element_set; + dat->next.i = -1; + return dat; +} + + +template <class charT, class traits, class Allocator> +void RE_CALL reg_expression<charT, traits, Allocator>::fixup_apply(re_syntax_base* b, unsigned cbraces) +{ + typedef JM_MAYBE_TYPENAME REBIND_TYPE(bool, Allocator) b_alloc; + + register unsigned char* base = (unsigned char*)b; + register re_syntax_base* ptr = b; + bool* pb = 0; + b_alloc a(data.allocator()); +#ifndef JM_NO_EXCEPTIONS + try + { +#endif + pb = a.allocate(cbraces); + for(unsigned i = 0; i < cbraces; ++i) + pb[i] = false; + + repeats = 0; + + while(ptr->next.i) + { + switch(ptr->type) + { + case syntax_element_rep: + ((re_jump*)ptr)->alt.p = (re_syntax_base*)(base + ((re_jump*)ptr)->alt.i); + ((re_repeat*)ptr)->id = repeats; + ++repeats; + goto rebase; + case syntax_element_jump: + case syntax_element_alt: + ((re_jump*)ptr)->alt.p = (re_syntax_base*)(base + ((re_jump*)ptr)->alt.i); + goto rebase; + case syntax_element_backref: + if((((re_brace*)ptr)->index >= cbraces) || (pb[((re_brace*)ptr)->index] == false) ) + { + fail(REG_ESUBREG); + a.deallocate(pb, cbraces); + return; + } + goto rebase; + case syntax_element_endmark: + pb[((re_brace*)ptr)->index] = true; + goto rebase; + default: + rebase: + ptr->next.p = (re_syntax_base*)(base + ptr->next.i); + ptr = ptr->next.p; + } + } + a.deallocate(pb, cbraces); + pb = 0; +#ifndef JM_NO_EXCEPTIONS + } + catch(...) + { + if(pb) + a.deallocate(pb, cbraces); + throw; + } +#endif +} + + +template <class charT, class traits, class Allocator> +unsigned int RE_CALL reg_expression<charT, traits, Allocator>::set_expression(const charT* p, const charT* end, jm_uintfast32_t f) +{ + if(p == expression()) + { + re_str<charT> s(p, end); + return set_expression(s.c_str(), f); + } +#if defined(RE_LOCALE_C) || defined(RE_LOCALE_W32) + locale_initialiser.update(); +#else + if(JM_HAS_FACET(locale_inst, regfacet<charT>) == false) + { +#ifdef _MSC_VER + locale_inst = __JM_STD::_ADDFAC(locale_inst, new regfacet<charT>()); +#else + locale_inst = __JM_STD::locale(locale_inst, new regfacet<charT>()); +#endif + } + JM_USE_FACET(locale_inst, regfacet<charT>).update(locale_inst); +#endif + const charT* base = p; + data.clear(); + _flags = f; + fail(REG_NOERROR); // clear any error + + if(p >= end) + { + fail(REG_EMPTY); + return code; + } + + const charT* ptr = p; + marks = 0; + jstack<unsigned int, Allocator> mark(64, data.allocator()); + jstack<unsigned int, Allocator> markid(64, data.allocator()); + unsigned int last_mark_popped = 0; + register traits_size_type c; + register re_syntax_base* dat; + + unsigned rep_min, rep_max; + + // + // set up header: + // + ++marks; + dat = 0; + + if(_flags & regbase::literal) + { + while(ptr != end) + { + dat = add_literal(dat, traits::translate(*ptr, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst))); + ++ptr; + } + } + + while (ptr < end) + { + c = (traits_size_type)(traits_uchar_type)*ptr; + switch(traits_type::syntax_type(c MAYBE_PASS_LOCALE(locale_inst))) + { + case syntax_open_bracket: + if(_flags & bk_parens) + { + dat = add_literal(dat, (charT)c); + ++ptr; + continue; + } + open_bracked_jump: + // extend: + dat = add_simple(dat, syntax_element_startmark, sizeof(re_brace)); + markid.push(marks); + ((re_brace*)dat)->index = marks++; + mark.push(data.index(dat)); + ++ptr; + break; + case syntax_close_bracket: + if(_flags & bk_parens) + { + dat = add_literal(dat, (charT)c); + ++ptr; + continue; + } + + close_bracked_jump: + if(dat) + { + data.align(); + dat->next.i = data.size(); + } + + if(mark.empty()) + { + fail(REG_EPAREN); + return code; + } + // see if we have an empty alternative: + if(mark.peek() == data.index(dat) ) + { + re_syntax_base* para = (re_syntax_base*)((char*)data.data() + mark.peek()); + if(para->type == syntax_element_jump) + { + fail(REG_EMPTY); + return code; + } + } + + // pop any pushed alternatives and set the target end destination: + dat = (re_syntax_base*)((unsigned char*)data.data() + mark.peek()); + while(dat->type == syntax_element_jump) + { + ((re_jump*)dat)->alt.i = data.size(); + mark.pop(); + dat = (re_jump*)((unsigned char*)data.data() + mark.peek()); + if(mark.empty()) + { + fail(REG_EPAREN); + return code; + } + } + + dat = add_simple(0, syntax_element_endmark, sizeof(re_brace)); + ((re_brace*)dat)->index = markid.peek(); + markid.pop(); + last_mark_popped = mark.peek(); + mark.pop(); + ++ptr; + break; + case syntax_char: + dat = add_literal(dat, (charT)c); + ++ptr; + break; + case syntax_slash: + if(++ptr == end) + { + fail(REG_EESCAPE); + return code; + } + c = (traits_size_type)(traits_uchar_type)*ptr; + switch(traits_type::syntax_type(c MAYBE_PASS_LOCALE(locale_inst))) + { + case syntax_open_bracket: + if(_flags & bk_parens) + goto open_bracked_jump; + break; + case syntax_close_bracket: + if(_flags & bk_parens) + goto close_bracked_jump; + break; + case syntax_plus: + if((_flags & bk_plus_qm) && ((_flags & limited_ops) == 0)) + { + rep_min = 1; + rep_max = (unsigned)-1; + goto repeat_jump; + } + break; + case syntax_question: + if((_flags & bk_plus_qm) && ((_flags & limited_ops) == 0)) + { + rep_min = 0; + rep_max = 1; + goto repeat_jump; + } + break; + case syntax_or: + if(((_flags & bk_vbar) == 0) || (_flags & limited_ops)) + break; + goto alt_string_jump; + case syntax_open_brace: + if( ((_flags & bk_braces) == 0) || ((_flags & intervals) == 0)) + break; + + // we have {x} or {x,} or {x,y}: + parse_range(ptr, end, rep_min, rep_max); + goto repeat_jump; + + case syntax_digit: + if(_flags & bk_refs) + { + // update previous: + int i = traits_type::toi((charT)c MAYBE_PASS_LOCALE(locale_inst)); + if(i == 0) + { + // we can have \025 which means take char whose + // code is 25 (octal), so parse string: + c = traits_type::toi(ptr, end, -8 MAYBE_PASS_LOCALE(locale_inst)); + --ptr; + break; + } + dat = add_simple(dat, syntax_element_backref, sizeof(re_brace)); + ((re_brace*)dat)->index = i; + ++ptr; + continue; + } + break; + case syntax_b: // syntax_element_word_boundary + dat = add_simple(dat, syntax_element_word_boundary); + ++ptr; + continue; + case syntax_B: + dat = add_simple(dat, syntax_element_within_word); + ++ptr; + continue; + case syntax_left_word: + dat = add_simple(dat, syntax_element_word_start); + ++ptr; + continue; + case syntax_right_word: + dat = add_simple(dat, syntax_element_word_end); + ++ptr; + continue; + case syntax_w: //syntax_element_word_char + dat = compile_set_simple(dat, char_class_word); + ++ptr; + continue; + case syntax_W: + dat = compile_set_simple(dat, char_class_word, true); + ++ptr; + continue; + case syntax_d: //syntax_element_word_char + dat = compile_set_simple(dat, char_class_digit); + ++ptr; + continue; + case syntax_D: + dat = compile_set_simple(dat, char_class_digit, true); + ++ptr; + continue; + case syntax_s: //syntax_element_word_char + dat = compile_set_simple(dat, char_class_space); + ++ptr; + continue; + case syntax_S: + dat = compile_set_simple(dat, char_class_space, true); + ++ptr; + continue; + case syntax_l: //syntax_element_word_char + dat = compile_set_simple(dat, char_class_lower); + ++ptr; + continue; + case syntax_L: + dat = compile_set_simple(dat, char_class_lower, true); + ++ptr; + continue; + case syntax_u: //syntax_element_word_char + dat = compile_set_simple(dat, char_class_upper); + ++ptr; + continue; + case syntax_U: + dat = compile_set_simple(dat, char_class_upper, true); + ++ptr; + continue; + case syntax_Q: + ++ptr; + while(true) + { + if(ptr == end) + { + fail(REG_EESCAPE); + return code; + } + if(traits_type::syntax_type((traits_size_type)(traits_uchar_type)*ptr MAYBE_PASS_LOCALE(locale_inst)) == syntax_slash) + { + ++ptr; + if((ptr != end) && (traits_type::syntax_type((traits_size_type)(traits_uchar_type)*ptr MAYBE_PASS_LOCALE(locale_inst)) == syntax_E)) + break; + else + { + dat = add_literal(dat, *(ptr-1)); + continue; + } + } + dat = add_literal(dat, *ptr); + ++ptr; + } + ++ptr; + continue; + case syntax_C: + dat = add_simple(dat, syntax_element_wild); + ++ptr; + continue; + case syntax_X: + dat = add_simple(dat, syntax_element_combining); + ++ptr; + continue; + case syntax_Z: + dat = add_simple(dat, syntax_element_soft_buffer_end); + ++ptr; + continue; + case syntax_G: + dat = add_simple(dat, syntax_element_restart_continue); + ++ptr; + continue; + case syntax_start_buffer: + dat = add_simple(dat, syntax_element_buffer_start); + ++ptr; + continue; + case syntax_end_buffer: + dat = add_simple(dat, syntax_element_buffer_end); + ++ptr; + continue; + default: + c = (traits_size_type)(traits_uchar_type)parse_escape(ptr, end); + dat = add_literal(dat, (charT)c); + continue; + } + dat = add_literal(dat, (charT)c); + ++ptr; + break; + case syntax_dollar: + dat = add_simple(dat, syntax_element_end_line, sizeof(re_syntax_base)); + ++ptr; + continue; + case syntax_caret: + dat = add_simple(dat, syntax_element_start_line, sizeof(re_syntax_base)); + ++ptr; + continue; + case syntax_dot: + dat = add_simple(dat, syntax_element_wild, sizeof(re_syntax_base)); + ++ptr; + continue; + case syntax_star: + rep_min = 0; + rep_max = (unsigned)-1; + + repeat_jump: + { + unsigned offset; + if(dat == 0) + { + fail(REG_BADRPT); + return code; + } + switch(dat->type) + { + case syntax_element_endmark: + offset = last_mark_popped; + break; + case syntax_element_literal: + if(((re_literal*)dat)->length > 1) + { + // update previous: + charT lit = *(charT*)((char*)dat + sizeof(re_literal) + ((((re_literal*)dat)->length-1)*sizeof(charT))); + --((re_literal*)dat)->length; + dat = add_simple(dat, syntax_element_literal, sizeof(re_literal) + sizeof(charT)); + ((re_literal*)dat)->length = 1; + *((charT*)(((re_literal*)dat)+1)) = lit; + } + offset = (char*)dat - (char*)data.data(); + break; + case syntax_element_backref: + case syntax_element_long_set: + case syntax_element_set: + case syntax_element_wild: + case syntax_element_combining: + // we're repeating a single item: + offset = (char*)dat - (char*)data.data(); + break; + default: + fail(REG_BADRPT); + return code; + } + data.align(); + dat->next.i = data.size(); + //unsigned pos = (char*)dat - (char*)data.data(); + + // add the trailing jump: + add_simple(dat, syntax_element_jump, re_jump_size); + + // now insert the leading repeater: + dat = (re_syntax_base*)data.insert(offset, re_repeater_size); + dat->next.i = ((char*)dat - (char*)data.data()) + re_repeater_size; + dat->type = syntax_element_rep; + ((re_repeat*)dat)->alt.i = data.size(); + ((re_repeat*)dat)->min = rep_min; + ((re_repeat*)dat)->max = rep_max; + ((re_repeat*)dat)->leading = false; + move_offsets(dat, re_repeater_size); + dat = (re_syntax_base*)((char*)data.data() + data.size() - re_jump_size); + ((re_repeat*)dat)->alt.i = offset; + ++ptr; + continue; + } + case syntax_plus: + if(_flags & (bk_plus_qm | limited_ops)) + { + dat = add_literal(dat, (charT)c); + ++ptr; + continue; + } + rep_min = 1; + rep_max = (unsigned)-1; + goto repeat_jump; + case syntax_question: + if(_flags & (bk_plus_qm | limited_ops)) + { + dat = add_literal(dat, (charT)c); + ++ptr; + continue; + } + rep_min = 0; + rep_max = 1; + goto repeat_jump; + case syntax_open_set: + // update previous: + if(dat) + { + data.align(); + dat->next.i = data.size(); + } + // extend: + dat = compile_set(ptr, end); + if(dat == 0) + { + if((_flags & regbase::failbit) == 0) + fail(REG_EBRACK); + return code; + } + break; + case syntax_or: + { + if(_flags & (bk_vbar | limited_ops)) + { + dat = add_literal(dat, (charT)c); + ++ptr; + continue; + } + + alt_string_jump: + + // update previous: + if(dat == 0) + { + // start of pattern can't have empty "|" + fail(REG_EMPTY); + return code; + } + // see if we have an empty alternative: + if(mark.empty() == false) + if(mark.peek() == data.index(dat)) + { + fail(REG_EMPTY); + return code; + } + // extend: + /*dat = */add_simple(dat, syntax_element_jump, re_jump_size); + data.align(); + + // now work out where to insert: + unsigned int offset = 0; + if(mark.empty() == false) + { + // we have a '(' or '|' to go back to: + offset = mark.peek(); + re_syntax_base* base = (re_syntax_base*)((unsigned char*)data.data() + offset); + offset = base->next.i; + } + re_jump* j = (re_jump*)data.insert(offset, re_jump_size); + j->type = syntax_element_alt; + j->next.i = offset + re_jump_size; + j->alt.i = data.size(); + move_offsets(j, re_jump_size); + dat = (re_syntax_base*)((unsigned char*)data.data() + data.size() - re_jump_size); + mark.push(data.size() - re_jump_size); + ++ptr; + break; + } + case syntax_open_brace: + if((_flags & bk_braces) || ((_flags & intervals) == 0)) + { + dat = add_literal(dat, (charT)c); + ++ptr; + continue; + } + // we have {x} or {x,} or {x,y}: + parse_range(ptr, end, rep_min, rep_max); + goto repeat_jump; + case syntax_newline: + if(_flags & newline_alt) + goto alt_string_jump; + dat = add_literal(dat, (charT)c); + ++ptr; + continue; + case syntax_close_brace: + if(_flags & bk_braces) + { + dat = add_literal(dat, (charT)c); + ++ptr; + continue; + } + fail(REG_BADPAT); + return code; + default: + dat = add_literal(dat, (charT)c); + ++ptr; + break; + } // switch + } // while + + // + // update previous: + if(dat) + { + data.align(); + dat->next.i = data.size(); + } + + // see if we have an empty alternative: + if(mark.empty() == false) + if(mark.peek() == data.index(dat) ) + { + re_syntax_base* para = (re_syntax_base*)((char*)data.data() + mark.peek()); + if(para->type == syntax_element_jump) + { + fail(REG_EMPTY); + return code; + } + } + // + // set up tail: + // + if(mark.empty() == false) + { + // pop any pushed alternatives and set the target end destination: + dat = (re_syntax_base*)((unsigned char*)data.data() + mark.peek()); + while(dat->type == syntax_element_jump) + { + ((re_jump*)dat)->alt.i = data.size(); + mark.pop(); + if(mark.empty() == true) + break; + dat = (re_jump*)((unsigned char*)data.data() + mark.peek()); + } + } + + dat = (re_brace*)data.extend(sizeof(re_syntax_base)); + dat->type = syntax_element_match; + dat->next.i = 0; + + if(mark.empty() == false) + { + fail(REG_EPAREN); + return code; + } + + // + // allocate space for start __map: + startmap = (unsigned char*)data.extend(256 + ((end - base + 1) * sizeof(charT))); + // + // and copy the expression we just compiled: + _expression = (charT*)((const char*)startmap + 256); + memcpy(_expression, base, (end - base) * sizeof(charT)); + *(_expression + (end - base)) = charT(0); + + // + // now we need to apply fixups to the array + // so that we can use pointers and not indexes + fixup_apply((re_syntax_base*)data.data(), marks); + + // check for error during fixup: + if(_flags & regbase::failbit) + return code; + + // + // finally compile the maps so that we can make intelligent choices + // whenever we encounter an alternative: + compile_maps(); + if(pkmp) + { + kmp_free(pkmp, data.allocator()); + pkmp = 0; + } + re_syntax_base* sbase = (re_syntax_base*)data.data(); + _restart_type = probe_restart(sbase); + _leading_len = fixup_leading_rep(sbase, 0); + if((sbase->type == syntax_element_literal) && (sbase->next.p->type == syntax_element_match)) + { + _restart_type = restart_fixed_lit; + if(0 == pkmp) + { + charT* p1 = (charT*)((char*)sbase + sizeof(re_literal)); + charT* p2 = p1 + ((re_literal*)sbase)->length; + pkmp = kmp_compile(p1, p2, charT(), kmp_translator<traits>(_flags®base::icase), data.allocator() MAYBE_PASS_LOCALE(locale_inst)); + } + } + return code; +} + +template <class charT, class traits, class Allocator> +re_syntax_base* RE_CALL reg_expression<charT, traits, Allocator>::add_simple(re_syntax_base* dat, syntax_element_type type, unsigned int size) +{ + if(dat) + { + data.align(); + dat->next.i = data.size(); + } + if(size < sizeof(re_syntax_base)) + size = sizeof(re_syntax_base); + dat = (re_syntax_base*)data.extend(size); + dat->type = type; + dat->next.i = 0; + return dat; +} + +template <class charT, class traits, class Allocator> +re_syntax_base* RE_CALL reg_expression<charT, traits, Allocator>::add_literal(re_syntax_base* dat, charT c) +{ + if(dat && (dat->type == syntax_element_literal)) + { + // add another charT to the list: + __JM_STDC::ptrdiff_t pos = (unsigned char*)dat - (unsigned char*)data.data(); + *(charT*)data.extend(sizeof(charT)) = traits::translate(c, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst)); + dat = (re_syntax_base*)((unsigned char*)data.data() + pos); + ++(((re_literal*)dat)->length); + } + else + { + // extend: + dat = add_simple(dat, syntax_element_literal, sizeof(re_literal) + sizeof(charT)); + ((re_literal*)dat)->length = 1; + *((charT*)(((re_literal*)dat)+1)) = traits::translate(c, (_flags & regbase::icase) MAYBE_PASS_LOCALE(locale_inst)); + } + return dat; +} + +template <class charT, class traits, class Allocator> +unsigned int RE_CALL reg_expression<charT, traits, Allocator>::probe_restart(re_syntax_base* dat) +{ + switch(dat->type) + { + case syntax_element_startmark: + case syntax_element_endmark: + return probe_restart(dat->next.p); + case syntax_element_start_line: + return regbase::restart_line; + case syntax_element_word_start: + return regbase::restart_word; + case syntax_element_buffer_start: + return regbase::restart_buf; + case syntax_element_restart_continue: + return regbase::restart_continue; + default: + return regbase::restart_any; + } +} + +template <class charT, class traits, class Allocator> +unsigned int RE_CALL reg_expression<charT, traits, Allocator>::fixup_leading_rep(re_syntax_base* dat, re_syntax_base* end) +{ + unsigned int len = 0; + bool leading_lit = end ? false : true; + while(dat != end) + { + switch(dat->type) + { + case syntax_element_literal: + len += ((re_literal*)dat)->length; + if((leading_lit) && (((re_literal*)dat)->length > 2)) + { + // we can do a literal search for the leading literal string + // using Knuth-Morris-Pratt (or whatever), and only then check for + // matches. We need a decent length string though to make it + // worth while. + _leading_string = (charT*)((char*)dat + sizeof(re_literal)); + _leading_string_len = ((re_literal*)dat)->length; + _restart_type = restart_lit; + leading_lit = false; + const charT* p1 = _leading_string; + const charT* p2 = _leading_string + _leading_string_len; + pkmp = kmp_compile(p1, p2, charT(), kmp_translator<traits>(_flags®base::icase), data.allocator() MAYBE_PASS_LOCALE(locale_inst)); + } + break; + case syntax_element_wild: + ++len; + leading_lit = false; + break; + case syntax_element_match: + return len; + case syntax_element_backref: + //case syntax_element_jump: + case syntax_element_alt: + case syntax_element_combining: + return 0; + case syntax_element_long_set: + { + // we need to verify that there are no multi-character + // collating elements inside the repeat: + const charT* p = (const charT*)((const char*)dat + sizeof(re_set_long)); + unsigned int csingles = ((re_set_long*)dat)->csingles; + for(unsigned int i = 0; i < csingles; ++i) + { + if(re_strlen(p) > 1) + return 0; + while(*p)++p; + ++p; + } + ++len; + leading_lit = false; + break; + } + case syntax_element_set: + ++len; + leading_lit = false; + break; + case syntax_element_rep: + if(1 == fixup_leading_rep(dat->next.p, ((re_repeat*)dat)->alt.p) ) + { + ((re_repeat*)dat)->leading = true; + return len; + } + return 0; + } + dat = dat->next.p; + } + return len; +} + +#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES) +} // namespace +#endif + +JM_END_NAMESPACE + + + + + + + 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 + + + + + + + + + + + + + + + diff --git a/utils/tfstats/regexp/include/jm/regfac.h b/utils/tfstats/regexp/include/jm/regfac.h new file mode 100644 index 0000000..fe45c94 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/regfac.h @@ -0,0 +1,168 @@ +//========= 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 regfac.h + * VERSION 2.12 + */ + +#ifndef REGFAC_H +#define REGFAC_H + +#ifndef JM_CFG_H +#include <jm/jm_cfg.h> +#endif + +#ifdef RE_LOCALE_CPP + + +#include <string> +#include <jm/re_str.h> +#include <jm/re_cls.h> +#include <list> +#include <map> + +// +// class regfacet +// +// provides syntax data etc, customised versions +// can be installed in an instance of std::locale and imbue'd +// into a reg_expression for per-instance localisation. +// + +JM_NAMESPACE(__JM) + +template <class charT> +class regfacet : public __JM_STD::locale::facet +{ +public: + static __JM_STD::locale::id id; + regfacet(unsigned int i = 0); + jm_uintfast32_t RE_CALL lookup_classname(const charT* first, const charT* last)const; + bool RE_CALL lookup_collatename(re_str<charT>& s, const re_str<charT>& name)const; + unsigned int RE_CALL syntax_type(charT)const; + void RE_CALL update(const __JM_STD::locale&)const; + charT RE_CALL zero()const; + charT RE_CALL ten()const; + +protected: + virtual jm_uintfast32_t RE_CALL do_lookup_classname(const charT* first, const charT* last)const = 0; + virtual bool RE_CALL do_lookup_collatename(re_str<charT>& s, const re_str<charT>& name)const = 0; + virtual unsigned int RE_CALL do_syntax_type(charT)const = 0; + virtual void RE_CALL do_update(const __JM_STD::locale&) = 0; + + // required by Rogue Wave, not part of standard: + __JM_STD::locale::id& get_id()const { return id; } + ~regfacet(){} +}; + +JM_TEMPLATE_SPECIALISE +class JM_IX_DECL regfacet<char> : public __JM_STD::locale::facet +{ +public: + typedef __JM_STD::messages<char>::string_type string_type; +private: + unsigned char syntax_map[256]; + string_type name; + char _zero, _ten; + __JM_STD::map<__JM_STD::string, unsigned long, __JM_STD::less<__JM_STD::string> > classes; + __JM_STD::map<re_str<char>, re_str<char>, __JM_STD::less<re_str<char> > > collating_elements; + regfacet(const regfacet&); + +#ifdef RE_THREADS + critical_section cs; +#endif + +public: + static __JM_STD::locale::id id; + regfacet(unsigned int i = 0); + jm_uintfast32_t RE_CALL lookup_classname(const char* first, const char* last)const { return do_lookup_classname(first, last); } + bool RE_CALL lookup_collatename(re_str<char>& s, const re_str<char>& name)const { return do_lookup_collatename(s, name); } + unsigned int RE_CALL syntax_type(char c)const { return do_syntax_type(c); } + void RE_CALL update(const __JM_STD::locale& l)const { const_cast<regfacet<char>*>(this)->do_update(l); } + char RE_CALL zero()const { return _zero; } + char RE_CALL ten()const { return _ten; } + +protected: + virtual jm_uintfast32_t RE_CALL do_lookup_classname(const char* first, const char* last)const; + virtual bool RE_CALL do_lookup_collatename(re_str<char>& s, const re_str<char>& name)const; + virtual unsigned int RE_CALL do_syntax_type(char)const; + virtual void RE_CALL do_update(const __JM_STD::locale&); + + // required by Rogue Wave, not part of standard: + __JM_STD::locale::id& get_id()const { return id; } + ~regfacet(); + +}; + +JM_TEMPLATE_SPECIALISE +class JM_IX_DECL regfacet<wchar_t> : public __JM_STD::locale::facet +{ +public: + typedef __JM_STD::messages<wchar_t>::string_type string_type; +private: + __JM_STD::messages<char>::string_type name; + + struct syntax_map + { + wchar_t c; + unsigned int type; + }; + + __JM_STD::list<syntax_map> syntax; + wchar_t _zero, _ten; + __JM_STD::map<__JM_STD::wstring, unsigned long, __JM_STD::less<__JM_STD::wstring> > classes; + const __JM_STD::locale* ploc; + __JM_STD::map<re_str<wchar_t>, re_str<wchar_t>, __JM_STD::less<re_str<wchar_t> > > collating_elements; + regfacet(const regfacet&); + +#ifdef RE_THREADS + critical_section cs; +#endif + +public: + static __JM_STD::locale::id id; + regfacet(unsigned int i = 0); + jm_uintfast32_t RE_CALL lookup_classname(const wchar_t* first, const wchar_t* last)const { return do_lookup_classname(first, last); } + bool RE_CALL lookup_collatename(re_str<wchar_t>& s, const re_str<wchar_t>& name)const { return do_lookup_collatename(s, name); } + unsigned int RE_CALL syntax_type(wchar_t c)const { return do_syntax_type(c); } + void RE_CALL update(const __JM_STD::locale& l)const { const_cast<regfacet<wchar_t>*>(this)->do_update(l); } + wchar_t RE_CALL zero()const { return _zero; } + wchar_t RE_CALL ten()const { return _ten; } + +protected: + virtual jm_uintfast32_t RE_CALL do_lookup_classname(const wchar_t* first, const wchar_t* last)const; + virtual bool RE_CALL do_lookup_collatename(re_str<wchar_t>& s, const re_str<wchar_t>& name)const; + virtual unsigned int RE_CALL do_syntax_type(wchar_t)const; + virtual void RE_CALL do_update(const __JM_STD::locale&); + + // required by Rogue Wave, not part of standard: + __JM_STD::locale::id& get_id()const { return id; } + ~regfacet(); + +}; + +JM_END_NAMESPACE + +#endif + +#endif diff --git a/utils/tfstats/regexp/include/jm/regfmt.h b/utils/tfstats/regexp/include/jm/regfmt.h new file mode 100644 index 0000000..dfe3521 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/regfmt.h @@ -0,0 +1,565 @@ +//========= 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 regfmt.h + * VERSION 2.12 + * + * Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.h, do not include on its own. + */ + + +#ifndef REGFMT_H +#define REGFMT_H + + +JM_NAMESPACE(__JM) + +template <class O, class I> +O RE_CALL re_copy_out(O out, I first, I last) +{ + while(first != last) + { + *out = *first; + ++out; + ++first; + } + return out; +} + +template <class charT> +void RE_CALL re_skip_format(const charT*& fmt +#ifdef RE_LOCALE_CPP + , const __JM_STD::locale& l +#endif + ) +{ + #ifdef JM_NO_TEMPLATE_TYPENAME + typedef char_regex_traits<charT> re_traits_type; + #else + typedef typename char_regex_traits<charT> re_traits_type; + #endif + unsigned int parens = 0; + unsigned int c; + while(*fmt) + { + c = re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)); + if((c == syntax_colon) && (parens == 0)) + { + ++fmt; + return; + } + else if(c == syntax_close_bracket) + { + if(parens == 0) + { + ++fmt; + return; + } + --parens; + } + else if(c == syntax_open_bracket) + ++parens; + else if(c == syntax_slash) + { + ++fmt; + if(*fmt == 0) + return; + } + ++fmt; + } +} + +#ifdef JM_NO_OI_ASSIGN + +// +// ugly hack for buggy output iterators + +template <class T> +inline void oi_assign(T* p, T v) +{ + jm_destroy(p); + jm_construct(p, v); +} + +#else + +template <class T> +inline void oi_assign(T* p, T v) +{ + // + // if you get a compile time error in here then you either + // need to rewrite your output iterator to make it assignable + // (as is required by the standard), or define JM_NO_OI_ASSIGN + // to use the ugly hack above + *p = v; +} + +#endif + +#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 + +// +// algorithm reg_format: +// takes the result of a match and a format string +// and merges them to produce a new string which +// is sent to an OutputIterator, +// __reg_format_aux does the actual work: +// +template <class OutputIterator, class iterator, class Allocator, class charT> +OutputIterator RE_CALL __reg_format_aux(OutputIterator out, + const reg_match<iterator, Allocator>& m, + const charT*& fmt, + bool isif +#ifdef RE_LOCALE_CPP + , const __JM_STD::locale& l +#endif + ) +{ + #ifdef JM_NO_TEMPLATE_TYPENAME + typedef char_regex_traits<charT> re_traits_type; + #else + typedef typename char_regex_traits<charT> re_traits_type; + #endif + + const charT* fmt_end = fmt; + while(*fmt_end) ++ fmt_end; + + while(*fmt) + { + switch(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l))) + { + case syntax_dollar: + ++fmt; + if(*fmt == 0) // oops trailing $ + { + --fmt; + *out = *fmt; + ++out; + return out; + } + switch(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l))) + { + case syntax_start_buffer: + oi_assign(&out, re_copy_out(out, iterator(m[-1].first), iterator(m[-1].second))); + ++fmt; + continue; + case syntax_end_buffer: + oi_assign(&out, re_copy_out(out, iterator(m[-2].first), iterator(m[-2].second))); + ++fmt; + continue; + case syntax_digit: + { + unsigned int index = re_traits_type::toi(fmt, fmt_end, 10 MAYBE_PASS_LOCALE(l)); + oi_assign(&out, re_copy_out(out, iterator(m[index].first), iterator(m[index].second))); + continue; + } + } + // anything else: + if(*fmt == '&') + { + oi_assign(&out, re_copy_out(out, iterator(m[0].first), iterator(m[0].second))); + ++fmt; + } + else + { + // probably an error, treat as a literal '$' + --fmt; + *out = *fmt; + ++out; + ++fmt; + } + continue; + case syntax_slash: + { + // escape sequence: + charT c; + ++fmt; + if(*fmt == 0) + { + --fmt; + *out = *fmt; + ++out; + ++fmt; + return out; + } + switch(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l))) + { + case syntax_a: + c = '\a'; + ++fmt; + break; + case syntax_f: + c = '\f'; + ++fmt; + break; + case syntax_n: + c = '\n'; + ++fmt; + break; + case syntax_r: + c = '\r'; + ++fmt; + break; + case syntax_t: + c = '\t'; + ++fmt; + break; + case syntax_v: + c = '\v'; + ++fmt; + break; + case syntax_x: + ++fmt; + if(fmt == fmt_end) + { + *out = *--fmt; + ++out; + return out; + } + // maybe have \x{ddd} + if(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)) == syntax_open_brace) + { + ++fmt; + if(fmt == fmt_end) + { + fmt -= 2; + *out = *fmt; + ++out; + ++fmt; + continue; + } + if(re_traits_type::is_class(*fmt, char_class_xdigit MAYBE_PASS_LOCALE(l)) == false) + { + fmt -= 2; + *out = *fmt; + ++out; + ++fmt; + continue; + } + c = (charT)re_traits_type::toi(fmt, fmt_end, -16 MAYBE_PASS_LOCALE(l)); + if(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)) != syntax_close_brace) + { + while(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)) != syntax_slash) + --fmt; + ++fmt; + *out = *fmt; + ++out; + ++fmt; + continue; + } + ++fmt; + break; + } + else + { + if(re_traits_type::is_class(*fmt, char_class_xdigit MAYBE_PASS_LOCALE(l)) == false) + { + --fmt; + *out = *fmt; + ++out; + ++fmt; + continue; + } + c = (charT)re_traits_type::toi(fmt, fmt_end, -16 MAYBE_PASS_LOCALE(l)); + } + break; + case syntax_c: + ++fmt; + if(fmt == fmt_end) + { + --fmt; + *out = *fmt; + ++out; + return out; + } + if(((typename re_traits_type::uchar_type)(*fmt) < (typename re_traits_type::uchar_type)'@') + || ((typename re_traits_type::uchar_type)(*fmt) > (typename re_traits_type::uchar_type)127) ) + { + --fmt; + *out = *fmt; + ++out; + ++fmt; + break; + } + c = (charT)((typename re_traits_type::uchar_type)(*fmt) - (typename re_traits_type::uchar_type)'@'); + ++fmt; + break; + case syntax_e: + c = (charT)27; + ++fmt; + break; + case syntax_digit: + c = (charT)re_traits_type::toi(fmt, fmt_end, -8 MAYBE_PASS_LOCALE(l)); + break; + default: + c = *fmt; + ++fmt; + } + *out = c; + continue; + } + case syntax_open_bracket: + ++fmt; // recurse + oi_assign(&out, __reg_format_aux(out, m, fmt, false MAYBE_PASS_LOCALE(l))); + continue; + case syntax_close_bracket: + ++fmt; // return from recursion + return out; + case syntax_colon: + if(isif) + { + ++fmt; + return out; + } + *out = *fmt; + ++out; + ++fmt; + continue; + case syntax_question: + { + ++fmt; + if(*fmt == 0) + { + --fmt; + *out = *fmt; + ++out; + ++fmt; + return out; + } + unsigned int id = re_traits_type::toi(fmt, fmt_end, 10 MAYBE_PASS_LOCALE(l)); + if(m[id].matched) + { + oi_assign(&out, __reg_format_aux(out, m, fmt, true MAYBE_PASS_LOCALE(l))); + if(re_traits_type::syntax_type(*(fmt-1) MAYBE_PASS_LOCALE(l)) == syntax_colon) + re_skip_format(fmt MAYBE_PASS_LOCALE(l)); + } + else + { + re_skip_format(fmt MAYBE_PASS_LOCALE(l)); + if(re_traits_type::syntax_type(*(fmt-1) MAYBE_PASS_LOCALE(l)) == syntax_colon) + oi_assign(&out, __reg_format_aux(out, m, fmt, true MAYBE_PASS_LOCALE(l))); + } + return out; + } + default: + *out = *fmt; + ++out; + ++fmt; + } + } + + return out; +} + +#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES) +} // namespace +#endif + + +template <class OutputIterator, class iterator, class Allocator, class charT> +OutputIterator RE_CALL reg_format(OutputIterator out, + const reg_match<iterator, Allocator>& m, + const charT* fmt +#ifdef RE_LOCALE_CPP + , __JM_STD::locale locale_inst = __JM_STD::locale() +#endif + ) +{ + // + // start by updating the locale: + // +#if defined(RE_LOCALE_C) || defined(RE_LOCALE_W32) + static re_initialiser<charT> locale_initialiser; + locale_initialiser.update(); +#else + if(JM_HAS_FACET(locale_inst, regfacet<charT>) == false) + { +#ifdef _MSC_VER + locale_inst = __JM_STD::_ADDFAC(locale_inst, new regfacet<charT>()); +#else + locale_inst = __JM_STD::locale(locale_inst, new regfacet<charT>()); +#endif + } + JM_USE_FACET(locale_inst, regfacet<charT>).update(locale_inst); +#endif + return __reg_format_aux(out, m, fmt, false MAYBE_PASS_LOCALE(locale_inst)); +} + +template <class S> +class string_out_iterator +{ + S* out; +public: + string_out_iterator(S& s) : out(&s) {} + string_out_iterator& operator++() { return *this; } + string_out_iterator& operator++(int) { return *this; } + string_out_iterator& operator*() { return *this; } + string_out_iterator& operator=(typename S::value_type v) + { + out->append(1, v); + return *this; + } +}; + +#ifndef JM_NO_STRING_DEF_ARGS +template <class iterator, class Allocator, class charT> +__JM_STD::basic_string<charT> RE_CALL reg_format(const reg_match<iterator, Allocator>& m, const charT* fmt +#ifdef RE_LOCALE_CPP + , __JM_STD::locale locale_inst = __JM_STD::locale() +#endif + ) +{ + __JM_STD::basic_string<charT> result; + string_out_iterator<__JM_STD::basic_string<charT> > i(result); + reg_format(i, m, fmt MAYBE_PASS_LOCALE(locale_inst)); + return result; +} +#elif !defined(JM_NO_STRING_H) +template <class iterator, class Allocator> +__JM_STD::string RE_CALL reg_format(const reg_match<iterator, Allocator>& m, const char* fmt +#ifdef RE_LOCALE_CPP + , __JM_STD::locale locale_inst = __JM_STD::locale() +#endif + ) +{ + __JM_STD::string result; + string_out_iterator<__JM_STD::string> i(result); + reg_format(i, m, fmt MAYBE_PASS_LOCALE(locale_inst)); + return result; +} +#endif + + +template <class OutputIterator, class iterator, class charT, class Allocator> +class merge_out_predicate +{ + OutputIterator* out; + iterator* last; + const charT* fmt; + bool copy_none; + +#ifdef RE_LOCALE_CPP + const __JM_STD::locale& l; +#endif + +public: + merge_out_predicate(OutputIterator& o, iterator& pi, const charT* f, bool c +#ifdef RE_LOCALE_CPP + , const __JM_STD::locale& loc +#endif + ) : out(&o), last(&pi), fmt(f), copy_none(c) +#ifdef RE_LOCALE_CPP + , l(loc) +#endif + {} + + ~merge_out_predicate() {} + bool RE_CALL operator()(const __JM::reg_match<iterator, Allocator>& m) + { + const charT* f = fmt; + if(copy_none) + oi_assign(out, re_copy_out(*out, iterator(m[-1].first), iterator(m[-1].second))); + oi_assign(out, __reg_format_aux(*out, m, f, false MAYBE_PASS_LOCALE(l))); + *last = m[-2].first; + return true; + } +}; + + +template <class OutputIterator, class iterator, class traits, class Allocator, class charT> +OutputIterator RE_CALL reg_merge(OutputIterator out, + iterator first, + iterator last, + const reg_expression<charT, traits, Allocator>& e, + const charT* fmt, + bool copy = true, + unsigned int flags = match_default) +{ + // + // start by updating the locale: + // +#if defined(RE_LOCALE_C) || defined(RE_LOCALE_W32) + static re_initialiser<charT> locale_initialiser; + locale_initialiser.update(); +#else + __JM_STD::locale locale_inst(e.locale()); + if(JM_HAS_FACET(locale_inst, regfacet<charT>) == false) + { +#ifdef _MSC_VER + locale_inst = __JM_STD::_ADDFAC(locale_inst, new regfacet<charT>()); +#else + locale_inst = __JM_STD::locale(locale_inst, new regfacet<charT>()); +#endif + } + JM_USE_FACET(locale_inst, regfacet<charT>).update(locale_inst); +#endif + iterator l = first; + merge_out_predicate<OutputIterator, iterator, charT, Allocator> oi(out, l, fmt, copy MAYBE_PASS_LOCALE(locale_inst)); + reg_grep(oi, first, last, e, flags); + return copy ? re_copy_out(out, l, last) : out; +} + +#ifndef JM_NO_STRING_DEF_ARGS +template <class traits, class Allocator, class charT> +__JM_STD::basic_string<charT> RE_CALL reg_merge(const __JM_STD::basic_string<charT>& s, + const reg_expression<charT, traits, Allocator>& e, + const charT* fmt, + bool copy = true, + unsigned int flags = match_default) +{ + __JM_STD::basic_string<charT> result; + string_out_iterator<__JM_STD::basic_string<charT> > i(result); + reg_merge(i, s.begin(), s.end(), e, fmt, copy, flags); + return result; +} +#elif !defined(JM_NO_STRING_H) +template <class traits, class Allocator> +__JM_STD::string RE_CALL reg_merge(const __JM_STD::string& s, + const reg_expression<char, traits, Allocator>& e, + const char* fmt, + bool copy = true, + unsigned int flags = match_default) +{ + __JM_STD::string result; + string_out_iterator<__JM_STD::string> i(result); + reg_merge(i, s.begin(), s.end(), e, fmt, copy, flags); + return result; +} +#endif + + +JM_END_NAMESPACE + +#endif + + + diff --git a/utils/tfstats/regexp/include/jm/regmatch.h b/utils/tfstats/regexp/include/jm/regmatch.h new file mode 100644 index 0000000..8acc0f5 --- /dev/null +++ b/utils/tfstats/regexp/include/jm/regmatch.h @@ -0,0 +1,1707 @@ +//========= 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 regmatch.h + * VERSION 2.12 + * regular expression matching algorithms + */ + + +#ifndef __REGMATCH_H +#define __REGMATCH_H + + +JM_NAMESPACE(__JM) + +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) +{ + const charT* p = (const charT*)(set+1); + iterator ptr; + unsigned int i; + bool icase = e.flags() & regbase::icase; + + // try and match a single character, could be a multi-character + // collating element... + for(i = 0; i < set->csingles; ++i) + { + ptr = next; + while(*p && (ptr != last)) + { + if(traits_type::translate(*ptr, icase MAYBE_PASS_LOCALE(e.locale())) != *p) + break; + ++p; + ++ptr; + } + if(*p == 0) // if null we've matched + return set->isnot ? next : (ptr == next) ? ++next : ptr; + + while(*p)++p; + ++p; // skip null + } + + charT col = traits_type::translate(*next, icase MAYBE_PASS_LOCALE(e.locale())); + + + if(set->cranges || set->cequivalents) + { + re_str<charT> s2(col); + re_str<charT> s1; + // + // try and match a range, NB only a single character can match + if(set->cranges) + { + if(e.flags() & regbase::nocollate) + s1 = s2; + else + traits_type::transform(s1, s2 MAYBE_PASS_LOCALE(e.locale())); + for(i = 0; i < set->cranges; ++i) + { + if(s1 <= p) + { + while(*p)++p; + ++p; + if(s1 >= p) + return set->isnot ? next : ++next; + } + else + { + // skip first string + while(*p)++p; + ++p; + } + // skip second string + while(*p)++p; + ++p; + } + } + // + // try and match an equivalence class, NB only a single character can match + if(set->cequivalents) + { + traits_type::transform_primary(s1, s2 MAYBE_PASS_LOCALE(e.locale())); + for(i = 0; i < set->cequivalents; ++i) + { + if(s1 == p) + return set->isnot ? next : ++next; + // skip string + while(*p)++p; + ++p; + } + } + } + + if(traits_type::is_class(col, set->cclasses MAYBE_PASS_LOCALE(e.locale())) == true) + return set->isnot ? next : ++next; + return set->isnot ? ++next : next; +} + +template <class iterator, class Allocator> +class __priv_match_data +{ +public: + typedef JM_MAYBE_TYPENAME REBIND_TYPE(int, Allocator) i_alloc; + typedef JM_MAYBE_TYPENAME REBIND_TYPE(iterator, Allocator) it_alloc; + + reg_match_base<iterator, Allocator> temp_match; + // failure stacks: + jstack<reg_match_base<iterator, Allocator>, Allocator> matches; + jstack<iterator, Allocator> prev_pos; + jstack<const re_syntax_base*, Allocator> prev_record; + jstack<int, Allocator> prev_acc; + int* accumulators; + unsigned int caccumulators; + iterator* loop_starts; + + __priv_match_data(const reg_match_base<iterator, Allocator>&); + + ~__priv_match_data() + { + free(); + } + void free(); + void set_accumulator_size(unsigned int size); + int* get_accumulators() + { + return accumulators; + } + iterator* get_loop_starts() + { + return loop_starts; + } +}; + +template <class iterator, class Allocator> +__priv_match_data<iterator, Allocator>::__priv_match_data(const reg_match_base<iterator, Allocator>& m) + : temp_match(m), matches(64, m.allocator()), prev_pos(64, m.allocator()), prev_record(64, m.allocator()) +{ + accumulators = 0; + caccumulators = 0; + loop_starts = 0; +} + +template <class iterator, class Allocator> +void __priv_match_data<iterator, Allocator>::set_accumulator_size(unsigned int size) +{ + if(size > caccumulators) + { + free(); + caccumulators = size; + accumulators = i_alloc(temp_match.allocator()).allocate(caccumulators); + loop_starts = it_alloc(temp_match.allocator()).allocate(caccumulators); + for(unsigned i = 0; i < caccumulators; ++i) + new (loop_starts + i) iterator(); + } +} + +template <class iterator, class Allocator> +void __priv_match_data<iterator, Allocator>::free() +{ + if(caccumulators) + { + //REBIND_INSTANCE(int, Allocator, temp_match.allocator()).deallocate(accumulators, caccumulators); + i_alloc temp1(temp_match.allocator()); + temp1.deallocate(accumulators, caccumulators); + for(unsigned i = 0; i < caccumulators; ++i) + jm_destroy(loop_starts + i); + //REBIND_INSTANCE(iterator, Allocator, temp_match.allocator()).deallocate(loop_starts, caccumulators); + it_alloc temp2(temp_match.allocator()); + temp2.deallocate(loop_starts, caccumulators); + } +} + +// +// proc query_match +// returns true if the specified regular expression matches +// at position first. Fills in what matched in m. +// +template <class iterator, class Allocator, class charT, class traits, class Allocator2> +bool query_match(iterator first, iterator last, reg_match<iterator, Allocator>& m, const reg_expression<charT, traits, Allocator2>& e, unsigned flags = match_default) +{ + // prepare m for failure: + if((flags & match_init) == 0) + { + m.set_size(e.mark_count(), first, last); + } + __priv_match_data<iterator, Allocator> pd(m); + iterator restart; + return query_match_aux(first, last, m, e, flags, pd, &restart); +} + +// +// query_match convenience interfaces: +#ifndef JM_NO_PARTIAL_FUNC_SPEC +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template <class charT, class Allocator, class traits, class Allocator2> +inline bool query_match(const charT* str, + reg_match<const charT*, Allocator>& m, + const reg_expression<charT, traits, Allocator2>& e, + unsigned flags = match_default) +{ + return query_match(str, str + traits::length(str), m, e, flags); +} + +#ifndef JM_NO_STRING_H +template <class ST, class SA, class Allocator, class charT, class traits, class Allocator2> +inline bool query_match(const __JM_STD::basic_string<charT, ST, SA>& s, + reg_match<typename __JM_STD::basic_string<charT, ST, SA>::const_iterator, Allocator>& m, + const reg_expression<charT, traits, Allocator2>& e, + unsigned flags = match_default) +{ + return query_match(s.begin(), s.end(), m, e, flags); +} +#endif +#else // partial specialisation +inline bool query_match(const char* str, + cmatch& m, + const regex& e, + unsigned flags = match_default) +{ + return query_match(str, str + regex::traits_type::length(str), m, e, flags); +} +#ifndef JM_NO_WCSTRING +inline bool query_match(const wchar_t* str, + wcmatch& m, + const wregex& e, + unsigned flags = match_default) +{ + return query_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +#endif +#ifndef JM_NO_STRING_H +inline bool query_match(const __JM_STD::string& s, + reg_match<__JM_STD::string::const_iterator, regex::alloc_type>& m, + const regex& e, + unsigned flags = match_default) +{ + return query_match(s.begin(), s.end(), m, e, flags); +} +#if !defined(JM_NO_STRING_DEF_ARGS) && !defined(JM_NO_WCSTRING) +inline bool query_match(const __JM_STD::basic_string<wchar_t>& s, + reg_match<__JM_STD::basic_string<wchar_t>::const_iterator, wregex::alloc_type>& m, + const wregex& e, + unsigned flags = match_default) +{ + return query_match(s.begin(), s.end(), m, e, flags); +} +#endif + +#endif + +#endif + + +#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 iterator, class Allocator, class charT, class traits, class Allocator2> +bool query_match_aux(iterator first, + iterator last, + reg_match<iterator, Allocator>& m, + const reg_expression<charT, traits, Allocator2>& e, + unsigned flags, + __priv_match_data<iterator, Allocator>& pd, + iterator* restart) +{ + if(e.flags() & regbase::failbit) + return false; + + typedef typename traits::size_type traits_size_type; + typedef typename traits::uchar_type traits_uchar_type; + typedef typename is_byte<charT>::width_type width_type; + + #ifdef RE_LOCALE_CPP + const __JM_STD::locale& locale_inst = e.locale(); + #endif + + // declare some local aliases to reduce pointer loads + // good optimising compilers should make this unnecessary!! + jstack<reg_match_base<iterator, Allocator>, Allocator>& matches = pd.matches; + jstack<iterator, Allocator>& prev_pos = pd.prev_pos; + jstack<const re_syntax_base*, Allocator>& prev_record = pd.prev_record; + jstack<int, Allocator>& prev_acc = pd.prev_acc; + reg_match_base<iterator, Allocator>& temp_match = pd.temp_match; + temp_match.set_first(first); + + //temp_match.set_size(e.mark_count(), first, last); + register const re_syntax_base* ptr = e.first(); + bool match_found = false; + bool need_push_match = (e.mark_count() > 1); + int cur_acc = -1; // no active accumulator + pd.set_accumulator_size(e.repeat_count()); + int* accumulators = pd.get_accumulators(); + iterator* start_loop = pd.get_loop_starts(); + int k; // for loops + bool icase = e.flags() & regbase::icase; + *restart = first; + iterator base = first; + + // prepare m for failure: + /* + if((flags & match_init) == 0) + { + m.init_fail(first, last); + } */ + + retry: + + while(first != last) + { + jm_assert(ptr); + switch(ptr->type) + { + case syntax_element_match: + match_jump: + { + // match found, save then fallback in case we missed a + // longer one. + if((flags & match_not_null) && (first == temp_match[0].first)) + goto failure; + temp_match.set_second(first); + m.maybe_assign(temp_match); + match_found = true; + if((flags & match_any) || ((first == last) && (need_push_match == false))) + { + // either we don't care what we match or we've matched + // the whole string and can't match anything longer. + while(matches.empty() == false) + matches.pop(); + while(prev_pos.empty() == false) + prev_pos.pop(); + while(prev_record.empty() == false) + prev_record.pop(); + while(prev_acc.empty() == false) + prev_acc.pop(); + return true; + } + } + goto failure; + case syntax_element_startmark: + temp_match.set_first(first, ((re_brace*)ptr)->index); + ptr = ptr->next.p; + break; + case syntax_element_endmark: + temp_match.set_second(first, ((re_brace*)ptr)->index); + ptr = ptr->next.p; + break; + case syntax_element_literal: + { + unsigned int len = ((re_literal*)ptr)->length; + charT* what = (charT*)(((re_literal*)ptr) + 1); + // + // compare string with what we stored in + // our records: + for(unsigned int i = 0; i < len; ++i, ++first) + { + if((first == last) || (traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst)) != what[i])) + goto failure; + } + ptr = ptr->next.p; + break; + } + case syntax_element_start_line: + outer_line_check: + if(first == temp_match[0].first) + { + // we're at the start of the buffer + if(flags & match_prev_avail) + { + inner_line_check: + // check the previous value even though its before + // the start of our "buffer". + iterator t(first); + --t; + if(traits::is_separator(*t) && !((*t == '\r') && (*first == '\n')) ) + { + ptr = ptr->next.p; + continue; + } + goto failure; + } + if((flags & match_not_bol) == 0) + { + ptr = ptr->next.p; + continue; + } + goto failure; + } + // we're in the middle of the string + goto inner_line_check; + case syntax_element_end_line: + // we're not yet at the end so *first is always valid: + if(traits::is_separator(*first)) + { + if((first != base) || (flags & match_prev_avail)) + { + // check that we're not in the middle of \r\n sequence + iterator t(first); + --t; + if((*t == '\r') && (*first == '\n')) + { + goto failure; + } + } + ptr = ptr->next.p; + continue; + } + goto failure; + case syntax_element_wild: + // anything except possibly NULL or \n: + if(traits::is_separator(*first)) + { + if(flags & match_not_dot_newline) + goto failure; + ptr = ptr->next.p; + ++first; + continue; + } + if(*first == charT(0)) + { + if(flags & match_not_dot_null) + goto failure; + ptr = ptr->next.p; + ++first; + continue; + } + ptr = ptr->next.p; + ++first; + break; + case syntax_element_word_boundary: + { + // prev and this character must be opposites: + bool b = traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)); + if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0)) + { + if(flags & match_not_bow) + b ^= true; + else + b ^= false; + } + else + { + --first; + b ^= traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)); + ++first; + } + if(b) + { + ptr = ptr->next.p; + continue; + } + goto failure; + } + case syntax_element_within_word: + // both prev and this character must be char_class_word: + if(traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst))) + { + bool b; + if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0)) + b = false; + else + { + --first; + b = traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)); + ++first; + } + if(b) + { + ptr = ptr->next.p; + continue; + } + } + goto failure; + case syntax_element_word_start: + if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0)) + { + // start of buffer: + if(flags & match_not_bow) + goto failure; + if(traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst))) + { + ptr = ptr->next.p; + continue; + } + goto failure; + } + // otherwise inside buffer: + if(traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst))) + { + iterator t(first); + --t; + if(traits::is_class(*t, char_class_word MAYBE_PASS_LOCALE(locale_inst)) == false) + { + ptr = ptr->next.p; + continue; + } + } + goto failure; // if we fall through to here then we've failed + case syntax_element_word_end: + if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0)) + goto failure; // start of buffer can't be end of word + + // otherwise inside buffer: + if(traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)) == false) + { + iterator t(first); + --t; + if(traits::is_class(*t, char_class_word MAYBE_PASS_LOCALE(locale_inst))) + { + ptr = ptr->next.p; + continue; + } + } + goto failure; // if we fall through to here then we've failed + case syntax_element_buffer_start: + if((first != temp_match[0].first) || (flags & match_not_bob)) + goto failure; + // OK match: + ptr = ptr->next.p; + break; + case syntax_element_buffer_end: + if((first != last) || (flags & match_not_eob)) + goto failure; + // OK match: + ptr = ptr->next.p; + break; + case syntax_element_backref: + { + // compare with what we previously matched: + iterator i = temp_match[((re_brace*)ptr)->index].first; + iterator j = temp_match[((re_brace*)ptr)->index].second; + while(i != j) + { + if((first == last) || (traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst)) != traits::translate(*i, icase MAYBE_PASS_LOCALE(locale_inst)))) + goto failure; + ++i; + ++first; + } + ptr = ptr->next.p; + break; + } + case syntax_element_long_set: + { + // let the traits class do the work: + iterator t = re_is_set_member(first, last, (re_set_long*)ptr, e); + if(t != first) + { + ptr = ptr->next.p; + first = t; + continue; + } + goto failure; + } + case syntax_element_set: + // lookup character in table: + if(((re_set*)ptr)->__map[(traits_uchar_type)traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst))]) + { + ptr = ptr->next.p; + ++first; + continue; + } + goto failure; + case syntax_element_jump: + ptr = ((re_jump*)ptr)->alt.p; + continue; + case syntax_element_alt: + { + // alt_jump: + if(reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_jump*)ptr)->__map, (unsigned char)mask_take, width_type())) + { + // we can take the first alternative, + // see if we need to push next alternative: + if(reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_jump*)ptr)->__map, mask_skip, width_type())) + { + if(need_push_match) + matches.push(temp_match); + for(k = 0; k <= cur_acc; ++k) + prev_pos.push(start_loop[k]); + prev_pos.push(first); + prev_record.push(ptr); + for(k = 0; k <= cur_acc; ++k) + prev_acc.push(accumulators[k]); + prev_acc.push(cur_acc); + } + ptr = ptr->next.p; + continue; + } + if(reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_jump*)ptr)->__map, mask_skip, width_type())) + { + ptr = ((re_jump*)ptr)->alt.p; + continue; + } + goto failure; // neither option is possible + } + case syntax_element_rep: + { + // repeater_jump: + // if we're moving to a higher id (nested repeats etc) + // zero out our accumualtors: + if(cur_acc < ((re_repeat*)ptr)->id) + { + cur_acc = ((re_repeat*)ptr)->id; + accumulators[cur_acc] = 0; + start_loop[cur_acc] = iterator(); + } + + cur_acc = ((re_repeat*)ptr)->id; + + if(((re_repeat*)ptr)->leading) + *restart = first; + + //charT c = traits::translate(*first MAYBE_PASS_LOCALE(locale_inst)); + + // first of all test for special case where this is last element, + // if that is the case then repeat as many times as possible: + + if(((re_repeat*)ptr)->alt.p->type == syntax_element_match) + { + // see if we can take the repeat: + if(((unsigned int)accumulators[cur_acc] < ((re_repeat*)ptr)->max) + && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_take, width_type())) + { + // push terminating match as fallback: + if((unsigned int)accumulators[cur_acc] >= ((re_repeat*)ptr)->min) + { + if((prev_record.empty() == false) && (prev_record.peek() == ((re_repeat*)ptr)->alt.p)) + { + // we already have the required fallback + // don't add any more, just update this one: + if(need_push_match) + matches.peek() = temp_match; + prev_pos.peek() = first; + } + else + { + if(need_push_match) + matches.push(temp_match); + prev_pos.push(first); + prev_record.push(((re_repeat*)ptr)->alt.p); + } + } + // move to next item in list: + if(first != start_loop[cur_acc]) + { + ++accumulators[cur_acc]; + ptr = ptr->next.p; + start_loop[cur_acc] = first; + continue; + } + goto failure; + } + // see if we can skip the repeat: + if(((unsigned int)accumulators[cur_acc] >= ((re_repeat*)ptr)->min) + && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_skip, width_type())) + { + ptr = ((re_repeat*)ptr)->alt.p; + continue; + } + // otherwise fail: + goto failure; + } + + // see if we can skip the repeat: + if(((unsigned int)accumulators[cur_acc] >= ((re_repeat*)ptr)->min) + && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_skip, width_type())) + { + // see if we can push failure info: + if(((unsigned int)accumulators[cur_acc] < ((re_repeat*)ptr)->max) + && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_take, width_type())) + { + // check to see if the last loop matched a NULL string + // if so then we really don't want to loop again: + if(((unsigned int)accumulators[cur_acc] == ((re_repeat*)ptr)->min) + || (first != start_loop[cur_acc])) + { + if(need_push_match) + matches.push(temp_match); + prev_pos.push(first); + prev_record.push(ptr); + for(k = 0; k <= cur_acc; ++k) + prev_acc.push(accumulators[k]); + //prev_acc.push(cur_acc); + } + } + ptr = ((re_repeat*)ptr)->alt.p; + continue; + } + + // otherwise see if we can take the repeat: + if(((unsigned int)accumulators[cur_acc] < ((re_repeat*)ptr)->max) + && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_take, width_type()) && + (first != start_loop[cur_acc])) + { + // move to next item in list: + ++accumulators[cur_acc]; + ptr = ptr->next.p; + start_loop[cur_acc] = first; + continue; + } + + // if we get here then neither option is allowed so fail: + goto failure; + + } + case syntax_element_combining: + if(traits::is_combining(traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst)))) + goto failure; + ++first; + while((first != last) && traits::is_combining(traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst))))++first; + ptr = ptr->next.p; + continue; + case syntax_element_soft_buffer_end: + { + if(flags & match_not_eob) + goto failure; + iterator p(first); + while((p != last) && traits::is_separator(traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst))))++p; + if(p != last) + goto failure; + ptr = ptr->next.p; + continue; + } + case syntax_element_restart_continue: + if(first != temp_match[-1].first) + goto failure; + ptr = ptr->next.p; + continue; + default: + jm_assert(0); // should never get to here!! + return false; + } + } + + // + // if we get to here then we've run out of characters to match against, + // we could however still have non-character regex items left + if(ptr->can_be_null == 0) + goto failure; + while(true) + { + jm_assert(ptr); + switch(ptr->type) + { + case syntax_element_match: + goto match_jump; + case syntax_element_startmark: + temp_match.set_first(first, ((re_brace*)ptr)->index); + ptr = ptr->next.p; + break; + case syntax_element_endmark: + temp_match.set_second(first, ((re_brace*)ptr)->index); + ptr = ptr->next.p; + break; + case syntax_element_start_line: + goto outer_line_check; + case syntax_element_end_line: + // we're at the end so *first is never valid: + if((flags & match_not_eol) == 0) + { + ptr = ptr->next.p; + continue; + } + goto failure; + case syntax_element_word_boundary: + case syntax_element_word_end: + if(((flags & match_not_eow) == 0) && (first != temp_match[0].first)) + { + iterator t(first); + --t; + if(traits::is_class(*t, char_class_word MAYBE_PASS_LOCALE(locale_inst))) + { + ptr = ptr->next.p; + continue; + } + } + goto failure; + case syntax_element_buffer_end: + case syntax_element_soft_buffer_end: + if(flags & match_not_eob) + goto failure; + // OK match: + ptr = ptr->next.p; + break; + case syntax_element_jump: + ptr = ((re_jump*)ptr)->alt.p; + continue; + case syntax_element_alt: + if(ptr->can_be_null & mask_take) + { + // we can test the first alternative, + // see if we need to push next alternative: + if(ptr->can_be_null & mask_skip) + { + if(need_push_match) + matches.push(temp_match); + for(k = 0; k <= cur_acc; ++k) + prev_pos.push(start_loop[k]); + prev_pos.push(first); + prev_record.push(ptr); + for(k = 0; k <= cur_acc; ++k) + prev_acc.push(accumulators[k]); + prev_acc.push(cur_acc); + } + ptr = ptr->next.p; + continue; + } + if(ptr->can_be_null & mask_skip) + { + ptr = ((re_jump*)ptr)->alt.p; + continue; + } + goto failure; // neither option is possible + case syntax_element_rep: + // if we're moving to a higher id (nested repeats etc) + // zero out our accumualtors: + if(cur_acc < ((re_repeat*)ptr)->id) + { + cur_acc = ((re_repeat*)ptr)->id; + accumulators[cur_acc] = 0; + start_loop[cur_acc] = first; + } + + cur_acc = ((re_repeat*)ptr)->id; + + // see if we can skip the repeat: + if(((unsigned int)accumulators[cur_acc] >= ((re_repeat*)ptr)->min) + && (ptr->can_be_null & mask_skip)) + { + // don't push failure info, there's no point: + ptr = ((re_repeat*)ptr)->alt.p; + continue; + } + + // otherwise see if we can take the repeat: + if(((unsigned int)accumulators[cur_acc] < ((re_repeat*)ptr)->max) + && ((ptr->can_be_null & (mask_take | mask_skip)) == (mask_take | mask_skip))) + { + // move to next item in list: + ++accumulators[cur_acc]; + ptr = ptr->next.p; + start_loop[cur_acc] = first; + continue; + } + + // if we get here then neither option is allowed so fail: + goto failure; + case syntax_element_restart_continue: + if(first != temp_match[-1].first) + goto failure; + ptr = ptr->next.p; + continue; + default: + goto failure; + } + } + + failure: + + if(prev_record.empty() == false) + { + ptr = prev_record.peek(); + switch(ptr->type) + { + case syntax_element_alt: + // get next alternative: + ptr = ((re_jump*)ptr)->alt.p; + if(need_push_match) + matches.pop(temp_match); + prev_acc.pop(cur_acc); + for(k = cur_acc; k >= 0; --k) + prev_acc.pop(accumulators[k]); + prev_pos.pop(first); + for(k = cur_acc; k >= 0; --k) + prev_pos.pop(start_loop[k]); + prev_record.pop(); + goto retry; + case syntax_element_rep: + // we're doing least number of repeats first, + // increment count and repeat again: + if(need_push_match) + matches.pop(temp_match); + prev_pos.pop(first); + cur_acc = ((re_repeat*)ptr)->id; + for(k = cur_acc; k >= 0; --k) + prev_acc.pop(accumulators[k]); + prev_record.pop(); + if((unsigned int)++accumulators[cur_acc] > ((re_repeat*)ptr)->max) + goto failure; // repetions exhausted. + ptr = ptr->next.p; + start_loop[cur_acc] = first; + goto retry; + case syntax_element_match: + if(need_push_match) + matches.pop(temp_match); + prev_pos.pop(first); + prev_record.pop(); + goto retry; + default: + jm_assert(0); + // mustn't get here!! + } + } + + if(match_found) + return true; + + // if we get to here then everything has failed + // and no match was found: + return false; +} +#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES) +} // namespace +#endif + + +template <class iterator> +void __skip_and_inc(unsigned int& clines, iterator& last_line, iterator& first, const iterator last) +{ + while(first != last) + { + if(*first == '\n') + { + last_line = ++first; + ++clines; + } + else + ++first; + } +} + +template <class iterator> +void __skip_and_dec(unsigned int& clines, iterator& last_line, iterator& first, iterator base, unsigned int len) +{ + bool need_line = false; + for(unsigned int i = 0; i < len; ++i) + { + --first; + if(*first == '\n') + { + need_line = true; + --clines; + } + } + + if(need_line) + { + last_line = first; + + if(last_line != base) + --last_line; + else + return; + + while((last_line != base) && (*last_line != '\n')) + --last_line; + if(*last_line == '\n') + ++last_line; + } +} + +template <class iterator> +inline void __inc_one(unsigned int& clines, iterator& last_line, iterator& first) +{ + if(*first == '\n') + { + last_line = ++first; + ++clines; + } + else + ++first; +} + +template <class iterator, class Allocator> +struct grep_search_predicate +{ + reg_match<iterator, Allocator>* pm; + grep_search_predicate(reg_match<iterator, Allocator>* p) : pm(p) {} + bool operator()(const reg_match<iterator, Allocator>& m) + { + *pm = static_cast<const reg_match_base<iterator, Allocator>&>(m); + return false; + } +}; + +#if !defined(JM_NO_TEMPLATE_RETURNS) && !defined(JM_NO_PARTIAL_FUNC_SPEC) + +template <class iterator, class Allocator> +inline const reg_match_base<iterator, Allocator>& grep_out_type(const grep_search_predicate<iterator, Allocator>& o, const Allocator&) +{ + return *(o.pm); +} + +#endif + +template <class T, class Allocator> +inline const Allocator& grep_out_type(const T&, const Allocator& a) +{ + return a; +} + +#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 + +// +// reg_grep2: +// find all non-overlapping matches within the sequence first last: +// +template <class Predicate, class I, class charT, class traits, class A, class A2> +unsigned int reg_grep2(Predicate foo, I first, I last, const reg_expression<charT, traits, A>& e, unsigned flags, A2 a) +{ + if(e.flags() & regbase::failbit) + return 0; + + typedef typename traits::size_type traits_size_type; + typedef typename traits::uchar_type traits_uchar_type; + typedef typename is_byte<charT>::width_type width_type; + + reg_match<I, A2> m(grep_out_type(foo, a)); + I restart; + m.set_size(e.mark_count(), first, last); + m.set_line(1, first); + + #ifdef RE_LOCALE_CPP + const __JM_STD::locale& locale_inst = e.locale(); + #endif + + unsigned int clines = 1; + unsigned int cmatches = 0; + I last_line = first; + I next_base; + I base = first; + bool need_init; + + flags |= match_init; + + __priv_match_data<I, A2> pd(m); + + const unsigned char* __map = e.get_map(); + unsigned int type; + + if(first == last) + { + // special case, only test if can_be_null, + // don't dereference any pointers!! + if(e.first()->can_be_null) + if(query_match_aux(first, last, m, e, flags, pd, &restart)) + { + foo(m); + ++cmatches; + } + return cmatches; + } + + // try one time whatever: + if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type() ) ) + { + if(query_match_aux(first, last, m, e, flags, pd, &restart)) + { + ++cmatches; + if(foo(m) == false) + return cmatches; + // update to end of what matched + // trying to match again with match_not_null set if this + // is a null match... + need_init = true; + if(first == m[0].second) + { + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart)) + { + ++cmatches; + if(foo(m) == false) + return cmatches; + } + else + { + need_init = false; + for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + } + } + if(need_init) + { + __skip_and_inc(clines, last_line, first, m[0].second); + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + } + } + else + { + for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + } + } + else + __inc_one(clines, last_line, first); + flags |= match_prev_avail | match_not_bob; + + + // depending on what the first record is we may be able to + // optimise the search: + type = (flags & match_continuous) ? regbase::restart_continue : e.restart_type(); + + if(type == regbase::restart_buf) + return cmatches; + + switch(type) + { + case regbase::restart_lit: + case regbase::restart_fixed_lit: + { + const kmp_info<charT>* info = e.get_kmp(); + int len = info->len; + const charT* x = info->pstr; + int j = 0; + bool icase = e.flags() & regbase::icase; + while (first != last) + { + while((j > -1) && (x[j] != traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst)))) + j = info->kmp_next[j]; + __inc_one(clines, last_line, first); + ++j; + if(j >= len) + { + if(type == regbase::restart_fixed_lit) + { + __skip_and_dec(clines, last_line, first, base, j); + restart = first; + restart += len; + m.set_first(first); + m.set_second(restart); + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + __skip_and_inc(clines, last_line, first, restart); + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + j = 0; + } + else + { + restart = first; + __skip_and_dec(clines, last_line, first, base, j); + if(query_match_aux(first, last, m, e, flags, pd, &restart)) + { + + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + // update to end of what matched + __skip_and_inc(clines, last_line, first, m[0].second); + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + j = 0; + } + else + { + for(int k = 0; (restart != first) && (k < j); ++k, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + j = 0; //we could do better than this... + } + } + } + } + break; + } + case regbase::restart_any: + { + while(first != last) + { + if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type()) ) + { + if(query_match_aux(first, last, m, e, flags, pd, &restart)) + { + + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + // update to end of what matched + // trying to match again with match_not_null set if this + // is a null match... + need_init = true; + if(first == m[0].second) + { + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart)) + { + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + } + else + { + need_init = false; + for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + } + } + if(need_init) + { + __skip_and_inc(clines, last_line, first, m[0].second); + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + } + continue; + } + else + { + for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + } + } + else + __inc_one(clines, last_line, first); + } + } + break; + case regbase::restart_word: + { + // do search optimised for word starts: + while(first != last) + { + --first; + if(*first == '\n') + --clines; + // skip the word characters: + while((first != last) && traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst))) + ++first; + // now skip the white space: + while((first != last) && (traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)) == false)) + __inc_one(clines, last_line, first); + if(first == last) + break; + + if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type()) ) + { + if(query_match_aux(first, last, m, e, flags, pd, &restart)) + { + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + // update to end of what matched + // trying to match again with match_not_null set if this + // is a null match... + need_init = true; + if(first == m[0].second) + { + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart)) + { + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + } + else + { + need_init = false; + for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + } + } + if(need_init) + { + __skip_and_inc(clines, last_line, first, m[0].second); + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + } + } + else + { + for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + } + } + else + __inc_one(clines, last_line, first); + } + } + break; + case regbase::restart_line: + { + // do search optimised for line starts: + while(first != last) + { + // find first charcter after a line break: + --first; + if(*first == '\n') + --clines; + while((first != last) && (*first != '\n')) + ++first; + if(first == last) + break; + ++first; + if(first == last) + break; + + ++clines; + last_line = first; + + if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type()) ) + { + if(query_match_aux(first, last, m, e, flags, pd, &restart)) + { + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + // update to end of what matched + // trying to match again with match_not_null set if this + // is a null match... + need_init = true; + if(first == m[0].second) + { + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart)) + { + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + } + else + { + need_init = false; + for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + } + } + if(need_init) + { + __skip_and_inc(clines, last_line, first, m[0].second); + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + } + } + else + { + for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart); + if(restart != last) + ++restart; + __skip_and_inc(clines, last_line, first, restart); + } + } + else + __inc_one(clines, last_line, first); + } + } + break; + case regbase::restart_continue: + { + while(first != last) + { + if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type()) ) + { + if(query_match_aux(first, last, m, e, flags, pd, &restart)) + { + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + // update to end of what matched + // trying to match again with match_not_null set if this + // is a null match... + if(first == m[0].second) + { + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart)) + { + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + } + else + return cmatches; // can't continue from null match + } + __skip_and_inc(clines, last_line, first, m[0].second); + next_base = m[0].second; + pd.temp_match.init_fail(next_base, last); + m.init_fail(next_base, last); + continue; + } + } + return cmatches; + } + } + break; + } + + + // finally check trailing null string: + if(e.first()->can_be_null) + { + if(query_match_aux(first, last, m, e, flags, pd, &restart)) + { + m.set_line(clines, last_line); + ++cmatches; + if(foo(m) == false) + return cmatches; + } + } + + return cmatches; +} +#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES) +} // namespace +#endif + + +template <class iterator, class Allocator, class charT, class traits, class Allocator2> +bool reg_search(iterator first, iterator last, reg_match<iterator, Allocator>& m, const reg_expression<charT, traits, Allocator2>& e, unsigned flags = match_default) +{ + if(e.flags() & regbase::failbit) + return false; + + typedef typename traits::size_type traits_size_type; + typedef typename traits::uchar_type traits_uchar_type; + + // prepare m for failure: + if((flags & match_init) == 0) + { + m.set_size(e.mark_count(), first, last); + } + + flags |= match_init; + return reg_grep2(grep_search_predicate<iterator, Allocator>(&m), first, last, e, flags, m.allocator()); +} + +// +// reg_search convenience interfaces: +#ifndef JM_NO_PARTIAL_FUNC_SPEC +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template <class charT, class Allocator, class traits, class Allocator2> +inline bool reg_search(const charT* str, + reg_match<const charT*, Allocator>& m, + const reg_expression<charT, traits, Allocator2>& e, + unsigned flags = match_default) +{ + return reg_search(str, str + traits::length(str), m, e, flags); +} + +#ifndef JM_NO_STRING_H +template <class ST, class SA, class Allocator, class charT, class traits, class Allocator2> +inline bool reg_search(const __JM_STD::basic_string<charT, ST, SA>& s, + reg_match<typename __JM_STD::basic_string<charT, ST, SA>::const_iterator, Allocator>& m, + const reg_expression<charT, traits, Allocator2>& e, + unsigned flags = match_default) +{ + return reg_search(s.begin(), s.end(), m, e, flags); +} +#endif +#else // partial specialisation +inline bool reg_search(const char* str, + cmatch& m, + const regex& e, + unsigned flags = match_default) +{ + return reg_search(str, str + regex::traits_type::length(str), m, e, flags); +} +#ifndef JM_NO_WCSTRING +inline bool reg_search(const wchar_t* str, + wcmatch& m, + const wregex& e, + unsigned flags = match_default) +{ + return reg_search(str, str + wregex::traits_type::length(str), m, e, flags); +} +#endif +#ifndef JM_NO_STRING_H +inline bool reg_search(const __JM_STD::string& s, + reg_match<__JM_STD::string::const_iterator, regex::alloc_type>& m, + const regex& e, + unsigned flags = match_default) +{ + return reg_search(s.begin(), s.end(), m, e, flags); +} +#if !defined(JM_NO_STRING_DEF_ARGS) && !defined(JM_NO_WCSTRING) +inline bool reg_search(const __JM_STD::basic_string<wchar_t>& s, + reg_match<__JM_STD::basic_string<wchar_t>::const_iterator, wregex::alloc_type>& m, + const wregex& e, + unsigned flags = match_default) +{ + return reg_search(s.begin(), s.end(), m, e, flags); +} +#endif + +#endif + +#endif + + +// +// reg_grep: +// find all non-overlapping matches within the sequence first last: +// +template <class Predicate, class iterator, class charT, class traits, class Allocator> +inline unsigned int reg_grep(Predicate foo, iterator first, iterator last, const reg_expression<charT, traits, Allocator>& e, unsigned flags = match_default) +{ + return reg_grep2(foo, first, last, e, flags, e.allocator()); +} + +// +// reg_grep convenience interfaces: +#ifndef JM_NO_PARTIAL_FUNC_SPEC +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template <class Predicate, class charT, class Allocator, class traits> +inline bool reg_grep(Predicate foo, const charT* str, + const reg_expression<charT, traits, Allocator>& e, + unsigned flags = match_default) +{ + return reg_grep(foo, str, str + traits::length(str), e, flags); +} + +#ifndef JM_NO_STRING_H +template <class Predicate, class ST, class SA, class Allocator, class charT, class traits> +inline bool reg_grep(Predicate foo, const __JM_STD::basic_string<charT, ST, SA>& s, + const reg_expression<charT, traits, Allocator>& e, + unsigned flags = match_default) +{ + return reg_grep(foo, s.begin(), s.end(), e, flags); +} +#endif +#else // partial specialisation +inline bool reg_grep(bool (*foo)(const cmatch&), const char* str, + const regex& e, + unsigned flags = match_default) +{ + return reg_grep(foo, str, str + regex::traits_type::length(str), e, flags); +} +#ifndef JM_NO_WCSTRING +inline bool reg_grep(bool (*foo)(const wcmatch&), const wchar_t* str, + const wregex& e, + unsigned flags = match_default) +{ + return reg_grep(foo, str, str + wregex::traits_type::length(str), e, flags); +} +#endif +#ifndef JM_NO_STRING_H +inline bool reg_grep(bool (*foo)(const reg_match<__JM_STD::string::const_iterator, regex::alloc_type>&), const __JM_STD::string& s, + const regex& e, + unsigned flags = match_default) +{ + return reg_grep(foo, s.begin(), s.end(), e, flags); +} +#if !defined(JM_NO_STRING_DEF_ARGS) && !defined(JM_NO_WCSTRING) +inline bool reg_grep(bool (*foo)(const reg_match<__JM_STD::basic_string<wchar_t>::const_iterator, wregex::alloc_type>&), + const __JM_STD::basic_string<wchar_t>& s, + const wregex& e, + unsigned flags = match_default) +{ + return reg_grep(foo, s.begin(), s.end(), e, flags); +} +#endif + +#endif + +#endif + + +// +// finally for compatablity with version 1.x of the library +// we need a form of reg_grep that takes an output iterator +// as its first argument: +// + +// +// struct grep_match: +// stores what matched during a reg_grep, +// the output iterator type passed to reg_grep must have an +// operator*() that returns a type with an +// operator=(const grep_match<iterator, Allocator>&); +// +template <class iterator, class Allocator> +struct grep_match +{ + unsigned int line; + iterator line_start; + reg_match<iterator, Allocator> what; + + grep_match(Allocator a = Allocator()) : what(a) {} + + grep_match(unsigned int l, iterator p1, const reg_match<iterator, Allocator>& m) + : what(m) { line = l; line_start = p1; } + + bool operator == (const grep_match& ) + { return false; } + + bool operator < (const grep_match&) + { return false; } +}; + +template <class O, class I, class A> +struct grep_adaptor +{ + O oi; + reg_match<I, A> m; + grep_adaptor(O i, A a) : m(a), oi(i) {} + bool operator()(const reg_match_base<I, A>& w) + { + m.what = w; + m.line = w.line(); + m.line_start = w.line_start(); + *oi = m; + ++oi; + return true; + } +}; + +template <class Out, class iterator, class charT, class traits, class Allocator> +inline unsigned int reg_grep_old(Out oi, iterator first, iterator last, const reg_expression<charT, traits, Allocator>& e, unsigned flags = match_default) +{ + return reg_grep2(grep_adaptor<Out, iterator, Allocator>(oi, e.allocator()), first, last, e, flags, e.allocator()); +} + + + +JM_END_NAMESPACE // namespace regex + +#endif // __REGMATCH_H + + + + + + + |