diff options
| author | griffin <briang42@easystreet.net> | 2022-12-21 06:59:38 (GMT) |
|---|---|---|
| committer | griffin <briang42@easystreet.net> | 2022-12-21 06:59:38 (GMT) |
| commit | bc3ff73062b718a3411ad95f90e0d55fed46ebd4 (patch) | |
| tree | 4cc614c14e8355eee212f1192127026bb46b2d87 /generic/tclArithSeries.c | |
| parent | a3f8bc6993db508508f569ffc66150ce09a8a122 (diff) | |
| download | tcl-bc3ff73062b718a3411ad95f90e0d55fed46ebd4.zip tcl-bc3ff73062b718a3411ad95f90e0d55fed46ebd4.tar.gz tcl-bc3ff73062b718a3411ad95f90e0d55fed46ebd4.tar.bz2 | |
Make as much abstract list implementation as possible internal.
Other code cleanup also.
Diffstat (limited to 'generic/tclArithSeries.c')
| -rwxr-xr-x | generic/tclArithSeries.c | 178 |
1 files changed, 144 insertions, 34 deletions
diff --git a/generic/tclArithSeries.c b/generic/tclArithSeries.c index 4902158..3be6cad 100755 --- a/generic/tclArithSeries.c +++ b/generic/tclArithSeries.c @@ -13,15 +13,14 @@ #include <assert.h> #include "tcl.h" #include "tclInt.h" -#include "tclArithSeries.h" /* - * The structure below defines the arithmetic series Tcl Obj Type by means of - * procedures that can be invoked by generic object code. + * The structure below defines the arithmetic series Tcl object type + * by means of procedures that can be invoked by generic object code. * - * The arithmetic series object is a oTcl_AbstractList representing an interval - * of an arithmetic series in constant space. + * The arithmetic series object is an AbstractList representing + * an interval of an arithmetic series in constant space. * * The arithmetic series is internally represented with three integers, * *start*, *end*, and *step*, Where the length is calculated with @@ -34,15 +33,37 @@ * else if RANGE < 0 * LEN is (((END-START)-1)/STEP) - 1 * - * And where the list's I-th element is calculated + * And where an equivalent list's I-th element is calculated * as: * - * LIST[i] = START+(STEP*i) + * LIST[i] = START + (STEP * i) * * Zero elements ranges, like in the case of START=10 END=10 STEP=1 * are valid and will be equivalent to the empty list. */ +/* + * The structure used for the ArithSeries internal representation. + * Note that the len can in theory be always computed by start,end,step + * but it's faster to cache it inside the internal representation. + */ +typedef struct { + Tcl_Size len; + Tcl_Obj **elements; + int isDouble; + Tcl_WideInt start; + Tcl_WideInt end; + Tcl_WideInt step; +} ArithSeries; +typedef struct { + Tcl_Size len; + Tcl_Obj **elements; + int isDouble; + double start; + double end; + double step; +} ArithSeriesDbl; + static inline double ArithSeriesIndexDbl(ArithSeriesDbl *repPtr, Tcl_Size index) { return (repPtr->start + ((double)index * repPtr->step)); @@ -69,13 +90,14 @@ static Tcl_Obj *TclNewArithSeriesDbl(double start, double end, static void DupArithSeriesRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FreeArithSeriesRep(Tcl_Obj *arithSeriesObjPtr); static void UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr); +static int SetArithSeriesFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static Tcl_ObjType arithSeriesType = { "arithseries", /* name */ FreeArithSeriesRep, /* freeIntRepProc */ DupArithSeriesRep, /* dupIntRepProc */ UpdateStringOfArithSeries, /* updateStringProc */ - NULL, /* setFromAnyProc */ + SetArithSeriesFromAny, /* setFromAnyProc */ TCL_OBJTYPE_V1( TclArithSeriesObjLength, NULL, @@ -103,7 +125,7 @@ static Tcl_ObjType arithSeriesType = { * * The length of the list generated by the given range, * that may be zero. - * The function returns -1 if the list is of length infiite. + * The function returns -1 if the list is of length infinite. * * Side effects: * @@ -149,8 +171,11 @@ DupArithSeriesRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) /* Note: we do not have to be worry about existing internal rep because copyPtr is supposed to be freshly initialized */ - Tcl_ObjSetConcreteRep(copyPtr, copyArithSeries); - copyPtr->typePtr = srcPtr->typePtr; + + Tcl_ObjInternalRep itr; + itr.twoPtrValue.ptr1 = copyArithSeries; + itr.twoPtrValue.ptr2 = NULL; + Tcl_StoreInternalRep(copyPtr, srcPtr->typePtr, &itr); if (copyArithSeries->len > 0) { Tcl_InvalidateStringRep(copyPtr); } else { @@ -217,8 +242,9 @@ TclNewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_W Tcl_ObjInternalRep itr; ArithSeries *arithSeriesRepPtr; + TclNewObj(arithSeriesObj); + if (length <= 0) { - TclNewObj(arithSeriesObj); return arithSeriesObj; } @@ -230,9 +256,9 @@ TclNewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_W arithSeriesRepPtr->len = length; arithSeriesRepPtr->elements = NULL; - TclNewObj(arithSeriesObj); + itr.twoPtrValue.ptr1 = arithSeriesRepPtr; + itr.twoPtrValue.ptr2 = NULL; Tcl_StoreInternalRep(arithSeriesObj, &arithSeriesType, &itr); - Tcl_ObjSetConcreteRep(arithSeriesObj, arithSeriesRepPtr); if (length > 0) Tcl_InvalidateStringRep(arithSeriesObj); @@ -266,8 +292,9 @@ TclNewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) Tcl_ObjInternalRep itr; ArithSeriesDbl *arithSeriesRepPtr; + TclNewObj(arithSeriesObj); + if (length <= 0) { - TclNewObj(arithSeriesObj); return arithSeriesObj; } @@ -279,9 +306,9 @@ TclNewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) arithSeriesRepPtr->len = length; arithSeriesRepPtr->elements = NULL; - TclNewObj(arithSeriesObj); + itr.twoPtrValue.ptr1 = arithSeriesRepPtr; + itr.twoPtrValue.ptr2 = NULL; Tcl_StoreInternalRep(arithSeriesObj, &arithSeriesType, &itr); - Tcl_ObjSetConcreteRep(arithSeriesObj, arithSeriesRepPtr); if (length > 0) Tcl_InvalidateStringRep(arithSeriesObj); @@ -294,7 +321,7 @@ TclNewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) * * assignNumber -- * - * Create the approprite Tcl_Obj value for the given numeric values. + * Create the appropriate Tcl_Obj value for the given numeric values. * Used locally only for decoding [lseq] numeric arguments. * refcount = 0. * @@ -362,14 +389,14 @@ assignNumber( int TclNewArithSeriesObj( - Tcl_Interp *interp, /* For error reporting */ - Tcl_Obj **arithSeriesObj, /* return value */ - int useDoubles, /* Promote values to double when true, - * int otherwise */ - Tcl_Obj *startObj, /* First value in list */ - Tcl_Obj *endObj, /* Upper bound value of list */ - Tcl_Obj *stepObj, /* Increment amount */ - Tcl_Obj *lenObj) /* Number of elements */ + Tcl_Interp *interp, /* For error reporting */ + Tcl_Obj **arithSeriesObj, /* return value */ + int useDoubles, /* Promote values to double when true, + ** int otherwise */ + Tcl_Obj *startObj, /* First value in list */ + Tcl_Obj *endObj, /* Upper bound value of list */ + Tcl_Obj *stepObj, /* Increment amount */ + Tcl_Obj *lenObj) /* Number of elements */ { double dstart, dend, dstep; Tcl_WideInt start, end, step; @@ -390,7 +417,7 @@ TclNewArithSeriesObj( } if (dstep == 0) { *arithSeriesObj = Tcl_NewObj(); - return TCL_OK; + return TCL_OK; } } if (endObj) { @@ -477,14 +504,14 @@ Tcl_Size TclArithSeriesObjLength(Tcl_Obj *arithSeriesObj) * TclArithSeriesObjIndex -- * * Returns the element with the specified index in the list - * represented by the specified Arithmentic Sequence object. + * represented by the specified Arithmetic Sequence object. * If the index is out of range, TCL_ERROR is returned, * otherwise TCL_OK is returned and the integer value of the * element is stored in *element. * * Results: * - * TCL_OK on succes, TCL_ERROR on index out of range. + * TCL_OK on success, TCL_ERROR on index out of range. * * Side Effects: * @@ -495,10 +522,10 @@ Tcl_Size TclArithSeriesObjLength(Tcl_Obj *arithSeriesObj) int TclArithSeriesObjIndex( - Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *arithSeriesPtr, /* List obj */ - Tcl_Size index, /* index to element of interest */ - Tcl_Obj **elemObj) /* Return value */ + Tcl_Size index, /* index to element of interest */ + Tcl_Obj **elemObj) /* Return value */ { ArithSeries *arithSeriesRepPtr = (ArithSeries *)Tcl_ObjGetConcreteRep(arithSeriesPtr); (void)interp; // quiet compiler @@ -760,8 +787,33 @@ TclArithSeriesObjReverse( } /* -** Handle ArithSeries GetElements call -*/ + *---------------------------------------------------------------------- + * + * TclArithSeriesGetElements -- + * + * This function returns an (objc,objv) array of the elements in a list + * object. + * + * Results: + * The return value is normally TCL_OK; in this case *objcPtr is set to + * the count of list elements and *objvPtr is set to a pointer to an + * array of (*objcPtr) pointers to each list element. If listPtr does not + * refer to an Abstract List object and the object can not be converted + * to one, TCL_ERROR is returned and an error message will be left in the + * interpreter's result if interp is not NULL. + * + * The objects referenced by the returned array should be treated as + * readonly and their ref counts are _not_ incremented; the caller must + * do that if it holds on to a reference. Furthermore, the pointer and + * length returned by this function may change as soon as any function is + * called on the list object; be careful about retaining the pointer in a + * local data structure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ int TclArithSeriesGetElements( @@ -818,6 +870,34 @@ TclArithSeriesGetElements( return TCL_OK; } +/* + *---------------------------------------------------------------------- + * + * UpdateStringOfArithSeries -- + * + * Update the string representation for an arithseries object. + * Note: This procedure does not invalidate an existing old string rep + * so storage will be lost if this has not already been done. + * + * Results: + * None. + * + * Side effects: + * The object's string is set to a valid string that results from + * the list-to-string conversion. This string will be empty if the + * list has no elements. The list internal representation + * should not be NULL and we assume it is not NULL. + * + * Notes: + * At the cost of overallocation it's possible to estimate + * the length of the string representation and make this procedure + * much faster. Because the programmer shouldn't expect the + * string conversion of a big arithmetic sequence to be fast + * this version takes more care of space than time. + * + *---------------------------------------------------------------------- + */ + static void UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) { @@ -862,6 +942,36 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) if (length > 0) arithSeriesObjPtr->bytes[length-1] = '\0'; arithSeriesObjPtr->length = length-1; } +/* + *---------------------------------------------------------------------- + * + * SetArithSeriesFromAny -- + * + * The Arithmetic Series object is just an way to optimize + * Lists space complexity, so no one should try to convert + * a string to an Arithmetic Series object. + * + * This function is here just to populate the Type structure. + * + * Results: + * + * The result is always TCL_ERROR. But see Side Effects. + * + * Side effects: + * + * Tcl Panic if called. + * + *---------------------------------------------------------------------- + */ + +static int +SetArithSeriesFromAny( + TCL_UNUSED(Tcl_Interp *), /* Used for error reporting if not NULL. */ + TCL_UNUSED(Tcl_Obj *)) /* The object to convert. */ +{ + Tcl_Panic("SetArithSeriesFromAny: should never be called"); + return TCL_ERROR; +} /* * Local Variables: |
