summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2011-08-23 17:00:54 (GMT)
committerdgp <dgp@users.sourceforge.net>2011-08-23 17:00:54 (GMT)
commit1e48d43ca28b379e168704d6206091af3472bfc4 (patch)
tree5bf7b690d66e1eb2f0c3f84b7a4cce881c3320fb
parentfe0b615064efb673ddf7e8d4f1d934aaabda0cd1 (diff)
parent89a784543529aa3a56cdc0037e5f8ef7ab6d37a4 (diff)
downloadtcl-1e48d43ca28b379e168704d6206091af3472bfc4.zip
tcl-1e48d43ca28b379e168704d6206091af3472bfc4.tar.gz
tcl-1e48d43ca28b379e168704d6206091af3472bfc4.tar.bz2
Revert the [string reverse] rewrite in a branch for more review.
-rw-r--r--ChangeLog4
-rw-r--r--generic/tclStringObj.c160
2 files changed, 80 insertions, 84 deletions
diff --git a/ChangeLog b/ChangeLog
index bc323fa..b927a2e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,10 +2,6 @@
* generic/tclIORChan.c: [Bug 3396948] Leak of ReflectedChannelMap.
-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 993a694..ab62359 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -2657,96 +2657,96 @@ Tcl_Obj *
TclStringObjReverse(
Tcl_Obj *objPtr)
{
- char *src, *dest;
- Tcl_Obj *resultPtr = objPtr;
- char c;
+ String *stringPtr;
+ char *src = NULL, *dest = NULL;
+ Tcl_UniChar *usrc = NULL, *udest = NULL;
+ Tcl_Obj *resultPtr = NULL;
- 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;
- }
+ SetStringFromAny(NULL, objPtr);
+ stringPtr = GET_STRING(objPtr);
- src = dest + objPtr->length;
+ 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.
+ */
- /* 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;
- }
- 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;
+ 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;
}
-#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;
+
+ /*
+ * Unshared. Reverse objPtr->bytes in place.
+ */
+
+ dest = objPtr->bytes;
+ src = dest + objPtr->length - 1;
+ while (dest < src) {
+ char tmp = *src;
+
+ *src-- = *dest;
+ *dest++ = tmp;
}
+ return objPtr;
}
+ FillUnicodeRep(objPtr);
+ stringPtr = GET_STRING(objPtr);
+ }
+ if (stringPtr->numChars <= 1) {
+ return objPtr;
}
- /* Pass 2: Reverse byte string. */
- dest = TclGetString(resultPtr);
+ /*
+ * 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.
+ */
- while (dest < --src) {
- c = *src;
- *src = *dest;
- *dest++ = c;
+ 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--;
}
- return resultPtr;
+ 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;
}
/*