summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclStringObj.c44
-rw-r--r--tests/string.test8
2 files changed, 45 insertions, 7 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index 33b2139..bdc9c99 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -2899,6 +2899,9 @@ TclStringReverse(
{
String *stringPtr;
Tcl_UniChar ch = 0;
+#if TCL_UTF_MAX <= 4
+ int needFlip = 0;
+#endif
if (TclIsPureByteArray(objPtr)) {
int numBytes;
@@ -2917,10 +2920,9 @@ TclStringReverse(
if (stringPtr->hasUnicode) {
Tcl_UniChar *from = Tcl_GetUnicode(objPtr);
Tcl_UniChar *src = from + stringPtr->numChars;
+ Tcl_UniChar *to;
if (Tcl_IsShared(objPtr)) {
- Tcl_UniChar *to;
-
/*
* Create a non-empty, pure unicode value, so we can coax
* Tcl_SetObjLength into growing the unicode rep buffer.
@@ -2930,19 +2932,54 @@ TclStringReverse(
Tcl_SetObjLength(objPtr, stringPtr->numChars);
to = Tcl_GetUnicode(objPtr);
while (--src >= from) {
+#if TCL_UTF_MAX <= 4
+ ch = *src;
+ if ((ch & 0xF800) == 0xD800) {
+ needFlip = 1;
+ }
+ *to++ = ch;
+#else
*to++ = *src;
+#endif
}
} else {
/*
* Reversing in place.
*/
+#if TCL_UTF_MAX <= 4
+ to = src;
+#endif
while (--src > from) {
ch = *src;
+#if TCL_UTF_MAX <= 4
+ if ((ch & 0xF800) == 0xD800) {
+ needFlip = 1;
+ }
+#endif
*src = *from;
*from++ = ch;
}
}
+#if TCL_UTF_MAX <= 4
+ if (needFlip) {
+ /*
+ * Flip back surrogate pairs.
+ */
+
+ from = to - stringPtr->numChars;
+ while (--to >= from) {
+ ch = *to;
+ if ((ch & 0xFC00) == 0xD800) {
+ if ((to-1 >= from) && ((to[-1] & 0xFC00) == 0xDC00)) {
+ to[0] = to[-1];
+ to[-1] = ch;
+ --to;
+ }
+ }
+ }
+ }
+#endif
}
if (objPtr->bytes) {
@@ -2968,6 +3005,7 @@ TclStringReverse(
int charCount = 0;
int bytesLeft = numBytes;
+ int chw;
while (bytesLeft) {
/*
@@ -2976,7 +3014,7 @@ TclStringReverse(
* skip calling Tcl_UtfCharComplete() here.
*/
- int bytesInChar = TclUtfToUniChar(from, &ch);
+ int bytesInChar = TclUtfToUCS4(from, &chw);
ReverseBytes((unsigned char *)to, (unsigned char *)from,
bytesInChar);
diff --git a/tests/string.test b/tests/string.test
index 3ac3060..66eb6ad 100644
--- a/tests/string.test
+++ b/tests/string.test
@@ -1828,19 +1828,19 @@ test string-24.15 {string reverse command - pure bytearray} {
binary scan [tcl::string::reverse [binary format H* 010203]] H* x
set x
} 030201
-test string-24.16 {string reverse command - surrogates} knownBug {
+test string-24.16 {string reverse command - surrogates} {
string reverse \u0444bulb\uD83D\uDE02
} \uD83D\uDE02blub\u0444
-test string-24.17 {string reverse command - surrogates} knownBug {
+test string-24.17 {string reverse command - surrogates} {
string reverse \uD83D\uDE02hello\uD83D\uDE02
} \uD83D\uDE02olleh\uD83D\uDE02
-test string-24.18 {string reverse command - surrogates} knownBug {
+test string-24.18 {string reverse command - surrogates} {
set s \u0444bulb\uD83D\uDE02
# shim shimmery ...
string index $s 0
string reverse $s
} \uD83D\uDE02blub\u0444
-test string-24.19 {string reverse command - surrogates} knownBug {
+test string-24.19 {string reverse command - surrogates} {
set s \uD83D\uDE02hello\uD83D\uDE02
# shim shimmery ...
string index $s 0