Attachment "bytearraymatch.diff" to
ticket [1827996fff]
added by
hobbs
2007-11-08 07:48:06.
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.339
diff -u -r1.339 tclExecute.c
--- generic/tclExecute.c 20 Oct 2007 02:15:05 -0000 1.339
+++ generic/tclExecute.c 8 Nov 2007 00:45:30 -0000
@@ -4063,6 +4063,15 @@
ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2);
match = TclUniCharMatch(ustring1, length1, ustring2, length2,
nocase);
+ } else if ((valuePtr->typePtr == &tclByteArrayType)
+ || (value2Ptr->typePtr == &tclByteArrayType)) {
+ unsigned char *string1, *string2;
+ int length1, length2;
+
+ string1 = Tcl_GetByteArrayFromObj(valuePtr, &length1);
+ string2 = Tcl_GetByteArrayFromObj(value2Ptr, &length2);
+ match = TclByteArrayMatch(string1, length1, string2, length2,
+ nocase);
} else {
match = Tcl_StringCaseMatch(TclGetString(valuePtr),
TclGetString(value2Ptr), nocase);
Index: generic/tclInt.decls
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.decls,v
retrieving revision 1.114
diff -u -r1.114 tclInt.decls
--- generic/tclInt.decls 6 Sep 2007 18:13:20 -0000 1.114
+++ generic/tclInt.decls 8 Nov 2007 00:45:30 -0000
@@ -942,6 +942,11 @@
void TclBackgroundException(Tcl_Interp *interp, int code)
}
+# Added for 8.5b3 to improve binary glob match case
+declare 237 generic {
+ int TclByteArrayMatch(CONST char *string, int strLen,
+ CONST char *pattern, int ptnLen, int nocase)
+}
##############################################################################
Index: generic/tclIntDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIntDecls.h,v
retrieving revision 1.105
diff -u -r1.105 tclIntDecls.h
--- generic/tclIntDecls.h 6 Sep 2007 18:13:20 -0000 1.105
+++ generic/tclIntDecls.h 8 Nov 2007 00:45:30 -0000
@@ -1057,6 +1057,12 @@
EXTERN void TclBackgroundException (Tcl_Interp * interp,
int code);
#endif
+#ifndef TclByteArrayMatch_TCL_DECLARED
+#define TclByteArrayMatch_TCL_DECLARED
+/* 237 */
+EXTERN int TclByteArrayMatch (CONST char * string, int strLen,
+ CONST char * pattern, int ptnLen, int nocase);
+#endif
typedef struct TclIntStubs {
int magic;
@@ -1314,6 +1320,7 @@
Var * (*tclVarHashCreateVar) (TclVarHashTable * tablePtr, const char * key, int * newPtr); /* 234 */
void (*tclInitVarHashTable) (TclVarHashTable * tablePtr, Namespace * nsPtr); /* 235 */
void (*tclBackgroundException) (Tcl_Interp * interp, int code); /* 236 */
+ int (*tclByteArrayMatch) (CONST char * string, int strLen, CONST char * pattern, int ptnLen, int nocase); /* 237 */
} TclIntStubs;
#ifdef __cplusplus
@@ -2047,6 +2054,10 @@
#define TclBackgroundException \
(tclIntStubsPtr->tclBackgroundException) /* 236 */
#endif
+#ifndef TclByteArrayMatch
+#define TclByteArrayMatch \
+ (tclIntStubsPtr->tclByteArrayMatch) /* 237 */
+#endif
#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
Index: generic/tclStubInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStubInit.c,v
retrieving revision 1.144
diff -u -r1.144 tclStubInit.c
--- generic/tclStubInit.c 6 Sep 2007 18:13:23 -0000 1.144
+++ generic/tclStubInit.c 8 Nov 2007 00:45:30 -0000
@@ -326,6 +326,7 @@
TclVarHashCreateVar, /* 234 */
TclInitVarHashTable, /* 235 */
TclBackgroundException, /* 236 */
+ TclByteArrayMatch, /* 237 */
};
TclIntPlatStubs tclIntPlatStubs = {
Index: generic/tclUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclUtil.c,v
retrieving revision 1.84
diff -u -r1.84 tclUtil.c
--- generic/tclUtil.c 28 Oct 2007 03:17:00 -0000 1.84
+++ generic/tclUtil.c 8 Nov 2007 00:45:30 -0000
@@ -1553,6 +1553,195 @@
/*
*----------------------------------------------------------------------
*
+ * TclByteArrayMatch --
+ *
+ * See if a particular string matches a particular pattern. Allows case
+ * insensitivity.
+ * Parallels tclUtf.c:TclUniCharMatch, adjusted for char*.
+ *
+ * Results:
+ * The return value is 1 if string matches pattern, and 0 otherwise. The
+ * matching operation permits the following special characters in the
+ * pattern: *?\[] (see the manual entry for details on what these mean).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclByteArrayMatch(
+ CONST char *string, /* String. */
+ int strLen, /* Length of String */
+ CONST char *pattern, /* Pattern, which may contain special
+ * characters. */
+ int ptnLen, /* Length of Pattern */
+ int nocase) /* 0 for case sensitive, 1 for insensitive */
+{
+ CONST char *stringEnd, *patternEnd;
+ char p;
+
+ stringEnd = string + strLen;
+ patternEnd = pattern + ptnLen;
+
+ while (1) {
+ /*
+ * See if we're at the end of both the pattern and the string. If so,
+ * we succeeded. If we're at the end of the pattern but not at the end
+ * of the string, we failed.
+ */
+
+ if (pattern == patternEnd) {
+ return (string == stringEnd);
+ }
+ p = *pattern;
+ if ((string == stringEnd) && (p != '*')) {
+ return 0;
+ }
+
+ /*
+ * Check for a "*" as the next pattern character. It matches any
+ * substring. We handle this by skipping all the characters up to the
+ * next matching one in the pattern, and then calling ourselves
+ * recursively for each postfix of string, until either we match or we
+ * reach the end of the string.
+ */
+
+ if (p == '*') {
+ /*
+ * Skip all successive *'s in the pattern.
+ */
+
+ while (*(++pattern) == '*') {
+ /* empty body */
+ }
+ if (pattern == patternEnd) {
+ return 1;
+ }
+ p = *pattern;
+ if (nocase) {
+ p = tolower(p);
+ }
+ while (1) {
+ /*
+ * Optimization for matching - cruise through the string
+ * quickly if the next char in the pattern isn't a special
+ * character.
+ */
+
+ if ((p != '[') && (p != '?') && (p != '\\')) {
+ if (nocase) {
+ while ((string < stringEnd) && (p != *string)
+ && (p != tolower(*string))) {
+ string++;
+ }
+ } else {
+ while ((string < stringEnd) && (p != *string)) {
+ string++;
+ }
+ }
+ }
+ if (TclByteArrayMatch(string, stringEnd - string,
+ pattern, patternEnd - pattern, nocase)) {
+ return 1;
+ }
+ if (string == stringEnd) {
+ return 0;
+ }
+ string++;
+ }
+ }
+
+ /*
+ * Check for a "?" as the next pattern character. It matches any
+ * single character.
+ */
+
+ if (p == '?') {
+ pattern++;
+ string++;
+ continue;
+ }
+
+ /*
+ * Check for a "[" as the next pattern character. It is followed by a
+ * list of characters that are acceptable, or by a range (two
+ * characters separated by "-").
+ */
+
+ if (p == '[') {
+ char ch1, startChar, endChar;
+
+ pattern++;
+ ch1 = (nocase ? tolower(*string) : *string);
+ string++;
+ while (1) {
+ if ((*pattern == ']') || (pattern == patternEnd)) {
+ return 0;
+ }
+ startChar = (nocase ? tolower(*pattern) : *pattern);
+ pattern++;
+ if (*pattern == '-') {
+ pattern++;
+ if (pattern == patternEnd) {
+ return 0;
+ }
+ endChar = (nocase ? tolower(*pattern) : *pattern);
+ pattern++;
+ if (((startChar <= ch1) && (ch1 <= endChar))
+ || ((endChar <= ch1) && (ch1 <= startChar))) {
+ /*
+ * Matches ranges of form [a-z] or [z-a].
+ */
+ break;
+ }
+ } else if (startChar == ch1) {
+ break;
+ }
+ }
+ while (*pattern != ']') {
+ if (pattern == patternEnd) {
+ pattern--;
+ break;
+ }
+ pattern++;
+ }
+ pattern++;
+ continue;
+ }
+
+ /*
+ * If the next pattern character is '\', just strip off the '\' so we
+ * do exact matching on the character that follows.
+ */
+
+ if (p == '\\') {
+ if (++pattern == patternEnd) {
+ return 0;
+ }
+ }
+
+ /*
+ * There's no special character. Just make sure that the next bytes of
+ * each string match.
+ */
+
+ if (nocase) {
+ if (tolower(*string) != tolower(*pattern)) {
+ return 0;
+ }
+ } else if (*string != *pattern) {
+ return 0;
+ }
+ string++;
+ pattern++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_DStringInit --
*
* Initializes a dynamic string, discarding any previous contents of the