From 8d186d9f5a98a5225ca38935c3cd51d33236f1c6 Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 12 Apr 2024 16:09:49 +0000 Subject: Clean up the arith series code, including fixing a memory leak --- generic/tclArithSeries.c | 426 +++++++++++++++++++++++++++-------------------- 1 file changed, 250 insertions(+), 176 deletions(-) diff --git a/generic/tclArithSeries.c b/generic/tclArithSeries.c index 2770639..fd1014c 100755 --- a/generic/tclArithSeries.c +++ b/generic/tclArithSeries.c @@ -46,41 +46,56 @@ * 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; +} ArithSeries; + +typedef struct { + ArithSeries base; Tcl_WideInt start; Tcl_WideInt end; Tcl_WideInt step; -} ArithSeries; +} ArithSeriesInt; + typedef struct { - Tcl_Size len; - Tcl_Obj **elements; - int isDouble; + ArithSeries base; double start; double end; double step; - int precision; + unsigned precision; /* Number of decimal places to render. */ } ArithSeriesDbl; -/* -------------------------- ArithSeries object ---------------------------- */ - -static int TclArithSeriesObjIndex(TCL_UNUSED(Tcl_Interp *), Tcl_Obj *arithSeriesObj, - Tcl_Size index, Tcl_Obj **elemObj); - -static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesObj); -static int TclArithSeriesObjRange(Tcl_Interp *interp, Tcl_Obj *arithSeriesObj, - Tcl_Size fromIdx, Tcl_Size toIdx, Tcl_Obj **newObjPtr); -static int TclArithSeriesObjReverse(Tcl_Interp *interp, Tcl_Obj *arithSeriesObj, Tcl_Obj **newObjPtr); -static int TclArithSeriesGetElements(Tcl_Interp *interp, - Tcl_Obj *objPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr); -static void DupArithSeriesInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); -static void FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr); -static void UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr); -static int SetArithSeriesFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); -static int ArithSeriesInOperation(Tcl_Interp *interp, Tcl_Obj *valueObj, Tcl_Obj *arithSeriesObj, - int *boolResult); +/* Forward declarations. */ + +static int TclArithSeriesObjIndex(TCL_UNUSED(Tcl_Interp *), + Tcl_Obj *arithSeriesObj, Tcl_Size index, + Tcl_Obj **elemObj); +static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesObj); +static int TclArithSeriesObjRange(Tcl_Interp *interp, + Tcl_Obj *arithSeriesObj, Tcl_Size fromIdx, + Tcl_Size toIdx, Tcl_Obj **newObjPtr); +static int TclArithSeriesObjReverse(Tcl_Interp *interp, + Tcl_Obj *arithSeriesObj, Tcl_Obj **newObjPtr); +static int TclArithSeriesGetElements(Tcl_Interp *interp, + Tcl_Obj *objPtr, Tcl_Size *objcPtr, + Tcl_Obj ***objvPtr); +static void DupArithSeriesInternalRep(Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr); +static void FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr); +static void UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr); +static int SetArithSeriesFromAny(Tcl_Interp *interp, + Tcl_Obj *objPtr); +static int ArithSeriesInOperation(Tcl_Interp *interp, + Tcl_Obj *valueObj, Tcl_Obj *arithSeriesObj, + int *boolResult); +static int TclArithSeriesObjStep(Tcl_Obj *arithSeriesObj, + Tcl_Obj **stepObj); + +/* ------------------------ ArithSeries object type -------------------------- */ + static const Tcl_ObjType arithSeriesType = { "arithseries", /* name */ FreeArithSeriesInternalRep, /* freeIntRepProc */ @@ -97,10 +112,11 @@ static const Tcl_ObjType arithSeriesType = { NULL, // Replace ArithSeriesInOperation) // "in" operator }; - + /* * Helper functions * + * - power10 -- Fast version of pow(10, (int) n) for common cases. * - ArithRound -- Round doubles to the number of significant fractional * digits * - ArithSeriesIndexDbl -- base list indexing operation for doubles @@ -111,10 +127,31 @@ static const Tcl_ObjType arithSeriesType = { * - maxPrecision -- Using the values provide, determine the longest percision * in the arithSeries */ + static inline double -ArithRound(double d, unsigned int n) { - double scalefactor = pow(10, n); - return round(d*scalefactor)/scalefactor; +power10( + unsigned n) +{ + static const double powers[] = { + 1, 10, 100, 1000, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, + 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20 + }; + + if (n < sizeof(powers) / sizeof(*powers)) { + return powers[n]; + } else { + // Not an expected case. Doesn't need to be so fast + return pow(10, n); + } +} + +static inline double +ArithRound( + double d, + unsigned n) +{ + double scalefactor = power10(n); + return round(d * scalefactor) / scalefactor; } static inline double @@ -122,13 +159,14 @@ ArithSeriesIndexDbl( ArithSeries *arithSeriesRepPtr, Tcl_WideInt index) { - ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; if (arithSeriesRepPtr->isDouble) { + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr; double d = dblRepPtr->start + (index * dblRepPtr->step); - unsigned n = (dblRepPtr->precision > 0 ? dblRepPtr->precision : 0); - return ArithRound(d, n); + + return ArithRound(d, dblRepPtr->precision); } else { - return (double)(arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step)); + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr; + return (double)(intRepPtr->start + (index * intRepPtr->step)); } } @@ -137,51 +175,57 @@ ArithSeriesIndexInt( ArithSeries *arithSeriesRepPtr, Tcl_WideInt index) { - ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; if (arithSeriesRepPtr->isDouble) { - return (Tcl_WideInt)(dblRepPtr->start + ((index) * dblRepPtr->step)); + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr; + return (Tcl_WideInt) (dblRepPtr->start + (index * dblRepPtr->step)); } else { - return (arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step)); + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr; + return intRepPtr->start + (index * intRepPtr->step); } } -static inline ArithSeries* -ArithSeriesGetInternalRep(Tcl_Obj *objPtr) +static inline ArithSeries * +ArithSeriesGetInternalRep( + Tcl_Obj *objPtr) { - const Tcl_ObjInternalRep *irPtr; - irPtr = TclFetchInternalRep((objPtr), &arithSeriesType); - return irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL; + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, + &arithSeriesType); + return irPtr ? (ArithSeries *) irPtr->twoPtrValue.ptr1 : NULL; } /* - * Compute number of significant factional digits + * Compute number of significant fractional digits */ -static inline int -Precision(double d) +static inline unsigned +Precision( + double d) { - char tmp[TCL_DOUBLE_SPACE+2], *off; + char tmp[TCL_DOUBLE_SPACE + 2], *off; + tmp[0] = 0; - Tcl_PrintDouble(NULL,d,tmp); + Tcl_PrintDouble(NULL, d, tmp); off = strchr(tmp, '.'); - return (off ? strlen(off+1) : 0); + return (off ? strlen(off + 1) : 0); } /* * Find longest number of digits after the decimal point. */ -static inline int -maxPrecision(double start, double end, double step) +static inline unsigned +maxPrecision( + double start, + double end, + double step) { - int dp = Precision(step); - int i = Precision(start); + unsigned dp = Precision(step); + unsigned i = Precision(start); + dp = i>dp ? i : dp; i = Precision(end); dp = i>dp ? i : dp; return dp; } - -static int TclArithSeriesObjStep(Tcl_Obj *arithSeriesObj, Tcl_Obj **stepObj); - + /* *---------------------------------------------------------------------- * @@ -206,31 +250,38 @@ static int TclArithSeriesObjStep(Tcl_Obj *arithSeriesObj, Tcl_Obj **stepObj); *---------------------------------------------------------------------- */ static Tcl_WideInt -ArithSeriesLenInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step) +ArithSeriesLenInt( + Tcl_WideInt start, + Tcl_WideInt end, + Tcl_WideInt step) { Tcl_WideInt len; if (step == 0) { return 0; } - len = 1 + ((end-start)/step); + len = 1 + ((end - start) / step); return (len < 0) ? -1 : len; } static Tcl_WideInt -ArithSeriesLenDbl(double start, double end, double step, int precision) +ArithSeriesLenDbl( + double start, + double end, + double step, + unsigned precision) { double istart, iend, istep, ilen; + if (step == 0) { return 0; } - istart = start * pow(10,precision); - iend = end * pow(10,precision); - istep = step * pow(10,precision); - ilen = ((iend-istart+istep)/istep); + istart = start * power10(precision); + iend = end * power10(precision); + istep = step * power10(precision); + ilen = (iend - istart + istep) / istep; return floor(ilen); } - /* *---------------------------------------------------------------------- @@ -239,6 +290,7 @@ ArithSeriesLenDbl(double start, double end, double step, int precision) * * Initialize the internal representation of a arithseries Tcl_Obj to a * copy of the internal representation of an existing arithseries object. + * The copy does not share the cache of the elements. * * Results: * None. @@ -246,6 +298,7 @@ ArithSeriesLenDbl(double start, double end, double step, int precision) * Side effects: * We set "copyPtr"s internal rep to a pointer to a * newly allocated ArithSeries structure. + * *---------------------------------------------------------------------- */ @@ -254,26 +307,25 @@ DupArithSeriesInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { - ArithSeries *srcArithSeriesRepPtr = - (ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1; + ArithSeries *srcRepPtr = (ArithSeries *) + srcPtr->internalRep.twoPtrValue.ptr1; - /* - * Allocate a new ArithSeries structure. */ - - if (srcArithSeriesRepPtr->isDouble) { - ArithSeriesDbl *srcArithSeriesDblRepPtr = - (ArithSeriesDbl *)srcArithSeriesRepPtr; - ArithSeriesDbl *copyArithSeriesDblRepPtr = - (ArithSeriesDbl *)Tcl_Alloc(sizeof(ArithSeriesDbl)); - *copyArithSeriesDblRepPtr = *srcArithSeriesDblRepPtr; - copyArithSeriesDblRepPtr->elements = NULL; - copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesDblRepPtr; + if (srcRepPtr->isDouble) { + ArithSeriesDbl *srcDblPtr = (ArithSeriesDbl *) srcRepPtr; + ArithSeriesDbl *copyDblPtr = (ArithSeriesDbl *) + Tcl_Alloc(sizeof(ArithSeriesDbl)); + + *copyDblPtr = *srcDblPtr; + copyDblPtr->base.elements = NULL; + copyPtr->internalRep.twoPtrValue.ptr1 = copyDblPtr; } else { - ArithSeries *copyArithSeriesRepPtr = - (ArithSeries *)Tcl_Alloc(sizeof(ArithSeries)); - *copyArithSeriesRepPtr = *srcArithSeriesRepPtr; - copyArithSeriesRepPtr->elements = NULL; - copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr; + ArithSeriesInt *srcIntPtr = (ArithSeriesInt *) srcRepPtr; + ArithSeriesInt *copyIntPtr = (ArithSeriesInt *) + Tcl_Alloc(sizeof(ArithSeriesInt)); + + *copyIntPtr = *srcIntPtr; + copyIntPtr->base.elements = NULL; + copyPtr->internalRep.twoPtrValue.ptr1 = copyIntPtr; } copyPtr->internalRep.twoPtrValue.ptr2 = NULL; copyPtr->typePtr = &arithSeriesType; @@ -293,24 +345,34 @@ DupArithSeriesInternalRep( * *---------------------------------------------------------------------- */ -static void -FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr) /* Free any allocated memory */ + +static inline void +FreeElements( + ArithSeries *arithSeriesRepPtr) { - ArithSeries *arithSeriesRepPtr = (ArithSeries*)arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; + if (arithSeriesRepPtr->elements) { + Tcl_WideInt i, len = arithSeriesRepPtr->len; - if (arithSeriesRepPtr) { - if (arithSeriesRepPtr->elements) { - Tcl_WideInt i, len = arithSeriesRepPtr->len; - for (i=0; ielements[i]); - } - Tcl_Free((char*)arithSeriesRepPtr->elements); - arithSeriesRepPtr->elements = NULL; + for (i=0; ielements[i]); } - Tcl_Free((char*)arithSeriesRepPtr); + Tcl_Free((char *) arithSeriesRepPtr->elements); + arithSeriesRepPtr->elements = NULL; } } +static void +FreeArithSeriesInternalRep( + Tcl_Obj *arithSeriesObjPtr) +{ + ArithSeries *arithSeriesRepPtr = (ArithSeries *) + arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; + + if (arithSeriesRepPtr) { + FreeElements(arithSeriesRepPtr); + Tcl_Free((char *) arithSeriesRepPtr); + } +} /* *---------------------------------------------------------------------- @@ -326,17 +388,20 @@ FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr) /* Free any allocated me * A NULL pointer of the range is invalid. * * Side Effects: - * * None. + * *---------------------------------------------------------------------- */ -static -Tcl_Obj * -NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_WideInt len) +static Tcl_Obj * +NewArithSeriesInt( + Tcl_WideInt start, + Tcl_WideInt end, + Tcl_WideInt step, + Tcl_WideInt len) { Tcl_WideInt length; Tcl_Obj *arithSeriesObj; - ArithSeries *arithSeriesRepPtr; + ArithSeriesInt *arithSeriesRepPtr; length = len>=0 ? len : -1; if (length < 0) { @@ -349,13 +414,13 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide return arithSeriesObj; } - arithSeriesRepPtr = (ArithSeries*)Tcl_Alloc(sizeof (ArithSeries)); - arithSeriesRepPtr->isDouble = 0; + arithSeriesRepPtr = (ArithSeriesInt *) Tcl_Alloc(sizeof(ArithSeriesInt)); + arithSeriesRepPtr->base.len = length; + arithSeriesRepPtr->base.elements = NULL; + arithSeriesRepPtr->base.isDouble = 0; arithSeriesRepPtr->start = start; arithSeriesRepPtr->end = end; arithSeriesRepPtr->step = step; - arithSeriesRepPtr->len = length; - arithSeriesRepPtr->elements = NULL; arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr; arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL; arithSeriesObj->typePtr = &arithSeriesType; @@ -385,9 +450,12 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide *---------------------------------------------------------------------- */ -static -Tcl_Obj * -NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) +static Tcl_Obj * +NewArithSeriesDbl( + double start, + double end, + double step, + Tcl_WideInt len) { Tcl_WideInt length; Tcl_Obj *arithSeriesObj; @@ -404,14 +472,14 @@ NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) return arithSeriesObj; } - arithSeriesRepPtr = (ArithSeriesDbl*)Tcl_Alloc(sizeof (ArithSeriesDbl)); - arithSeriesRepPtr->isDouble = 1; + arithSeriesRepPtr = (ArithSeriesDbl *) Tcl_Alloc(sizeof(ArithSeriesDbl)); + arithSeriesRepPtr->base.len = length; + arithSeriesRepPtr->base.elements = NULL; + arithSeriesRepPtr->base.isDouble = 1; arithSeriesRepPtr->start = start; arithSeriesRepPtr->end = end; arithSeriesRepPtr->step = step; - arithSeriesRepPtr->len = length; - arithSeriesRepPtr->elements = NULL; - arithSeriesRepPtr->precision = maxPrecision(start,end,step); + arithSeriesRepPtr->precision = maxPrecision(start, end, step); arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr; arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL; arithSeriesObj->typePtr = &arithSeriesType; @@ -546,7 +614,7 @@ TclNewArithSeriesObj( assert(dstep!=0); if (!lenObj) { if (useDoubles) { - int precision = maxPrecision(dstart,dend,dstep); + unsigned precision = maxPrecision(dstart, dend, dstep); len = ArithSeriesLenDbl(dstart, dend, dstep, precision); } else { len = ArithSeriesLenInt(start, end, step); @@ -557,21 +625,21 @@ TclNewArithSeriesObj( if (!endObj) { if (useDoubles) { // Compute precision based on given command argument values - int precision = maxPrecision(dstart,len,dstep); + unsigned precision = maxPrecision(dstart, len, dstep); + dend = dstart + (dstep * (len-1)); // Make computed end value match argument(s) precision dend = ArithRound(dend, precision); end = dend; } else { - end = start + (step * (len-1)); + end = start + (step * (len - 1)); dend = end; } } if (len > TCL_SIZE_MAX) { - Tcl_SetObjResult( - interp, - Tcl_NewStringObj("max length of a Tcl list exceeded", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "max length of a Tcl list exceeded", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); return TCL_ERROR; } @@ -606,13 +674,12 @@ TclNewArithSeriesObj( * *---------------------------------------------------------------------- */ - int TclArithSeriesObjIndex( - TCL_UNUSED(Tcl_Interp *),/* Used for error reporting if not NULL. */ - Tcl_Obj *arithSeriesObj, /* List obj */ - Tcl_Size index, /* index to element of interest */ - Tcl_Obj **elemObj) /* Return value */ + TCL_UNUSED(Tcl_Interp *), + Tcl_Obj *arithSeriesObj, /* List obj */ + Tcl_Size index, /* index to element of interest */ + Tcl_Obj **elemObj) /* Return value */ { ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj); @@ -651,7 +718,7 @@ Tcl_Size ArithSeriesObjLength( Tcl_Obj *arithSeriesObj) { - ArithSeries *arithSeriesRepPtr = (ArithSeries*) + ArithSeries *arithSeriesRepPtr = (ArithSeries *) arithSeriesObj->internalRep.twoPtrValue.ptr1; return arithSeriesRepPtr->len; } @@ -681,14 +748,15 @@ TclArithSeriesObjStep( Tcl_Obj **stepObj) { ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj); + if (arithSeriesRepPtr->isDouble) { - *stepObj = Tcl_NewDoubleObj(((ArithSeriesDbl*)(arithSeriesRepPtr))->step); + *stepObj = Tcl_NewDoubleObj(((ArithSeriesDbl *) arithSeriesRepPtr)->step); } else { - *stepObj = Tcl_NewWideIntObj(arithSeriesRepPtr->step); + *stepObj = Tcl_NewWideIntObj(((ArithSeriesInt *) arithSeriesRepPtr)->step); } return TCL_OK; } - + /* *---------------------------------------------------------------------- * @@ -773,8 +841,8 @@ TclArithSeriesObjRange( if (toIdx < 0) { toIdx = 0; } - if (toIdx > arithSeriesRepPtr->len-1) { - toIdx = arithSeriesRepPtr->len-1; + if (toIdx > arithSeriesRepPtr->len - 1) { + toIdx = arithSeriesRepPtr->len - 1; } TclArithSeriesObjIndex(interp, arithSeriesObj, fromIdx, &startObj); @@ -806,30 +874,31 @@ TclArithSeriesObjRange( TclInvalidateStringRep(arithSeriesObj); if (arithSeriesRepPtr->isDouble) { - ArithSeriesDbl *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr; double start, end, step; Tcl_GetDoubleFromObj(NULL, startObj, &start); Tcl_GetDoubleFromObj(NULL, endObj, &end); Tcl_GetDoubleFromObj(NULL, stepObj, &step); - arithSeriesDblRepPtr->start = start; - arithSeriesDblRepPtr->end = end; - arithSeriesDblRepPtr->step = step; - arithSeriesDblRepPtr->precision = maxPrecision(start, end, step); - arithSeriesDblRepPtr->len = - ArithSeriesLenDbl(start, end, step, arithSeriesDblRepPtr->precision); - arithSeriesDblRepPtr->elements = NULL; - + dblRepPtr->start = start; + dblRepPtr->end = end; + dblRepPtr->step = step; + dblRepPtr->precision = maxPrecision(start, end, step); + FreeElements(arithSeriesRepPtr); + dblRepPtr->base.len = + ArithSeriesLenDbl(start, end, step, dblRepPtr->precision); } else { + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr; Tcl_WideInt start, end, step; + Tcl_GetWideIntFromObj(NULL, startObj, &start); Tcl_GetWideIntFromObj(NULL, endObj, &end); Tcl_GetWideIntFromObj(NULL, stepObj, &step); - arithSeriesRepPtr->start = start; - arithSeriesRepPtr->end = end; - arithSeriesRepPtr->step = step; - arithSeriesRepPtr->len = ArithSeriesLenInt(start, end, step); - arithSeriesRepPtr->elements = NULL; + intRepPtr->start = start; + intRepPtr->end = end; + intRepPtr->step = step; + FreeElements(arithSeriesRepPtr); + intRepPtr->base.len = ArithSeriesLenInt(start, end, step); } Tcl_DecrRefCount(startObj); @@ -880,32 +949,32 @@ TclArithSeriesGetElements( * pointers to the list's objects. */ { if (TclHasInternalRep(objPtr, &arithSeriesType)) { - ArithSeries *arithSeriesRepPtr; + ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr); Tcl_Obj **objv; - int i, objc; - - arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr); + Tcl_Size objc = arithSeriesRepPtr->len; - objc = arithSeriesRepPtr->len; if (objc > 0) { if (arithSeriesRepPtr->elements) { /* If this exists, it has already been populated */ objv = arithSeriesRepPtr->elements; } else { /* Construct the elements array */ - objv = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj*) * objc); + objv = (Tcl_Obj **) Tcl_Alloc(sizeof(Tcl_Obj*) * objc); if (objv == NULL) { if (interp) { - Tcl_SetObjResult( - interp, - Tcl_NewStringObj("max length of a Tcl list exceeded", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "max length of a Tcl list exceeded", + TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return TCL_ERROR; } arithSeriesRepPtr->elements = objv; + + Tcl_Size i; for (i = 0; i < objc; i++) { int status = TclArithSeriesObjIndex(interp, objPtr, i, &objv[i]); + if (status) { return TCL_ERROR; } @@ -919,7 +988,8 @@ TclArithSeriesGetElements( *objcPtr = objc; } else { if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("value is not an arithseries", TCL_INDEX_NONE)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "value is not an arithseries", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "UNKNOWN", (void *)NULL); } return TCL_ERROR; @@ -968,7 +1038,7 @@ TclArithSeriesObjReverse( isDouble = arithSeriesRepPtr->isDouble; len = arithSeriesRepPtr->len; - TclArithSeriesObjIndex(NULL, arithSeriesObj, (len-1), &startObj); + TclArithSeriesObjIndex(NULL, arithSeriesObj, len - 1, &startObj); Tcl_IncrRefCount(startObj); TclArithSeriesObjIndex(NULL, arithSeriesObj, 0, &endObj); Tcl_IncrRefCount(endObj); @@ -991,6 +1061,7 @@ TclArithSeriesObjReverse( if (Tcl_IsShared(arithSeriesObj) || (arithSeriesObj->refCount > 1)) { Tcl_Obj *lenObj; + TclNewIntObj(lenObj, len); if (TclNewArithSeriesObj(NULL, &resultObj, isDouble, startObj, endObj, stepObj, lenObj) != TCL_OK) { @@ -998,7 +1069,6 @@ TclArithSeriesObjReverse( } Tcl_DecrRefCount(lenObj); } else { - /* * In-place is possible. */ @@ -1006,25 +1076,18 @@ TclArithSeriesObjReverse( TclInvalidateStringRep(arithSeriesObj); if (isDouble) { - ArithSeriesDbl *arithSeriesDblRepPtr = - (ArithSeriesDbl*)arithSeriesRepPtr; - arithSeriesDblRepPtr->start = dstart; - arithSeriesDblRepPtr->end = dend; - arithSeriesDblRepPtr->step = dstep; + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr; + + dblRepPtr->start = dstart; + dblRepPtr->end = dend; + dblRepPtr->step = dstep; } else { - arithSeriesRepPtr->start = start; - arithSeriesRepPtr->end = end; - arithSeriesRepPtr->step = step; - } - if (arithSeriesRepPtr->elements) { - Tcl_WideInt i; - for (i=0; ielements[i]); - } - Tcl_Free((char*)arithSeriesRepPtr->elements); + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr; + intRepPtr->start = start; + intRepPtr->end = end; + intRepPtr->step = step; } - arithSeriesRepPtr->elements = NULL; - + FreeElements(arithSeriesRepPtr); resultObj = arithSeriesObj; } @@ -1064,11 +1127,12 @@ TclArithSeriesObjReverse( * *---------------------------------------------------------------------- */ - static void -UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) +UpdateStringOfArithSeries( + Tcl_Obj *arithSeriesObjPtr) { - ArithSeries *arithSeriesRepPtr = (ArithSeries*)arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; + ArithSeries *arithSeriesRepPtr = (ArithSeries *) + arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; char *p; Tcl_Obj *eleObj; Tcl_Size i, bytlen = 0; @@ -1078,14 +1142,16 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) */ if (!arithSeriesRepPtr->isDouble) { for (i = 0; i < arithSeriesRepPtr->len; i++) { - double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i); - size_t slen = d>0 ? log10(d)+1 : d<0 ? log10((0-d))+2 : 1; + double d = ArithSeriesIndexInt(arithSeriesRepPtr, i); + size_t slen = d>0 ? log10(d)+1 : d<0 ? log10(-d)+2 : 1; + bytlen += slen; } } else { for (i = 0; i < arithSeriesRepPtr->len; i++) { double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i); - char tmp[TCL_DOUBLE_SPACE+2]; + char tmp[TCL_DOUBLE_SPACE + 2]; + tmp[0] = 0; Tcl_PrintDouble(NULL,d,tmp); if ((bytlen + strlen(tmp)) > TCL_SIZE_MAX) { @@ -1105,6 +1171,7 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) if (TclArithSeriesObjIndex(NULL, arithSeriesObjPtr, i, &eleObj) == TCL_OK) { Tcl_Size slen; char *str = TclGetStringFromObj(eleObj, &slen); + strcpy(p, str); p[slen] = ' '; p += slen + 1; @@ -1143,12 +1210,13 @@ ArithSeriesInOperation( Tcl_Obj *arithSeriesObjPtr, int *boolResult) { - ArithSeries *arithSeriesRepPtr = (ArithSeries*)arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; - ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; + ArithSeries *repPtr = (ArithSeries *) + arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; int status; Tcl_Size index, incr, elen, vlen; - if (arithSeriesRepPtr->isDouble) { + if (repPtr->isDouble) { + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) repPtr; double y; int test = 0; @@ -1161,9 +1229,12 @@ ArithSeriesInOperation( index = (y - dblRepPtr->start) / dblRepPtr->step; while (incr<2) { Tcl_Obj *elemObj; + elen = 0; TclArithSeriesObjIndex(interp, arithSeriesObjPtr, (index+incr), &elemObj); + const char *estr = elemObj ? TclGetStringFromObj(elemObj, &elen) : ""; + /* "in" operation defined as a string compare */ test = (elen == vlen) ? (memcmp(estr, vstr, elen) == 0) : 0; Tcl_BounceRefCount(elemObj); @@ -1178,7 +1249,7 @@ ArithSeriesInOperation( *boolResult = test; } } else { - ArithSeries *intRepPtr = arithSeriesRepPtr; + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) repPtr; Tcl_WideInt y; status = Tcl_GetWideIntFromObj(NULL, valueObj, &y); @@ -1188,11 +1259,14 @@ ArithSeriesInOperation( } } else { Tcl_Obj *elemObj; + elen = 0; index = (y - intRepPtr->start) / intRepPtr->step; TclArithSeriesObjIndex(interp, arithSeriesObjPtr, index, &elemObj); + char const *vstr = TclGetStringFromObj(valueObj, &vlen); char const *estr = elemObj ? TclGetStringFromObj(elemObj, &elen) : ""; + if (boolResult) { *boolResult = (elen == vlen) ? (memcmp(estr, vstr, elen) == 0) : 0; } -- cgit v0.12