TIP 481: <code>Tcl_GetStringFromObj()</code> with <code>size_t</code> length parameter

Login
Author:         Jan Nijtmans <[email protected]>
State:          Draft
Type:           Project
Vote:           Pending
Created:        27-Oct-2017
Post-History:
Keywords:       Tcl
Tcl-Version:    8.7
Tcl-Branch:     tip-481

Abstract

This TIP proposes enhancing various C API functions which having a int * parameter, to be used with a size_t * parameter as well. In addition, a new Tcl_GetValue() function is proposed which can retrieve a signed or unsigned (wide) integer or a float/double/long double from a Tcl_Obj, .

Rationale

In Tcl 9, the range of various functions need to be increased. For example Tcl_GetStringFromObj now is limited to returning 32 bit for the maximum string length. This can be fixed by introducing an internal function Tcl_GetStringFromObj2() which has a size_t * parameter in stead of int *. On top of that, Tcl_GetStringFromObj is provided as a macro, which switches between the two possible functions depending on the size of the parameter.

The same is done for Tcl_GetUnicodeFromObj and Tcl_GetByteArrayFromObj.

This way, we have a compatibility layer, easing the transition to Tcl 9. In Tcl 8.7, although the parameter has type size_t, the actual length range that can be returned is actually -1 up to 4294967294. In Tcl 9, the full size_t range is available.

Specification

Add to Tcl's stub table of public C routines the following new routines

int Tcl_GetStringFromObj2(Tcl_Obj *objPtr, size_t *lengthPtr)

int Tcl_GetUnicodeFromObj2(Tcl_Obj *objPtr, size_t *lengthPtr)

int Tcl_GetByteArrayFromObj2(Tcl_Obj *objPtr, size_t *lengthPtr)

Those 3 functions do exactly the same as their existing counterparts, only the lengthPtr parameter is of type size_t in stead of int. The original 3 functions will be wrapped in a macro of the same name, so depending on the actual size of the variable where lengthPtr points to, the switch between the two function versions are done automatically. So, the new functions don't need to be used in code, the original function can be used pointing to a size_t length variable as well.

int Tcl_GetValue(Tcl_Interp *interp, Tcl_Obj *objPtr, void *valuePtr, int flags)

This functions is able to function the same as Tcl_GetIntFromObj, Tcl_GetLongFromObj, Tcl_GetWideFromObj and Tcl_GetDoubleFromObj. The flags argument determines the actual conversion done. The following flags are possible.

TCL_TYPE_I(int | long | Tcl_WideInt) : valuePtr points at an integer of given size

TCL_TYPE_U(int | long | Tcl_WideInt) : valuePtr points at an unsigned integer of given size

TCL_TYPE_D(float | double) : valuePtr points at a float or double

Those 3 macro's use the sizeof() macro on the type to provide the requested size to Tcl_GetValue(). Actually, you can use any integer type, so e.g. size_t or intmax_t work as well.

int Tcl_GetUIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, void *valuePtr)

This is a wrapper macro around Tcl_GetValue, handling unsigned integer values only.

For Tcl 9.0, the function Tcl_GetIntFromObj is modified to return 1 when the Tcl_Obj value is in the range -2147483648 .. 2147483647.

Implementation

See the tip-481 branch in Tcl's fossil repository https://core.tcl.tk/tcl/timeline?r=tip-481 .