Version 11 of Array enumeration

Updated 2016-11-24 20:08:33 by AMG

AMG: Tcl arrays are enumerated via the [array names] or [array get] commands or by the (virtually obsolete) combination of [array startsearch], [array nextelement], [array anymore], and [array donesearch]. At present, they cannot be enumerated via the Tcl C API. The FlightAware Tcl bounty programme [L1 ] seeks to address this and other Tcl shortcomings.

I intend to implement a Tcl C API for enumerating array elements. I am patterning my API on Tcl API listed above and on the C API for accessing variables. The implementation will be obtained by rearranging existing code as much as possible to minimize the inadvertent introduction of new bugs. The above-listed [array] commands will be reimplemented as calls into the new C API so that it can be tested by the existing Tcl test suite.

This will be my first TIP and my first case of Tcl core programming. Outside of random bug and documentation fixes, my Tcl C experience is writing proprietary Tcl extensions over the last 10-15 years, and my Tcl scripting experience goes back to 1999.


Code

http://core.tcl.tk/tcl/timeline?r=amg-array-enum-c-api


API

Here is my working API design. Please share any comments or questions you may have. I welcome opinions about the alternatives and wishes I outline below, and please feel free to add your own ideas.

Types

typedef struct ArraySearch *Tcl_ArraySearch

Tcl_ArraySearch is an opaque pointer to struct ArraySearch which has the search internals. The term "search" is reused for the C API even though it's actually a full enumeration.

Arguments

Tcl_Interp *interp (in)

Interpreter containing array variable.

Tcl_Obj *varNamePtr (in)

Points to a Tcl object containing the variable's name. The name may include a series of :: namespace qualifiers to specify an array varaible in a particular namespace.

int *objcPtr (out)

In flux.

Tcl_Obj ***objvPtr (out)

In flux.

Tcl_ArraySearch search (in)

Search token obtained from Tcl_ArraySearchStart().

int flags (in)

OR-ed combination of bits providing additional information. Can be TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG.

Functions

int Tcl_ArraySize(interp, varNamePtr, flags)

Returns array size or -1 on error.

Alternative: Take an intPtr argument and return TCL_OK or TCL_ERROR. This approach matches Tcl_ListObjLength().

Wish: Optional exact/glob/regexp filter like [array names].

Tcl_ArraySearch Tcl_ArraySearchStart(interp, varNamePtr, flags)

Returns a Tcl_ArraySearch on success or NULL on error.

Wish: Optional exact/glob/regexp filter like [array names].

Tcl_Obj *Tcl_ArraySearchNext(search)

Returns name of next element or NULL if finished.

void Tcl_ArraySearchDone(search)

Cleans up array search internals.

Alternative name: Tcl_ArraySearchStop().

int Tcl_ArrayNames(interp, varNamePtr, objcPtr, objvPtr, flags)

Gets a list of all array element names. Call ckfree() on objvPtr when done.

Alternative: Give caller the option to manage objvPtr memory directly. Only automatically allocate if *objvPtr is NULL, otherwise assume it points to a block of memory big enough for Tcl_ArraySize() Tcl_Obj pointers.

Alternative: Hybrid approach. If *objvPtr is not NULL and *objcPtr is at least Tcl_ArraySize(), use it directly as described above. If *objvPtr is not NULL but *objcPtr is insufficient, attemptckrealloc() *objvPtr to the minimum required size. This way, Tcl_ArrayGetNames() can be used many times in a row without allocating and freeing memory more than needed. Changes objcPtr and objvPtr to be (in/out). Even if glob filter wish is implemented, would still allocate to match the array size just in case the filter ends up matching everything.

Alternative: Forget all the above. Instead simply store results into a list-type Tcl_Obj to simplify memory management and avoid [array names] having to make a copy.

Alternative name: Tcl_ArrayGetNames().

Wish: Optional exact/glob/regexp filter like [array names].


Progress

20 November 2016
Began work, implemented Tcl_ArraySize().
24 November 2016
Published commits, fixed [array size] reporting of trace errors, improved Wiki page.