diff options
author | dgp <dgp@users.sourceforge.net> | 2018-03-30 19:37:21 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2018-03-30 19:37:21 (GMT) |
commit | 27f230c6bf59b38ce4490468093692084b37e7f0 (patch) | |
tree | 2050aeef5fc61a89ba60704afa30ca71a2736918 /generic/tclListObj.c | |
parent | be8b7d25f6ed27943242888bf395ea2aa50632ae (diff) | |
parent | a5d6e9657a73455c2b0163d64a0fd0938962849b (diff) | |
download | tcl-27f230c6bf59b38ce4490468093692084b37e7f0.zip tcl-27f230c6bf59b38ce4490468093692084b37e7f0.tar.gz tcl-27f230c6bf59b38ce4490468093692084b37e7f0.tar.bz2 |
merge 8.7
Diffstat (limited to 'generic/tclListObj.c')
-rw-r--r-- | generic/tclListObj.c | 81 |
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 |