diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2023-01-18 16:54:07 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2023-01-18 16:54:07 (GMT) |
commit | c18f5f7f8caa27fa6dc03bd79a4136391cad620f (patch) | |
tree | efdb7209773c9d7491787b4d93607ce734fc2681 /generic/tclStringObj.c | |
parent | 6efbc1b2785d247ceedfd98a5de2eae2a16bbf3c (diff) | |
parent | 81262438a784ae0087c36fabd189c15a2433df33 (diff) | |
download | tcl-c18f5f7f8caa27fa6dc03bd79a4136391cad620f.zip tcl-c18f5f7f8caa27fa6dc03bd79a4136391cad620f.tar.gz tcl-c18f5f7f8caa27fa6dc03bd79a4136391cad620f.tar.bz2 |
Merge 8.6
Diffstat (limited to 'generic/tclStringObj.c')
-rw-r--r-- | generic/tclStringObj.c | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 25bf34b..723d2e5 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3859,9 +3859,10 @@ TclStringCmp( Tcl_Obj *value2Ptr, int checkEq, /* comparison is only for equality */ int nocase, /* comparison is not case sensitive */ - int reqlength) /* requested length */ + int reqlength) /* requested length in characters; + * TCL_INDEX_NONE to compare whole strings */ { - char *s1, *s2; + const char *s1, *s2; int empty, length, match, s1len, s2len; memCmpFn_t memCmpFn; @@ -3886,10 +3887,10 @@ TclStringCmp( } else if (TclHasInternalRep(value1Ptr, &tclUniCharStringType) && TclHasInternalRep(value2Ptr, &tclUniCharStringType)) { /* - * Do a unicode-specific comparison if both of the args are of - * String type. If the char length == byte length, we can do a - * memcmp. In benchmark testing this proved the most efficient - * check between the unicode and string comparison operations. + * Do a Unicode-specific comparison if both of the args are of String + * type. If the char length == byte length, we can do a memcmp. In + * benchmark testing this proved the most efficient check between the + * Unicode and string comparison operations. */ if (nocase) { @@ -3903,6 +3904,9 @@ TclStringCmp( && (value1Ptr->bytes != NULL) && (s2len == value2Ptr->length) && (value2Ptr->bytes != NULL)) { + /* each byte represents one character so s1l3n, s2l3n, and + * reqlength are in both bytes and characters + */ s1 = value1Ptr->bytes; s2 = value2Ptr->bytes; memCmpFn = memcmp; @@ -3919,6 +3923,9 @@ TclStringCmp( memCmpFn = memcmp; s1len *= sizeof(Tcl_UniChar); s2len *= sizeof(Tcl_UniChar); + if (reqlength > 0) { + reqlength *= sizeof(Tcl_UniChar); + } } else { memCmpFn = (memCmpFn_t)(void *)TclUniCharNcmp; } @@ -3960,7 +3967,7 @@ TclStringCmp( s1 = TclGetStringFromObj(value1Ptr, &s1len); s2 = TclGetStringFromObj(value2Ptr, &s2len); } - if (!nocase && checkEq) { + if (!nocase && checkEq && reqlength < 0) { /* * When we have equal-length we can check only for * (in)equality. We can use memcmp in all (n)eq cases because @@ -3988,19 +3995,23 @@ TclStringCmp( } } + /* At this point s1len, s2len, and reqlength should by now have been + * adjusted so that they are all in the units expected by the selected + * comparison function. + */ length = (s1len < s2len) ? s1len : s2len; if (reqlength > 0 && reqlength < length) { length = reqlength; } else if (reqlength < 0) { /* - * The requested length is negative, so we ignore it by setting it - * to length + 1 so we correct the match var. + * The requested length is negative, so ignore it by setting it + * to length + 1 to correct the match var. */ reqlength = length + 1; } - if (checkEq && (s1len != s2len)) { + if (checkEq && reqlength < 0 && (s1len != s2len)) { match = 1; /* This will be reversed below. */ } else { /* |