summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2013-10-03 13:32:06 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2013-10-03 13:32:06 (GMT)
commitf9427cdbfd828dbabe79facdc3d757146c090563 (patch)
tree0fc8c55a7c7074e884924430835fce4b9eaeabcc
parentc9e288f12b7d1802ea33bb58cc546f1a1ce153e1 (diff)
downloadtcl-f9427cdbfd828dbabe79facdc3d757146c090563.zip
tcl-f9427cdbfd828dbabe79facdc3d757146c090563.tar.gz
tcl-f9427cdbfd828dbabe79facdc3d757146c090563.tar.bz2
cleaner and faster 'string trim'
-rw-r--r--generic/tclAssembly.c3
-rw-r--r--generic/tclCompCmdsSZ.c24
-rw-r--r--generic/tclCompile.c5
-rw-r--r--generic/tclCompile.h7
-rw-r--r--generic/tclExecute.c34
5 files changed, 41 insertions, 32 deletions
diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c
index 659f483..44cddba 100644
--- a/generic/tclAssembly.c
+++ b/generic/tclAssembly.c
@@ -462,6 +462,7 @@ static const TalInstDesc TalInstructionTable[] = {
{"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1},
{"strrange", ASSEM_1BYTE, INST_STR_RANGE, 3, 1},
{"strrfind", ASSEM_1BYTE, INST_STR_FIND_LAST, 2, 1},
+ {"strtrim", ASSEM_1BYTE, INST_STRTRIM, 2, 1},
{"strtrimLeft", ASSEM_1BYTE, INST_STRTRIM_LEFT, 2, 1},
{"strtrimRight", ASSEM_1BYTE, INST_STRTRIM_RIGHT, 2, 1},
{"sub", ASSEM_1BYTE, INST_SUB, 2, 1},
@@ -505,7 +506,7 @@ static const unsigned char NonThrowingByteCodes[] = {
INST_NS_CURRENT, /* 151 */
INST_INFO_LEVEL_NUM, /* 152 */
INST_RESOLVE_COMMAND, /* 154 */
- INST_STRTRIM_LEFT, INST_STRTRIM_RIGHT /* 166,167 */
+ INST_STRTRIM, INST_STRTRIM_LEFT, INST_STRTRIM_RIGHT /* 166-168 */
};
/*
diff --git a/generic/tclCompCmdsSZ.c b/generic/tclCompCmdsSZ.c
index 0177b2d..12f6167 100644
--- a/generic/tclCompCmdsSZ.c
+++ b/generic/tclCompCmdsSZ.c
@@ -739,7 +739,6 @@ TclCompileStringTrimCmd(
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr;
- Tcl_Obj *objPtr;
if (parsePtr->numWords != 2 && parsePtr->numWords != 3) {
return TCL_ERROR;
@@ -749,30 +748,11 @@ TclCompileStringTrimCmd(
CompileWord(envPtr, tokenPtr, interp, 1);
if (parsePtr->numWords == 3) {
tokenPtr = TokenAfter(tokenPtr);
- TclNewObj(objPtr);
- if (TclWordKnownAtCompileTime(tokenPtr, objPtr)) {
- int len;
- const char *p = Tcl_GetStringFromObj(objPtr, &len);
-
- PushLiteral(envPtr, p, len);
- OP( STRTRIM_LEFT);
- PushLiteral(envPtr, p, len);
- OP( STRTRIM_RIGHT);
- } else {
- CompileWord(envPtr, tokenPtr, interp, 2);
- OP4( REVERSE, 2);
- OP4( OVER, 1);
- OP( STRTRIM_LEFT);
- OP4( REVERSE, 2);
- OP( STRTRIM_RIGHT);
- }
- TclDecrRefCount(objPtr);
+ CompileWord(envPtr, tokenPtr, interp, 2);
} else {
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
- OP( STRTRIM_LEFT);
- PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
- OP( STRTRIM_RIGHT);
}
+ OP( STRTRIM);
return TCL_OK;
}
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index cdedbda..7e72d84 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -545,6 +545,11 @@ InstructionDesc const tclInstructionTable[] = {
/* Drops an element from the auxiliary stack, popping stack elements
* until the matching stack depth is reached. */
+ {"strtrim", 1, -1, 0, {OPERAND_NONE}},
+ /* [string trim] core: removes the characters (designated by the value
+ * at the top of the stack) from both ends of the string and pushes
+ * the resulting string.
+ * Stack: ... string charset => ... trimmedString */
{"strtrimLeft", 1, -1, 0, {OPERAND_NONE}},
/* [string trimleft] core: removes the characters (designated by the
* value at the top of the stack) from the left of the string and
diff --git a/generic/tclCompile.h b/generic/tclCompile.h
index 08eb393..fa8d773 100644
--- a/generic/tclCompile.h
+++ b/generic/tclCompile.h
@@ -769,11 +769,12 @@ typedef struct ByteCode {
#define INST_EXPAND_DROP 165
/* For compilation of [string trim] and related */
-#define INST_STRTRIM_LEFT 166
-#define INST_STRTRIM_RIGHT 167
+#define INST_STRTRIM 166
+#define INST_STRTRIM_LEFT 167
+#define INST_STRTRIM_RIGHT 168
/* The last opcode */
-#define LAST_INST_OPCODE 167
+#define LAST_INST_OPCODE 168
/*
* Table describing the Tcl bytecode instructions: their name (for displaying
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 83f68fd..8470389 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -5258,19 +5258,41 @@ TEBCresume(
{
const char *string1, *string2;
+ int trim1, trim2;
+ case INST_STRTRIM:
+ valuePtr = OBJ_UNDER_TOS; /* String */
+ value2Ptr = OBJ_AT_TOS; /* TrimSet */
+ string2 = TclGetStringFromObj(value2Ptr, &length2);
+ string1 = TclGetStringFromObj(valuePtr, &length);
+ trim1 = TclTrimLeft(string1, length, string2, length2);
+ if (trim1 < length) {
+ trim2 = TclTrimRight(string1, length, string2, length2);
+ } else {
+ trim2 = 0;
+ }
+ if (trim1 == 0 && trim2 == 0) {
+ TRACE_WITH_OBJ(("\"%.30s\" \"%.30s\" => ", valuePtr, value2Ptr),
+ valuePtr);
+ NEXT_INST_F(1, 1, 0);
+ } else {
+ objResultPtr = Tcl_NewStringObj(string1+trim1, length-trim1-trim2);
+ TRACE_WITH_OBJ(("\"%.30s\" \"%.30s\" => ", valuePtr, value2Ptr),
+ objResultPtr);
+ NEXT_INST_F(1, 2, 1);
+ }
case INST_STRTRIM_LEFT:
valuePtr = OBJ_UNDER_TOS; /* String */
value2Ptr = OBJ_AT_TOS; /* TrimSet */
string2 = TclGetStringFromObj(value2Ptr, &length2);
string1 = TclGetStringFromObj(valuePtr, &length);
- match = TclTrimLeft(string1, length, string2, length2);
- if (match == 0) {
+ trim1 = TclTrimLeft(string1, length, string2, length2);
+ if (trim1 == 0) {
TRACE_WITH_OBJ(("\"%.30s\" \"%.30s\" => ", valuePtr, value2Ptr),
valuePtr);
NEXT_INST_F(1, 1, 0);
} else {
- objResultPtr = Tcl_NewStringObj(string1+match, length-match);
+ objResultPtr = Tcl_NewStringObj(string1+trim1, length-trim1);
TRACE_WITH_OBJ(("\"%.30s\" \"%.30s\" => ", valuePtr, value2Ptr),
objResultPtr);
NEXT_INST_F(1, 2, 1);
@@ -5280,11 +5302,11 @@ TEBCresume(
value2Ptr = OBJ_AT_TOS; /* TrimSet */
string2 = TclGetStringFromObj(value2Ptr, &length2);
string1 = TclGetStringFromObj(valuePtr, &length);
- match = TclTrimRight(string1, length, string2, length2);
- if (match == 0) {
+ trim2 = TclTrimRight(string1, length, string2, length2);
+ if (trim2 == 0) {
NEXT_INST_F(1, 1, 0);
} else {
- objResultPtr = Tcl_NewStringObj(string1, length-match);
+ objResultPtr = Tcl_NewStringObj(string1, length-trim2);
NEXT_INST_F(1, 2, 1);
}
}