diff options
author | hobbs <hobbs> | 2007-11-12 02:07:18 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 2007-11-12 02:07:18 (GMT) |
commit | cf8a7199f105edc95e59373e098af6eb47d22a16 (patch) | |
tree | c7f005156cbe08f8e11d6845d4a71f991dc5b488 /generic/tclRegexp.c | |
parent | 094b6f7ae513ec561543276d7659f3a8b2a5b853 (diff) | |
download | tcl-cf8a7199f105edc95e59373e098af6eb47d22a16.zip tcl-cf8a7199f105edc95e59373e098af6eb47d22a16.tar.gz tcl-cf8a7199f105edc95e59373e098af6eb47d22a16.tar.bz2 |
* generic/tclCompCmds.c, generic/tclCompile.c, generic/tclCompile.h:
* generic/tclExecute.c, generic/tclInt.decls, generic/tclIntDecls.h:
* generic/tclRegexp.c, generic/tclRegexp.h: Add INST_REGEXP and fully
* generic/tclStubInit.c, generic/tclUtil.c: compiled [regexp] for the
* tests/regexpComp.test: [Bug 1830166] simple cases. Also
added TclReToGlob function to convert RE to glob patterns and use
these in the possible cases.
Diffstat (limited to 'generic/tclRegexp.c')
-rw-r--r-- | generic/tclRegexp.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/generic/tclRegexp.c b/generic/tclRegexp.c index 89e2061..d24e9a8 100644 --- a/generic/tclRegexp.c +++ b/generic/tclRegexp.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclRegexp.c,v 1.25 2007/11/11 19:32:17 msofer Exp $ + * RCS: @(#) $Id: tclRegexp.c,v 1.26 2007/11/12 02:07:20 hobbs Exp $ */ #include "tclInt.h" @@ -437,6 +437,45 @@ Tcl_RegExpExecObj( TclRegexp *regexpPtr = (TclRegexp *) re; Tcl_UniChar *udata; int length; + int reflags = regexpPtr->flags; +#define TCL_REG_GLOBOK_FLAGS (TCL_REG_ADVANCED | TCL_REG_NOSUB | TCL_REG_NOCASE) + + /* + * Take advantage of the equivalent glob pattern, if one exists. + * This is possible based only on the right mix of incoming flags (0) + * and regexp compile flags. + */ + if ((offset == 0) && (nmatches == 0) && (flags == 0) + && !(reflags & ~TCL_REG_GLOBOK_FLAGS) + && (regexpPtr->globObjPtr != NULL)) { + int match, nocase = (reflags & TCL_REG_NOCASE); + + /* + * Promote based on the type of incoming object. + * XXX: Currently doesn't take advantage of exact-ness that + * XXX: TclReToGlob tells us about + */ + + if (textObj->typePtr == &tclStringType) { + Tcl_UniChar *uptn; + int plen; + + udata = Tcl_GetUnicodeFromObj(textObj, &length); + uptn = Tcl_GetUnicodeFromObj(regexpPtr->globObjPtr, &plen); + match = TclUniCharMatch(udata, length, uptn, plen, nocase); + } else if ((textObj->typePtr == &tclByteArrayType) && !nocase) { + unsigned char *data, *ptn; + int plen; + + data = Tcl_GetByteArrayFromObj(textObj, &length); + ptn = Tcl_GetByteArrayFromObj(regexpPtr->globObjPtr, &plen); + match = TclByteArrayMatch(data, length, ptn, plen); + } else { + match = Tcl_StringCaseMatch(TclGetString(textObj), + TclGetString(regexpPtr->globObjPtr), nocase); + } + return match; + } /* * Save the target object so we can extract strings from it later. @@ -830,7 +869,7 @@ CompileRegexp( { TclRegexp *regexpPtr; const Tcl_UniChar *uniString; - int numChars, status, i; + int numChars, status, i, exact; Tcl_DString stringBuf; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -919,6 +958,21 @@ CompileRegexp( } /* + * Convert RE to a glob pattern equivalent, if any, and cache it. If this + * is not possible, then globObjPtr will be NULL. This is used by + * Tcl_RegExpExecObj to optionally do a fast match (avoids RE engine). + */ + + if (TclReToGlob(NULL, string, length, &stringBuf, &exact) == TCL_OK) { + regexpPtr->globObjPtr = Tcl_NewStringObj(Tcl_DStringValue(&stringBuf), + Tcl_DStringLength(&stringBuf)); + Tcl_IncrRefCount(regexpPtr->globObjPtr); + Tcl_DStringFree(&stringBuf); + } else { + regexpPtr->globObjPtr = NULL; + } + + /* * Allocate enough space for all of the subexpressions, plus one extra for * the entire pattern. */ @@ -978,6 +1032,9 @@ FreeRegexp( TclRegexp *regexpPtr) /* Compiled regular expression to free. */ { TclReFree(®expPtr->re); + if (regexpPtr->globObjPtr) { + TclDecrRefCount(regexpPtr->globObjPtr); + } if (regexpPtr->matches) { ckfree((char *) regexpPtr->matches); } |