summaryrefslogtreecommitdiffstats
path: root/generic/tclExecute.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r--generic/tclExecute.c91
1 files changed, 59 insertions, 32 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index f6d2ea2..bbe2728 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclExecute.c,v 1.53 2002/04/18 13:04:20 msofer Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.54 2002/05/29 09:09:57 hobbs Exp $
*/
#include "tclInt.h"
@@ -2718,7 +2718,7 @@ TclExecuteByteCode(interp, codePtr)
/*
* String compare
*/
- char *s1, *s2;
+ CONST char *s1, *s2;
int s1len, s2len, iResult;
value2Ptr = POP_OBJECT();
@@ -2728,18 +2728,25 @@ TclExecuteByteCode(interp, codePtr)
* The comparison function should compare up to the
* minimum byte length only.
*/
- if ((valuePtr->typePtr == &tclByteArrayType) &&
+ if (valuePtr == value2Ptr) {
+ /*
+ * In the pure equality case, set lengths too for
+ * the checks below (or we could goto beyond it).
+ */
+ iResult = s1len = s2len = 0;
+ } else if ((valuePtr->typePtr == &tclByteArrayType) &&
(value2Ptr->typePtr == &tclByteArrayType)) {
s1 = (char *) Tcl_GetByteArrayFromObj(valuePtr, &s1len);
s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len);
iResult = memcmp(s1, s2,
(size_t) ((s1len < s2len) ? s1len : s2len));
- } else if ((valuePtr->typePtr == &tclStringType) ||
- (value2Ptr->typePtr == &tclStringType)) {
+ } else if (((valuePtr->typePtr == &tclStringType)
+ && (valuePtr->bytes == NULL))
+ || ((value2Ptr->typePtr == &tclStringType)
+ && (value2Ptr->bytes == NULL))) {
/*
- * The alternative is to break this into more code
- * that does type sensitive comparison, as done in
- * Tcl_StringObjCmd.
+ * Do a unicode-specific comparison if one of the args
+ * only has the unicode rep.
*/
Tcl_UniChar *uni1, *uni2;
uni1 = Tcl_GetUnicodeFromObj(valuePtr, &s1len);
@@ -2748,21 +2755,12 @@ TclExecuteByteCode(interp, codePtr)
(unsigned) ((s1len < s2len) ? s1len : s2len));
} else {
/*
- * This solution is less mem intensive, but it is
- * computationally expensive as the string grows. The
- * reason that we can't use a memcmp is that UTF-8 strings
- * that contain a \u0000 can't be compared with memcmp. If
- * we knew that the string was ascii-7 or had no null byte,
- * we could just do memcmp and save all the hassle.
+ * We can't do a simple memcmp in order to handle the
+ * special Tcl \xC0\x80 null encoding for utf-8.
*/
s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
- /*
- * These have to be in true chars
- */
- s1len = Tcl_NumUtfChars(s1, s1len);
- s2len = Tcl_NumUtfChars(s2, s2len);
- iResult = Tcl_UtfNcmp(s1, s2,
+ iResult = TclpUtfNcmp2(s1, s2,
(size_t) ((s1len < s2len) ? s1len : s2len));
}
@@ -2931,6 +2929,26 @@ TclExecuteByteCode(interp, codePtr)
value2Ptr = POP_OBJECT();
valuePtr = POP_OBJECT();
+
+ if (valuePtr == value2Ptr) {
+ /*
+ * Optimize the equal object case.
+ */
+ switch (*pc) {
+ case INST_EQ:
+ case INST_LE:
+ case INST_GE:
+ iResult = 1;
+ break;
+ case INST_NEQ:
+ case INST_LT:
+ case INST_GT:
+ iResult = 0;
+ break;
+ }
+ goto foundResult;
+ }
+
t1Ptr = valuePtr->typePtr;
t2Ptr = value2Ptr->typePtr;
@@ -2967,30 +2985,39 @@ TclExecuteByteCode(interp, codePtr)
if (!IS_NUMERIC_TYPE(t1Ptr) || !IS_NUMERIC_TYPE(t2Ptr)) {
/*
* One operand is not numeric. Compare as strings.
- * NOTE: strcmp is not correct for \x00 < \x01.
+ * NOTE: strcmp is not correct for \x00 < \x01, but
+ * that is unlikely to occur here. We could use the
+ * TclUtfNCmp2 to handle this.
*/
- int cmpValue;
- s1 = TclGetString(valuePtr);
- s2 = TclGetString(value2Ptr);
- cmpValue = strcmp(s1, s2);
+ int s1len, s2len;
+ s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
+ s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
switch (*pc) {
case INST_EQ:
- iResult = (cmpValue == 0);
+ if (s1len == s2len) {
+ iResult = (strcmp(s1, s2) == 0);
+ } else {
+ iResult = 0;
+ }
break;
case INST_NEQ:
- iResult = (cmpValue != 0);
+ if (s1len == s2len) {
+ iResult = (strcmp(s1, s2) != 0);
+ } else {
+ iResult = 1;
+ }
break;
case INST_LT:
- iResult = (cmpValue < 0);
+ iResult = (strcmp(s1, s2) < 0);
break;
case INST_GT:
- iResult = (cmpValue > 0);
+ iResult = (strcmp(s1, s2) > 0);
break;
case INST_LE:
- iResult = (cmpValue <= 0);
+ iResult = (strcmp(s1, s2) <= 0);
break;
case INST_GE:
- iResult = (cmpValue >= 0);
+ iResult = (strcmp(s1, s2) >= 0);
break;
}
} else if ((t1Ptr == &tclDoubleType)
@@ -3094,7 +3121,7 @@ TclExecuteByteCode(interp, codePtr)
/*
* Reuse the valuePtr object already on stack if possible.
*/
-
+ foundResult:
TRACE(("%.20s %.20s => %ld\n",
O2S(valuePtr), O2S(value2Ptr), iResult));
if (Tcl_IsShared(valuePtr)) {