summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--generic/tclStringObj.c160
-rw-r--r--generic/tclTest.c8
3 files changed, 88 insertions, 84 deletions
diff --git a/ChangeLog b/ChangeLog
index 5e7821a..36cf7f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2011-08-23 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * generic/tclStringObj.c: [FRQ 3396731] inline string reverse
+
2011-08-19 Don Porter <dgp@users.sourceforge.net>
* generic/tclIORTrans.c: [Bugs 3393279, 3393280] ReflectClose(.) is
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index ab62359..993a694 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -2657,96 +2657,96 @@ Tcl_Obj *
TclStringObjReverse(
Tcl_Obj *objPtr)
{
- String *stringPtr;
- char *src = NULL, *dest = NULL;
- Tcl_UniChar *usrc = NULL, *udest = NULL;
- Tcl_Obj *resultPtr = NULL;
+ char *src, *dest;
+ Tcl_Obj *resultPtr = objPtr;
+ char c;
- SetStringFromAny(NULL, objPtr);
- stringPtr = GET_STRING(objPtr);
+ src = TclGetString(objPtr);
+ if (Tcl_IsShared(objPtr)) {
+ resultPtr = Tcl_NewObj();
+ Tcl_SetObjLength(resultPtr, objPtr->length);
+ dest = TclGetString(resultPtr);
+ memcpy(dest, src, objPtr->length);
+ } else {
+ TclFreeIntRep(objPtr);
+ dest = src;
+ }
- if (stringPtr->hasUnicode == 0) {
- if (stringPtr->numChars == -1) {
- TclNumUtfChars(stringPtr->numChars, objPtr->bytes, objPtr->length);
- }
- if (stringPtr->numChars <= 1) {
- return objPtr;
- }
- if (stringPtr->numChars == objPtr->length) {
- /*
- * All one-byte chars. Reverse in objPtr->bytes.
- */
+ src = dest + objPtr->length;
- if (Tcl_IsShared(objPtr)) {
- resultPtr = Tcl_NewObj();
- Tcl_SetObjLength(resultPtr, objPtr->length);
- dest = TclGetString(resultPtr);
- src = objPtr->bytes + objPtr->length - 1;
- while (src >= objPtr->bytes) {
- *dest++ = *src--;
- }
- return resultPtr;
+ /* Pass 1: reverse individual bytes of UTF-8 representation. */
+ while (dest < src) {
+ Tcl_UniChar ch = 0;
+ switch (Tcl_UtfToUniChar(dest, &ch)) {
+ case 1: {
+ ++dest;
+ break;
}
-
- /*
- * Unshared. Reverse objPtr->bytes in place.
- */
-
- dest = objPtr->bytes;
- src = dest + objPtr->length - 1;
- while (dest < src) {
- char tmp = *src;
-
- *src-- = *dest;
- *dest++ = tmp;
+ case 2: {
+ c = dest[0];
+ dest[0] = dest[1];
+ dest[1] = c;
+ dest += 2;
+ break;
+ }
+ case 3: {
+ c = dest[0];
+ dest[0] = dest[2];
+ dest[2] = c;
+ dest += 3;
+ break;
+ }
+#if TCL_UTF_MAX > 4
+ case 5: {
+ c = dest[0];
+ dest[0] = dest[4];
+ dest[4] = c;
+ c = dest[1];
+ dest[1] = dest[3];
+ dest[3] = c;
+ dest += 5;
+ break;
+ }
+#endif
+#if TCL_UTF_MAX > 5
+ case 6: {
+ c = dest[0];
+ dest[0] = dest[5];
+ dest[5] = c;
+ c = dest[1];
+ dest[1] = dest[4];
+ dest[4] = c;
+ c = dest[0];
+ dest[2] = dest[3];
+ dest[3] = c;
+ dest += 6;
+ break;
+ }
+#endif
+ default: {
+#if TCL_UTF_MAX > 3
+ c = dest[0];
+ dest[0] = dest[3];
+ dest[3] = c;
+ c = dest[1];
+ dest[1] = dest[2];
+ dest[2] = c;
+ dest += 4;
+#endif
+ break;
}
- return objPtr;
}
- FillUnicodeRep(objPtr);
- stringPtr = GET_STRING(objPtr);
- }
- if (stringPtr->numChars <= 1) {
- return objPtr;
}
- /*
- * Reverse the Unicode rep.
- */
-
- if (Tcl_IsShared(objPtr)) {
- Tcl_UniChar ch = 0;
-
- /*
- * Create a non-empty, pure unicode value, so we can coax
- * Tcl_SetObjLength into growing the unicode rep buffer.
- */
+ /* Pass 2: Reverse byte string. */
+ dest = TclGetString(resultPtr);
- resultPtr = Tcl_NewUnicodeObj(&ch, 1);
- Tcl_SetObjLength(resultPtr, stringPtr->numChars);
- udest = Tcl_GetUnicode(resultPtr);
- usrc = stringPtr->unicode + stringPtr->numChars - 1;
- while (usrc >= stringPtr->unicode) {
- *udest++ = *usrc--;
+ while (dest < --src) {
+ c = *src;
+ *src = *dest;
+ *dest++ = c;
}
- return resultPtr;
- }
-
- /*
- * Unshared. Reverse objPtr->bytes in place.
- */
-
- udest = stringPtr->unicode;
- usrc = udest + stringPtr->numChars - 1;
- while (udest < usrc) {
- Tcl_UniChar tmp = *usrc;
-
- *usrc-- = *udest;
- *udest++ = tmp;
- }
-
- TclInvalidateStringRep(objPtr);
- stringPtr->allocated = 0;
- return objPtr;
+ return resultPtr;
}
/*
diff --git a/generic/tclTest.c b/generic/tclTest.c
index 3e3bc09..96dcb36 100644
--- a/generic/tclTest.c
+++ b/generic/tclTest.c
@@ -799,7 +799,7 @@ TestasyncCmd(
asyncPtr->id = nextId;
nextId++;
asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc,
- (ClientData) asyncPtr->id);
+ INT2PTR(asyncPtr->id));
asyncPtr->nextPtr = firstHandler;
firstHandler = asyncPtr;
Tcl_MutexUnlock(&asyncTestMutex);
@@ -870,7 +870,7 @@ TestasyncCmd(
if (asyncPtr->id == id) {
Tcl_ThreadId threadID;
if (Tcl_CreateThread(&threadID, AsyncThreadProc,
- (ClientData) id, TCL_THREAD_STACK_DEFAULT,
+ INT2PTR(id), TCL_THREAD_STACK_DEFAULT,
TCL_THREAD_NOFLAGS) != TCL_OK) {
Tcl_SetResult(interp, "can't create thread", TCL_STATIC);
return TCL_ERROR;
@@ -901,7 +901,7 @@ AsyncHandlerProc(
int code) /* Current return code from command. */
{
TestAsyncHandler *asyncPtr;
- int id = (int) clientData;
+ int id = PTR2INT(clientData);
const char *listArgv[4], *cmd;
char string[TCL_INTEGER_SPACE];
@@ -958,7 +958,7 @@ AsyncThreadProc(
* TestAsyncHandler, defined above. */
{
TestAsyncHandler *asyncPtr;
- int id = (int) clientData;
+ int id = PTR2INT(clientData);
Tcl_Sleep(1);
Tcl_MutexLock(&asyncTestMutex);