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 .