Tcl_ListObj(3)
β¨ NAME β¨
okay so bestie, welcome to Tcl_ListObj(3) from the Tcl Library Procedures β this is part 1 of 3, and it is literally the group chat for manipulating Tcl values as lists. The whole squad is:
Tcl_ListObjAppendListTcl_ListObjAppendElementTcl_NewListObjTcl_SetListObjTcl_ListObjGetElementsTcl_ListObjLengthTcl_ListObjIndexTcl_ListObjReplaceTcl_ListObjRangeTcl_ListObjRepeatTcl_ListObjReverse
No cap, that is the entire list-ops friend group.
π¦ SYNOPSIS π¦
#include <tcl.h>
int
Tcl_ListObjAppendList(interp, listPtr, elemListPtr)
int
Tcl_ListObjAppendElement(interp, listPtr, objPtr)
Tcl_Obj *
Tcl_NewListObj(objc, objv)
Tcl_SetListObj(objPtr, objc, objv)
int
Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr)
int
Tcl_ListObjLength(interp, listPtr, lengthPtr)
int
Tcl_ListObjIndex(interp, listPtr, index, objPtrPtr)
int
Tcl_ListObjReplace(interp, listPtr, first, count, objc, objv)
int
Tcl_ListObjRange(interp, listPtr, first, last, objPtrPtr)
int
Tcl_ListObjRepeat(interp, count, objc, objv, objPtrPtr)
int
Tcl_ListObjReverse(interp, listPtr, objPtrPtr)
π ARGUMENTS π
here is the cast, bestie β every type, every caveat, every little detail kept intact. periodt.
Tcl_Interp *interp(in) β if an error happens while converting a value to be a list value, an error message gets left in the interpreter's result value unlessinterpisNULL. iykyk.Tcl_Obj *listPtr(in/out) β points to the input list value. IflistPtrdoes not already point to a list value, an attempt will be made to convert it to one. Some functions may store a reference to it internally, so care must be taken when managing its reference count. See the REFERENCE COUNT MANAGEMENT section below, okay? do not skip that part.Tcl_Obj *elemListPtr(in/out) β forTcl_ListObjAppendList, this points to a list value containing elements to be appended ontolistPtr. Each element of*elemListPtrwill become a new element oflistPtr. If*elemListPtris notNULLand does not already point to a list value, an attempt will be made to convert it to one. slay.Tcl_Obj *objPtr(in) β forTcl_ListObjAppendElement, points to the Tcl value that will be appended tolistPtr. ForTcl_SetListObj, this points to the Tcl value that will be converted to a list value containing theobjcelements of the array referenced byobjv. two jobs, one argument.Tcl_Size | int *objcPtr(in) β points to the location whereTcl_ListObjGetElementsstores the number of element values inlistPtr. May be(Tcl_Size *)NULLwhen not used. If it points to a variable whose type is notTcl_Size, a compiler warning will be generated. If your extension is compiled with-DTCL_8_API, this function will returnNULLfor lists with more thanINT_MAXelements (which should trigger proper error-handling); otherwise expect it to crash. bestie, that crash warning is not a vibe.Tcl_Obj ***objvPtr(out) β a location whereTcl_ListObjGetElementsstores a pointer to an array of pointers to the element values oflistPtr. pointer-to-pointer-to-pointer energy, honestly iconic.Tcl_Size objc(in) β the number of Tcl values in theobjvarray.Tcl_Obj *const *objv(in) β an array of pointers to Tcl values.Tcl_Size | int *lengthPtr(out) β points to the location whereTcl_ListObjLengthstores the length of the list. May be(Tcl_Size *)NULLwhen not used. If it points to a variable whose type is notTcl_Size, a compiler warning will be generated. If your extension is compiled with-DTCL_8_API, this function will returnTCL_ERRORfor lists with more thanINT_MAXelements (which should trigger proper error-handling); otherwise expect it to crash. again: crash warning. handle it.Tcl_Size index(in) β index of the list element thatTcl_ListObjIndexis to return. The first element has index0. zero-based, obviously.Tcl_Obj **objPtrPtr(out) β points to a location to store an output list or element value. No assumptions should be made about the reference count of the returned value. See the REFERENCE COUNT MANAGEMENT section below. refcount girlies, stay alert.Tcl_Size first(in) β index of the first element in a range of elements in a list.Tcl_Size last(in) β index of the last element in a range of elements in a list.Tcl_Size count(in) β the number of elements to be operated on or a repetition count. context-dependent queen.
π DESCRIPTION π
okay so bestie, here's the tea: Tcl list values have an internal representation that's built for efficient indexing and appending β like, the whole point. And all the procedures on this page are how you create, modify, access, and transform Tcl list values from C code. Coder girl summer, fr fr. π
πΈ Appending stuff (the glow-up arc)
Tcl_ListObjAppendList and Tcl_ListObjAppendElement both add one or more values to the end of the list value referenced by listPtr. The difference?
Tcl_ListObjAppendListappends each element of the list value referenced by elemListPtr (so, a whole squad π )Tcl_ListObjAppendElementappends the single value referenced by objPtr (just the one main character)
Both procedures will convert the value referenced by listPtr to a list value if necessary. If an error occurs during conversion, both return TCL_ERROR and leave an error message in the interpreter's result value if interp is not NULL. π
Same energy for elemListPtr: if it doesn't already refer to a list value, Tcl_ListObjAppendList will attempt to convert it to one, and if an error occurs during conversion, it will return TCL_ERROR and leave an error message in the interpreter's result value if interp is not NULL.
Both procedures invalidate any old string representation of listPtr and, if it was converted to a list value, free any old internal representation. Similarly, Tcl_ListObjAppendList frees any old internal representation of elemListPtr if it converts it to a list value.
After appending each element in elemListPtr, Tcl_ListObjAppendList increments the element's reference count β because listPtr now also refers to it, bestie, it's a whole shared custody situation π«Ά. For the same reason, Tcl_ListObjAppendElement increments objPtr's reference count.
If no error occurs, the two procedures return TCL_OK after appending the values. Slay. β¨
π Making new lists / resetting old ones
Tcl_NewListObj and Tcl_SetListObj create a new value or modify an existing value to hold the objc elements of the array referenced by objv, where each element is a pointer to a Tcl value.
- If objc is less than or equal to zero, they return an empty value.
- If objv is
NULL, the resulting list contains 0 elements, with reserved space in an internal representation for objc more elements (to avoid its reallocation later β forward thinking, iconic π ). - The new value's string representation is left invalid.
- The two procedures increment the reference counts of the elements in objc since the list value now refers to them.
- The new list value returned by
Tcl_NewListObjhas reference count zero.
π¦ Reading lists
Tcl_ListObjGetElements returns a count and a pointer to an array of the elements in a list value. It returns the count by storing it in the address objcPtr. Similarly, it returns the array pointer by storing it in the address objvPtr.
β οΈ The memory pointed to is managed by Tcl and should not be freed or written to by the caller. Hands off, it's not yours, no cap.
- If the list is empty,
0is stored at objcPtr andNULLat objvPtr. - If objcPtr points to a variable of type
intand the list contains more than2**31elements, the function returnsTCL_ERROR. - If listPtr is not already a list value,
Tcl_ListObjGetElementswill attempt to convert it to one; if the conversion fails, it returnsTCL_ERRORand leaves an error message in the interpreter's result value if interp is notNULL. - Otherwise it returns
TCL_OKafter storing the count and array pointer.
Tcl_ListObjLength returns the number of elements in the list value referenced by listPtr. If the value is not already a list value, Tcl_ListObjLength will attempt to convert it to one; if the conversion fails, it returns TCL_ERROR and leaves an error message in the interpreter's result value if interp is not NULL. Otherwise it returns TCL_OK after storing the list's length. Just a little length check, we love a quick vibe check. π
Tcl_ListObjIndex returns a pointer to the value at element index in the list referenced by listPtr. It returns this value by storing a pointer to it in the address objPtrPtr.
If listPtr does not already refer to a list value, Tcl_ListObjIndex will attempt to convert it to one; if the conversion fails, it returns TCL_ERROR and leaves an error message in the interpreter's result value if interp is not NULL.
If the index is out of range β that is, index is negative or greater than or equal to the number of elements in the list β Tcl_ListObjIndex stores a NULL in objPtrPtr and returns TCL_OK. Otherwise it returns TCL_OK after storing the element's value pointer.
π Big important caveat: the reference count for the list element is not incremented. The caller must do that if it needs to retain a pointer to the element, or "bounce" the reference count when the element is no longer needed. This is because a returned element may have a reference count of 0.
Abstract Lists create a new element Obj on demand, and do not retain any element Obj values. Therefore, the caller is responsible for freeing the element when it is no longer needed. Note that this is a change from Tcl 8 where all list elements always have a reference count of at least 1. (See ABSTRACT LIST TYPES, STORAGE MANAGEMENT OF VALUES, Tcl_BounceRefCount(3), and lseq(n) for more information.) iykyk π§
π₯ Replacing elements
Tcl_ListObjReplace replaces zero or more elements of the list referenced by listPtr with the objc values in the array referenced by objv.
If listPtr does not point to a list value, Tcl_ListObjReplace will attempt to convert it to one; if the conversion fails, it returns TCL_ERROR and leaves an error message in the interpreter's result value if interp is not NULL. Otherwise, it returns TCL_OK after replacing the values.
Here's the rules of the game, bestie:
- If objv is
NULL, no new elements are added. - If the argument first is zero or negative, it refers to the first element.
- If first is greater than or equal to the number of elements in the list, then no elements are deleted; the new elements are appended to the list.
- count gives the number of elements to replace.
- If count is zero or negative then no elements are deleted; the new elements are simply inserted before the one designated by first.
Tcl_ListObjReplaceinvalidates listPtr's old string representation.- The reference counts of any elements inserted from objv are incremented since the resulting list now refers to them.
- Similarly, the reference counts for any replaced values are decremented.
Because Tcl_ListObjReplace combines both element insertion and deletion, it can be used to implement a number of list operations. For example, the following code inserts the objc values referenced by the array of value pointers objv just before the element index of the list referenced by listPtr:
result = Tcl_ListObjReplace(interp, listPtr, index, 0,
objc, objv);
Similarly, the following code appends the objc values referenced by the array objv to the end of the list listPtr:
result = Tcl_ListObjLength(interp, listPtr, &length);
if (result == TCL_OK) {
result = Tcl_ListObjReplace(interp, listPtr, length, 0,
objc, objv);
}
The count list elements starting at first can be deleted by simply calling Tcl_ListObjReplace with a NULL objvPtr:
result = Tcl_ListObjReplace(interp, listPtr, first, count,
0, NULL);
π Range, Repeat, Reverse (the fun trio)
Tcl_ListObjRange stores in objPtrPtr a pointer to a list value containing all elements in the passed input list listPtr at indices between first and last, both inclusive. An empty list is returned in the case of first being greater than last.
Tcl_ListObjRepeat stores in objPtrPtr a pointer to a list value whose elements are the objc elements passed in objv, repeated count number of times. An error is raised if count is negative. π
Tcl_ListObjReverse stores in objPtrPtr a pointer to a list value containing all elements of the input list listPtr in reverse order. (Yes queen, backwards but make it fashion. π)
For all three functions β Tcl_ListObjRange, Tcl_ListObjRepeat and Tcl_ListObjReverse β the value passed in listPtr need not be unshared. The pointer stored at objPtrPtr is guaranteed to be different from listPtr but no assumptions should be made about its reference count.
π In case of errors, the location addressed by objPtrPtr may have been modified and should be treated by the caller as undefined. Do not touch it, do not trust it, do not look at it.
π«Ά REFERENCE COUNT MANAGEMENT π«Ά
Care must be taken by callers when managing the reference count of values passed in as well as values returned from the above functions. This is the part where you have to actually pay attention, bestie. π
Unless specified otherwise below, the above functions may internally keep a reference to the value passed in listPtr and increment its reference count. Therefore:
- If listPtr is newly allocated and has a zero reference count, it should not be freed after the call with
Tcl_DecrRefCount. Rather, useTcl_BounceRefCountinstead. - Furthermore, if listPtr was retrieved from the interpreter result (e.g. via
Tcl_GetObjResult) and that is the only reference to the value, it may be deleted if a function sets the interpreter result on error. - The more general and safe method for passing values is to increment their reference counts with
Tcl_IncrRefCountprior to the call and release them withTcl_DecrRefCountwhen the call returns. However, this may preclude certain optimizations based on modifying unshared values in-place.
Tcl_NewListObj always returns a zero-reference object, much like Tcl_NewObj. If a non-NULL objv argument is given, the reference counts of the first objc values in that array are incremented.
Tcl_SetListObj does not modify the reference count of its objPtr argument, but does require that the object be unshared. The reference counts of the first objc values in the objv array are incremented.
Tcl_ListObjGetElements, Tcl_ListObjIndex, and Tcl_ListObjLength do not modify the reference count of the listPtr argument except on error when the interpreter result holds a reference to it as described earlier.
Tcl_ListObjAppendList, Tcl_ListObjAppendElement, and Tcl_ListObjReplace require an unshared listPtr argument.
Tcl_ListObjAppendListonly reads its elemListPtr argument.Tcl_ListObjAppendElementincrements the reference count of its objPtr on success.Tcl_ListObjReplaceincrements the reference count of the first objc values in the objv array on success.- Note that the same caveat stated earlier applies if the interpreter result holds a reference to listPtr.
The pointer to a result value returned in objPtrPtr by the functions Tcl_ListObjRange, Tcl_ListObjRepeat and Tcl_ListObjReverse is guaranteed to be different from the listPtr passed in. It is therefore safe to manage its reference count independently from that of listPtr.
No assumptions should be made about its reference count and the standard reference counting idiom should be followed. The caller can pass it to a function such as Tcl_SetObjResult, Tcl_ListObjAppendElement etc. which take ownership of its reference count management, or dispose of the value itself with either a Tcl_IncrRefCount/Tcl_DecrRefCount pair or Tcl_BounceRefCount. π
β¨ SEE ALSO β¨
β¨ KEYWORDS β¨
okay bestie, here's the lil tag cloud for this page β the magic words you'd grep for if you forgot which function does the thing π
appendπ β for when you're adding stuff to the end, ngl the most relatable keyword hereindexπ¦ β the "gimme just that one element" energyinsertβ¨ β squeezing new elements in the middle like a true main characterinternal representationπ β the secret behind-the-scenes version of the list, iykyklengthπ β how many elements, periodtlistπ β the whole point of this entire manpage, literallylist valueπΈ β theTcl_Objyou're out here manipulating, gorgeouslist typeπ₯ β theTcl_ObjTypethat makes a value act all listyvalueβ β genericTcl_Objappreciation cornervalue typeπ β ditto but for the type structreplaceπ§ β out with the old elements, in with the new, slaystring representationπ β the obverse of the internal rep, the text-y version, careful with thatbytespointer babe
and that's a wrap on Tcl_ListObj(3) π«Άπ thanks for reading bestie, go forth and mutate your Tcl_Obj refCounts responsibly. this iconic lil page is from Tcl 9.1 β you're welcome ππ
π¦ where this page comes from
- nixpkgs unstable: tcl 9.1.0
- Copyright (c) 1996-1997 Sun Microsystems, Inc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms