summaryrefslogtreecommitdiffstats
path: root/generic/tclStringObj.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2007-03-28 19:03:41 (GMT)
committerdgp <dgp@users.sourceforge.net>2007-03-28 19:03:41 (GMT)
commitf0dcf496f096fd97761a4392ff77c13f9eb49707 (patch)
tree5e6ea6dfc617bfe467971c624cb6c9218f9eb92c /generic/tclStringObj.c
parent2ef27f98192e8690ab3b297accafe52001b24014 (diff)
downloadtcl-f0dcf496f096fd97761a4392ff77c13f9eb49707.zip
tcl-f0dcf496f096fd97761a4392ff77c13f9eb49707.tar.gz
tcl-f0dcf496f096fd97761a4392ff77c13f9eb49707.tar.bz2
* generic/tclCmdMZ.c (STR_REVERSE): Implement the actual
[string reverse] command in terms of the new TclStringObjReverse() routine. * generic/tclInt.h (TclStringObjReverse): New internal routine * generic/tclStringObj.c (TclStringObjReverse): that implements the [string reverse] operation, making use of knowledge/surgery of the String intrep to minimize the number of allocs and copies needed to do the job.
Diffstat (limited to 'generic/tclStringObj.c')
-rw-r--r--generic/tclStringObj.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index f3aa3ab..2ab51fb 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -33,7 +33,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclStringObj.c,v 1.64 2007/03/21 18:02:51 dgp Exp $ */
+ * RCS: @(#) $Id: tclStringObj.c,v 1.65 2007/03/28 19:03:42 dgp Exp $ */
#include "tclInt.h"
#include "tommath.h"
@@ -2519,6 +2519,88 @@ Tcl_ObjPrintf(
/*
*---------------------------------------------------------------------------
*
+ * TclStringObjReverse --
+ *
+ * Implements the [string reverse] operation.
+ *
+ * Results:
+ * An unshared Tcl value which is the [string reverse] of the argument
+ * supplied. When sharing rules permit, the returned value might be
+ * the argument with modifications done in place.
+ *
+ * Side effects:
+ * May allocate a new Tcl_Obj.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclStringObjReverse(
+ Tcl_Obj *objPtr)
+{
+ String *stringPtr;
+ int numChars = Tcl_GetCharLength(objPtr);
+ int i = 0, lastCharIdx = numChars - 1;
+ char *bytes;
+
+ if (numChars <= 1) {
+ return objPtr;
+ }
+
+ stringPtr = GET_STRING(objPtr);
+ if (stringPtr->hasUnicode) {
+ Tcl_UniChar *source = stringPtr->unicode;
+
+ if (Tcl_IsShared(objPtr)) {
+ Tcl_UniChar *dest, ch = 0;
+
+ /*
+ * Create a non-empty, pure unicode value, so we can coax
+ * Tcl_SetObjLength into growing the unicode rep buffer.
+ */
+
+ Tcl_Obj *resultPtr = Tcl_NewUnicodeObj(&ch, 1);
+ Tcl_SetObjLength(resultPtr, numChars);
+ dest = Tcl_GetUnicode(resultPtr);
+
+ while (i < numChars) {
+ dest[i++] = source[lastCharIdx--];
+ }
+ return resultPtr;
+ }
+
+ while (i < lastCharIdx) {
+ Tcl_UniChar tmp = source[lastCharIdx];
+ source[lastCharIdx--] = source[i];
+ source[i++] = tmp;
+ }
+ Tcl_InvalidateStringRep(objPtr);
+ return objPtr;
+ }
+
+ bytes = Tcl_GetString(objPtr);
+ if (Tcl_IsShared(objPtr)) {
+ char *dest;
+ Tcl_Obj *resultPtr = Tcl_NewObj();
+ Tcl_SetObjLength(resultPtr, numChars);
+ dest = Tcl_GetString(resultPtr);
+ while (i < numChars) {
+ dest[i++] = bytes[lastCharIdx--];
+ }
+ return resultPtr;
+ }
+
+ while (i < lastCharIdx) {
+ char tmp = bytes[lastCharIdx];
+ bytes[lastCharIdx--] = bytes[i];
+ bytes[i++] = tmp;
+ }
+ return objPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
* FillUnicodeRep --
*
* Populate the Unicode internal rep with the Unicode form of its string