TIP #445: TCL_OBJTYPE UTILITY ROUTINES ======================================== Version: $Revision: 1.7 $ Author: Don Porter State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: Friday, 18 March 2016 URL: https://tip.tcl-lang.org445.html Post-History: ------------------------------------------------------------------------- ABSTRACT ========== Proposes additional public routines useful for extensions that implement custom *Tcl_ObjType/s. BACKGROUND ============ When an extension creates a custom *Tcl_ObjType* it needs to operate on the fields of the *Tcl_Obj* and the *Tcl_ObjType* structs. Almost all of these operations have been nicely encapsulated in utility routines, so for example, an extension calls *Tcl_GetString* to make sure a value is set for /objPtr->bytes/, rather than worrying about the backing details of calling the routine /objPtr->typePtr->updateStringProc/ (if present) for itself. Likewise *Tcl_DuplicateObj* routes processing to type-specific routines as needed. There are gaps in this interface. Most glaring is the lack of any way to call the /freeIntRepProc/ of an incumbent type other than directly through the /typePtr/ field. Another missing bit is an encapsulated way to set the string rep without direct manipulation of the /bytes/ and /length/ fields. Within Tcl itself, there are internal utility macros *TclFreeIntRep* and *TclInitStringRep* for these tasks, but extensions have nothing. Besides convenience, utility routines such as these improve chances for correctness, since they bring constraints into one place instead of many places. For example, the requirement that when /objPtr->typePtr/ is not NULL, it must be paired with an appropriate /objPtr->internalRep/. The *TclFreeIntRep* macro has a history of fixing such bugs. A corresponding routine will offer the same benefit to extensions. PROPOSAL ========== Add to Tcl's stub table of public C routines a new routine void *Tcl_FreeIntRep*(Tcl_Obj* /objPtr/) that performs precisely the same task as the existing internal macro *TclFreeIntRep*. Add to Tcl's stub table of public C routines a new routine char * *Tcl_InitStringRep*(Tcl_Obj* /objPtr/, const char* /bytes/, unsigned int /numBytes/) that performs the function of the existing internal macro *TclInitStringRep*, but is extended to return a pointer to the string rep, and to accept NULL as a value for /bytes/. When /bytes/ is NULL and /objPtr/ has no string rep, an uninitialzed buffer of /numBytes/ bytes is created for filling by the caller. When /bytes/ is NULL and /objPtr/ has a string rep, the string rep will be truncated to a length of /numBytes/ bytes. When /numBytes/ is greater than zero, and the returned pointer is NULL, that indicates a failure to allocate memory for the string representation. The caller may then choose whether to raise an error or panic. Add to Tcl's stub table of public C routines a new routine int *Tcl_HasStringRep*(Tcl_Obj* /objPtr/) that returns a boolean indicating whether or not a string rep is currently stored in /objPtr/. This is used when the caller wants to act on /objPtr/ differently depending on whether or not it is a /pure/ value. Typically this only makes sense in an extension if it is already known that /objPtr/ possesses an internal type that is managed by the extension. Define a new public type typedef union *Tcl_ObjIntRep* {...} *Tcl_ObjIntRep* where the contents are exactly the existing contents of the union in the /internalRep/ field of the *Tcl_Obj* struct. This definition permits us to pass internal representations and pointers to them as arguments and results in public routines. Add to Tcl's stub table of public C routines a new routine void *Tcl_StoreIntRep*(Tcl_Obj* /objPtr/, const Tcl_ObjType* /typePtr/, const Tcl_ObjIntRep* /irPtr/) which stores in /objPtr/ a copy of the internal representation pointed to by /irPtr/ and sets its type to /typePtr/. When /irPtr/ is NULL, this leaves /objPtr/ without a representation for type /typePtr/. Add to Tcl's stub table of public C routines a new routine Tcl_ObjIntRep* *Tcl_FetchIntRep*(Tcl_Obj* /objPtr/, const Tcl_ObjType* /typePtr/) which returns a pointer to the internal representation stored in /objPtr/ that matches the requested type /typePtr/. COMPATIBILITY =============== These are new routines, so they have no compatibility concerns in the sense of cause trouble for existing working code. They do help set up an improved compatibility scenario for the future however. Extensions that use these new routines to stop directly referring to the fields of the *Tcl_Obj* and *Tcl_ObjType* structs are prepared to support a source-compatible migration to a Tcl 9 that might then be free to make revisions to those structs. IMPLEMENTATION ================ Taking shape on the tip-445 branch. REJECTED ALTERNATIVES ======================= COPYRIGHT =========== This document has been placed in the public domain. ------------------------------------------------------------------------- TIP AutoGenerator - written by Donal K. Fellows