summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--generic/tclStringObj.c160
2 files changed, 84 insertions, 80 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;
}
/*