Compare commits

...
3 changed files with 105 additions and 5 deletions
+49 -5
View File
@@ -4934,22 +4934,58 @@ TEBCresume(
}
} else {
/*
* strcmp can't do a simple memcmp in order to handle the
* special Tcl \xC0\x80 null encoding for utf-8.
* In order to handle the special Tcl \xC0\x80 null encoding
* for utf-8, strcmp can't do a simple memcmp.
*/
s1 = TclGetStringFromObj(valuePtr, &s1len);
s2 = TclGetStringFromObj(value2Ptr, &s2len);
if (TclCheckEmptyString(valuePtr) > 0) {
s1 = "";
s1len = 0;
switch (TclCheckEmptyString(value2Ptr)) {
case -1:
s2 = TclGetStringFromObj(value2Ptr, &s2len);
break;
case 0:
/* Synthesize a value for comparison */
s2 = "1";
s2len = 1;
break;
case 1:
s2 = "";
s2len = 0;
}
} else if (TclCheckEmptyString(value2Ptr) > 0) {
s2 = "";
s2len = 0;
switch (TclCheckEmptyString(valuePtr)) {
case -1:
s1 = TclGetStringFromObj(valuePtr, &s1len);
break;
case 0:
/* Synthesize a value for comparison */
s1 = "1";
s1len = 1;
break;
case 1:
s1 = "";
s1len = 0;
}
} else {
s1 = TclGetStringFromObj(valuePtr, &s1len);
s2 = TclGetStringFromObj(value2Ptr, &s2len);
}
if (checkEq) {
memCmpFn = memcmp;
} else {
memCmpFn = (memCmpFn_t) TclpUtfNcmp2;
}
}
if (checkEq && (s1len != s2len)) {
match = 1;
} else {
} else {
/*
* The comparison function should compare up to the minimum
* byte length only.
@@ -5529,6 +5565,14 @@ TEBCresume(
value2Ptr = OBJ_AT_TOS;
valuePtr = OBJ_UNDER_TOS;
/*
Try to determine, without triggering generation of a string
representation, whether one value is not a number.
*/
if (TclCheckEmptyString(valuePtr) > 0 || TclCheckEmptyString(value2Ptr) > 0) {
goto stringCompare;
}
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK
|| GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) {
/*
+11
View File
@@ -2698,6 +2698,10 @@ MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS];
MODULE_SCOPE char tclEmptyString;
enum CheckEmptyStringResult {
TCL_EMPTYSTRING_UNKNOWN = -1, TCL_EMPTYSTRING_NO, TCL_EMPTYSTRING_YES
};
/*
*----------------------------------------------------------------
* Procedures shared among Tcl modules but not used by the outside world,
@@ -3925,6 +3929,7 @@ MODULE_SCOPE int TclCompileStreqOpCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCheckEmptyString(Tcl_Obj *objPtr);
/*
* Routines that provide the [string] ensemble functionality. Possible
@@ -4472,6 +4477,12 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr);
#define TclIsPureDict(objPtr) \
(((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclDictType))
#define TclIsPureList(objPtr) \
(((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclListType))
/*
*----------------------------------------------------------------
* Macro used by the Tcl core to compare Unicode strings. On big-endian
+45
View File
@@ -436,6 +436,7 @@ Tcl_GetCharLength(
return length;
}
/*
* OK, need to work with the object as a string.
*/
@@ -454,6 +455,50 @@ Tcl_GetCharLength(
}
return numChars;
}
/*
*----------------------------------------------------------------------
*
* TclCheckEmptyString --
*
* Determine whether the string value of an object is or would be the
* empty string, without generating a string representation.
*
* Results:
* Returns 1 if empty, 0 if not, and -1 if unknown.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclCheckEmptyString (
Tcl_Obj *objPtr
) {
int length = -1;
if (objPtr->bytes == tclEmptyStringRep) {
return TCL_EMPTYSTRING_YES;
}
if (TclIsPureList(objPtr)) {
Tcl_ListObjLength(NULL, objPtr, &length);
return length == 0;
}
if (TclIsPureDict(objPtr)) {
Tcl_DictObjSize(NULL, objPtr, &length);
return length == 0;
}
if (objPtr->bytes == NULL) {
return TCL_EMPTYSTRING_UNKNOWN;
}
return objPtr->length == 0;
}
/*
*----------------------------------------------------------------------