summaryrefslogtreecommitdiffstats
path: root/generic/tclListObj.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2018-03-30 19:37:21 (GMT)
committerdgp <dgp@users.sourceforge.net>2018-03-30 19:37:21 (GMT)
commit27f230c6bf59b38ce4490468093692084b37e7f0 (patch)
tree2050aeef5fc61a89ba60704afa30ca71a2736918 /generic/tclListObj.c
parentbe8b7d25f6ed27943242888bf395ea2aa50632ae (diff)
parenta5d6e9657a73455c2b0163d64a0fd0938962849b (diff)
downloadtcl-27f230c6bf59b38ce4490468093692084b37e7f0.zip
tcl-27f230c6bf59b38ce4490468093692084b37e7f0.tar.gz
tcl-27f230c6bf59b38ce4490468093692084b37e7f0.tar.bz2
merge 8.7
Diffstat (limited to 'generic/tclListObj.c')
-rw-r--r--generic/tclListObj.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index a312f4c..2078989 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -446,6 +446,87 @@ TclListObjCopy(
/*
*----------------------------------------------------------------------
*
+ * TclListObjRange --
+ *
+ * Makes a slice of a list value.
+ * *listPtr must be known to be a valid list.
+ *
+ * Results:
+ * Returns a pointer to the sliced list.
+ * This may be a new object or the same object if not shared.
+ *
+ * Side effects:
+ * The possible conversion of the object referenced by listPtr
+ * to a list object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclListObjRange(
+ Tcl_Obj *listPtr, /* List object to take a range from. */
+ int fromIdx, /* Index of first element to include. */
+ int toIdx) /* Index of last element to include. */
+{
+ Tcl_Obj **elemPtrs;
+ int listLen, i, newLen;
+ List *listRepPtr;
+
+ TclListObjGetElements(NULL, listPtr, &listLen, &elemPtrs);
+
+ if (fromIdx < 0) {
+ fromIdx = 0;
+ }
+ if (toIdx >= listLen) {
+ toIdx = listLen-1;
+ }
+ if (fromIdx > toIdx) {
+ return Tcl_NewObj();
+ }
+
+ newLen = toIdx - fromIdx + 1;
+
+ if (Tcl_IsShared(listPtr) ||
+ ((ListRepPtr(listPtr)->refCount > 1))) {
+ return Tcl_NewListObj(newLen, &elemPtrs[fromIdx]);
+ }
+
+ /*
+ * In-place is possible.
+ */
+
+ /*
+ * Even if nothing below cause any changes, we still want the
+ * string-canonizing effect of [lrange 0 end].
+ */
+
+ TclInvalidateStringRep(listPtr);
+
+ /*
+ * Delete elements that should not be included.
+ */
+
+ for (i = 0; i < fromIdx; i++) {
+ TclDecrRefCount(elemPtrs[i]);
+ }
+ for (i = toIdx + 1; i < listLen; i++) {
+ TclDecrRefCount(elemPtrs[i]);
+ }
+
+ if (fromIdx > 0) {
+ memmove(elemPtrs, &elemPtrs[fromIdx],
+ (size_t) newLen * sizeof(Tcl_Obj*));
+ }
+
+ listRepPtr = ListRepPtr(listPtr);
+ listRepPtr->elemCount = newLen;
+
+ return listPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_ListObjGetElements --
*
* This function returns an (objc,objv) array of the elements in a list