summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgriffin <briang42@easystreet.net>2022-08-16 18:33:47 (GMT)
committergriffin <briang42@easystreet.net>2022-08-16 18:33:47 (GMT)
commit2439b064ea3e521e50f6c7bd43ef0a69d183bff9 (patch)
tree1f796e5d3ede5434f99570ffa0d81f82d87dff8b
parentcb579a693a31557eda69872f9f9275372d020afe (diff)
downloadtcl-2439b064ea3e521e50f6c7bd43ef0a69d183bff9.zip
tcl-2439b064ea3e521e50f6c7bd43ef0a69d183bff9.tar.gz
tcl-2439b064ea3e521e50f6c7bd43ef0a69d183bff9.tar.bz2
Implement lrange for arithseries. Code cleanup.
-rw-r--r--generic/tclCmdIL.c41
-rw-r--r--generic/tclCmdMZ.c1
-rw-r--r--generic/tclInt.h1
-rw-r--r--generic/tclListObj.c63
4 files changed, 71 insertions, 35 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 065bc2a..669f34b 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -3129,33 +3129,7 @@ Tcl_LreverseObjCmd(
* just to reverse it.
*/
if (TclHasInternalRep(objv[1],&tclArithSeriesType)) {
- ArithSeries *arithSeriesPtr = ArithSeriesRepPtr(objv[1]);
- Tcl_WideInt rstart, rend, rstep, len;
-
- len = TclArithSeriesObjLength(objv[1]);
- if (TclArithSeriesObjIndex(objv[1], 0, &rend) != TCL_OK) {
- return TCL_ERROR;
- }
- if (TclArithSeriesObjIndex(objv[1], (len-1), &rstart) != TCL_OK) {
- return TCL_ERROR;
- }
- rstep = -arithSeriesPtr->step;
-
- if (Tcl_IsShared(objv[1])) {
- Tcl_Obj *resultObj = TclNewArithSeriesObj(rstart, rend, rstep, len);
- Tcl_SetObjResult(interp, resultObj);
- } else {
-
- /*
- * Not shared, so swap in place.
- */
-
- arithSeriesPtr->start = rstart;
- arithSeriesPtr->end = rend;
- arithSeriesPtr->step = rstep;
- TclInvalidateStringRep(objv[1]);
- Tcl_SetObjResult(interp, objv[1]);
- }
+ Tcl_SetObjResult(interp, TclArithSeriesObjReverse(objv[1]));
return TCL_OK;
} /* end ArithSeries */
@@ -4127,8 +4101,8 @@ SequenceIdentifyArgument(
*
* Tcl_LseqObjCmd --
*
- * This procedure is invoked to process the "range" Tcl command. See
- * the user documentation for details on what it does.
+ * This procedure is invoked to process the "lseq" Tcl command.
+ * See the user documentation for details on what it does.
*
* Enumerated possible argument patterns:
*
@@ -4347,10 +4321,13 @@ Tcl_LseqObjCmd(
goto done;
break;
}
- if (start <= end) {
- elementCount = step ? (end-start+step)/step : 0; // 0 step -> empty list
+ if (step == 0) {
+ // 0 step -> empty list
+ elementCount = 0;
+ } else if (start <= end) {
+ elementCount = (end-start+step)/step;
} else {
- elementCount = step ? (start-end-step)/(-step) : 0; // 0 step -> empty list
+ elementCount = (start-end-step)/(-step);
}
break;
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c
index cff182d..a9d1f11 100644
--- a/generic/tclCmdMZ.c
+++ b/generic/tclCmdMZ.c
@@ -62,7 +62,6 @@ const char tclDefaultTrimSet[] =
"\xE3\x80\x80" /* ideographic space (U+3000) */
"\xEF\xBB\xBF" /* zero width no-break space (U+feff) */
;
-
/*
*----------------------------------------------------------------------
diff --git a/generic/tclInt.h b/generic/tclInt.h
index bfbf1bc..f66814e 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -2949,6 +2949,7 @@ MODULE_SCOPE int TclArithSeriesObjIndex(Tcl_Obj *arithSeriesPtr,
MODULE_SCOPE Tcl_WideInt TclArithSeriesObjLength(Tcl_Obj *arithSeriesPtr);
MODULE_SCOPE Tcl_Obj * TclArithSeriesObjRange(Tcl_Obj *arithSeriesPtr,
int fromIdx, int toIdx);
+MODULE_SCOPE Tcl_Obj * TclArithSeriesObjReverse(Tcl_Obj *arithSeriesPtr);
MODULE_SCOPE int TclArithSeriesGetElements(Tcl_Interp *interp,
Tcl_Obj *objPtr, int *objcPtr, Tcl_Obj ***objvPtr);
MODULE_SCOPE Tcl_Obj * TclNewArithSeriesObj(Tcl_WideInt start,
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index d62583a..37d941d 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -2554,7 +2554,7 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesPtr)
* Pass 1: estimate space.
*/
for (i = 0; i < arithSeriesRepPtr->len; i++) {
- ele = arithSeriesRepPtr->start + (i*arithSeriesRepPtr->step);
+ ele = ArithSeriesIndexM(arithSeriesRepPtr, i);
/*
* Note that sprintf will generate a compiler warning under
* Mingw claiming %I64 is an unknown format specifier.
@@ -2572,7 +2572,7 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesPtr)
p = Tcl_InitStringRep(arithSeriesPtr, NULL, length);
for (i = 0; i < arithSeriesRepPtr->len; i++) {
- ele = arithSeriesRepPtr->start + (i*arithSeriesRepPtr->step);
+ ele = ArithSeriesIndexM(arithSeriesRepPtr, i);
sprintf(buffer, "%" TCL_LL_MODIFIER "d", ele);
slen = strlen(buffer);
strcpy(p, buffer);
@@ -2816,6 +2816,65 @@ TclArithSeriesGetElements(
}
return TCL_OK;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclArithSeriesObjReverse --
+ *
+ * Reverse the order of the ArithSeries value.
+ * *arithSeriesPtr must be known to be a valid list.
+ *
+ * Results:
+ * Returns a pointer to the reordered series.
+ * This may be a new object or the same object if not shared.
+ *
+ * Side effects:
+ * ?The possible conversion of the object referenced by listPtr?
+ * ?to a list object.?
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclArithSeriesObjReverse(
+ Tcl_Obj *arithSeriesPtr) /* List object to reverse. */
+{
+ ArithSeries *arithSeriesRepPtr;
+ Tcl_WideInt start = -1, end = -1, step, len;
+
+ ArithSeriesGetInternalRep(arithSeriesPtr, arithSeriesRepPtr);
+
+ len = arithSeriesRepPtr->len;
+ TclArithSeriesObjIndex(arithSeriesPtr, (len-1), &start);
+ TclArithSeriesObjIndex(arithSeriesPtr, 0, &end);
+ step = -arithSeriesRepPtr->step;
+
+ if (Tcl_IsShared(arithSeriesPtr) ||
+ ((arithSeriesPtr->refCount > 1))) {
+ return TclNewArithSeriesObj(start, end, step, len);
+ }
+
+ /*
+ * In-place is possible.
+ */
+
+ TclInvalidateStringRep(arithSeriesPtr);
+
+ arithSeriesRepPtr->start = start;
+ arithSeriesRepPtr->end = end;
+ arithSeriesRepPtr->step = step;
+ if (arithSeriesRepPtr->elements) {
+ Tcl_WideInt i;
+ for (i=0; i<len; i++) {
+ Tcl_DecrRefCount(arithSeriesRepPtr->elements[i]);
+ }
+ ckfree((char*)arithSeriesRepPtr->elements);
+ }
+ arithSeriesRepPtr->elements = NULL;
+
+ return arithSeriesPtr;
+}
/*