diff options
-rw-r--r-- | generic/tclExecute.c | 59 | ||||
-rw-r--r-- | generic/tclInt.h | 6 | ||||
-rw-r--r-- | generic/tclStringObj.c | 48 |
3 files changed, 108 insertions, 5 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index ac4076c..67c58fc 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5443,22 +5443,57 @@ 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 (TclIsEmpty(valuePtr) > 0) { + s1 = ""; + s1len = 0; + switch (TclIsEmpty(value2Ptr)) { + case -1: + s2 = TclGetStringFromObj(value2Ptr, &s2len); + case 0: + /* Synthesize a value for comparison */ + s2 = "1"; + s2len = 1; + break; + case 1: + s2 = ""; + s2len = 0; + } + } else if (TclIsEmpty(value2Ptr) > 0) { + s2 = ""; + s2len = 0; + switch (TclIsEmpty(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. @@ -6169,6 +6204,20 @@ 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. + */ +# define TclIsNotNumber(objPtr) ( \ + ( TclIsEmpty((objPtr)) > 0 \ + || ( (objPtr)->bytes != NULL && \ + TclParseNumber( \ + interp, (objPtr), "number", NULL, -1, NULL, 0) != TCL_OK)) \ + ) + if (TclIsNotNumber(valuePtr) || TclIsNotNumber(value2Ptr)) { + goto stringCompare; + } + if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) { /* * At least one non-numeric argument - compare as strings. diff --git a/generic/tclInt.h b/generic/tclInt.h index c01b0c1..817f17d 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4411,6 +4411,12 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, #define TclIsPureByteArray(objPtr) \ (((objPtr)->typePtr==&tclByteArrayType) && ((objPtr)->bytes==NULL)) +#define TclIsPureDict(objPtr) \ + (((objPtr)->typePtr==&tclDictType) && ((objPtr)->bytes==NULL)) + +#define TclIsPureList(objPtr) \ + (((objPtr)->typePtr==&tclListType) && ((objPtr)->bytes==NULL)) + /* *---------------------------------------------------------------- * Macro used by the Tcl core to compare Unicode strings. On big-endian diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index e3cede6..de3a82e 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -421,6 +421,7 @@ Tcl_GetCharLength( return length; } + /* * OK, need to work with the object as a string. */ @@ -439,6 +440,53 @@ Tcl_GetCharLength( } return numChars; } + + + +/* + *---------------------------------------------------------------------- + * + * TclIsEmpty -- + * + * 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 +TclIsEmpty ( + Tcl_Obj *objPtr +) { + int length = -1; + + if (objPtr->bytes == tclEmptyStringRep) { + return 1; + } + + 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 -1; + } + if (objPtr->bytes[0] == '\0') { + return 1; + } + return 0; +} /* *---------------------------------------------------------------------- |