[Python-checkins] python/nondist/sandbox/datetime datetime.c,1.39,1.40 obj_date.c,1.19,1.20 obj_datetime.c,1.14,1.15 obj_delta.c,1.20,1.21
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Tue, 03 Dec 2002 21:08:17 -0800
Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv2441
Modified Files:
datetime.c obj_date.c obj_datetime.c obj_delta.c
Log Message:
Reworked the overflow checking for timedeltas, and, for speed, added a
bool "normalize?" argument to new_delta(). The scheme this replaces
didn't make sense anymore, not since the timedelta constructor was beefed
up to be as capable as the Python timedelta constructor.
Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -C2 -d -r1.39 -r1.40
*** datetime.c 3 Dec 2002 21:42:00 -0000 1.39
--- datetime.c 4 Dec 2002 05:08:14 -0000 1.40
***************
*** 14,22 ****
#define MAXYEAR 9999
typedef struct
{
PyObject_HEAD
! long hashcode;
! long days; /* in -TOOBIG_INPUT .. TOOBIG_INPUT */
long seconds; /* 0 <= seconds < 24*3600 is invariant */
long microseconds; /* 0 <= microseconds < 1000000 is invariant */
--- 14,29 ----
#define MAXYEAR 9999
+ /* Nine decimal digits is easy to communicate, and leaves enough room
+ * so that two delta days can be added w/o fear of overflowing a signed
+ * 32-bit int, and with plenty of room left over to absorb any possible
+ * carries from adding seconds.
+ */
+ #define MAX_DELTA_DAYS 999999999
+
typedef struct
{
PyObject_HEAD
! long hashcode; /* -1 when unknown */
! long days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
long seconds; /* 0 <= seconds < 24*3600 is invariant */
long microseconds; /* 0 <= microseconds < 1000000 is invariant */
***************
*** 96,122 ****
}
! /* All input fields (year, month, day, hour, minute, second, millisecond,
! * microsecond) are constrained to lie within -TOOBIG_INPUT .. TOOBIG_INPUT
! * exclusive of endpoints. You can't make this larger without studying the
! * code very carefully, as various "can't overflow" assurances follow
! * from the specific value used here.
! */
! #define TOOBIG_INPUT 1000000000 /* a billion; 1e9 */
!
! /* Check that x is in the range given above. If so, return 0. If not,
! * raise the given exception and return -1.
*/
static int
! check_range(long x, const char* tag, PyObject *exception)
{
char buf[200];
! if (-TOOBIG_INPUT < x && x < TOOBIG_INPUT)
return 0;
/* PyErr_Format() ignores the "l" in "%ld", which isn't correct
* on boxes where sizeof(long) > sizeof(int). So roll our own.
*/
! PyOS_snprintf(buf, sizeof(buf), "%s=%ld; must have magnitude < %ld",
! tag, x, TOOBIG_INPUT);
PyErr_SetString(exception, buf);
return -1;
--- 103,121 ----
}
! /* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
! * If not, raise the given exception and return -1.
*/
static int
! check_delta_day_range(long days, PyObject *exception)
{
char buf[200];
! if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
return 0;
/* PyErr_Format() ignores the "l" in "%ld", which isn't correct
* on boxes where sizeof(long) > sizeof(int). So roll our own.
*/
! PyOS_snprintf(buf, sizeof(buf), "days=%ld; must have magnitude <= %ld",
! days, MAX_DELTA_DAYS);
PyErr_SetString(exception, buf);
return -1;
***************
*** 516,527 ****
}
static PyObject *
! new_delta(long days, long seconds, long microseconds)
{
PyDateTime_Delta *self;
! normalize_d_s_us(&days, &seconds, µseconds);
! if (check_range(days, "timedelta days", PyExc_OverflowError) < 0)
return NULL;
--- 515,535 ----
}
+ /* Create a timedelta instance. Normalize the members iff normalize is
+ * true. Passing false is a speed optimization, if you know for sure
+ * that seconds and microseconds are already in their proper ranges. In any
+ * case, raises OverflowError and returns NULL if the normalized days is out
+ * of range).
+ */
static PyObject *
! new_delta(long days, long seconds, long microseconds, int normalize)
{
PyDateTime_Delta *self;
! if (normalize)
! normalize_d_s_us(&days, &seconds, µseconds);
! assert(0 <= seconds && seconds < 24*3600);
! assert(0 <= microseconds && microseconds < 1000000);
! if (check_delta_day_range(days, PyExc_OverflowError) < 0)
return NULL;
***************
*** 606,620 ****
return;
! dt = new_delta(0, 0, 1);
if (dt == NULL || PyDict_SetItemString(d, "resolution", dt) < 0)
return;
Py_DECREF(dt);
! dt = new_delta(1-TOOBIG_INPUT, 0, 0);
if (dt == NULL || PyDict_SetItemString(d, "min", dt) < 0)
return;
Py_DECREF(dt);
! dt = new_delta(TOOBIG_INPUT-1, 24*3600-1, 1000000-1);
if (dt == NULL || PyDict_SetItemString(d, "max", dt) < 0)
return;
--- 614,628 ----
return;
! dt = new_delta(0, 0, 1, 0);
if (dt == NULL || PyDict_SetItemString(d, "resolution", dt) < 0)
return;
Py_DECREF(dt);
! dt = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
if (dt == NULL || PyDict_SetItemString(d, "min", dt) < 0)
return;
Py_DECREF(dt);
! dt = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
if (dt == NULL || PyDict_SetItemString(d, "max", dt) < 0)
return;
***************
*** 634,638 ****
Py_DECREF(dt);
! dt = new_delta(1, 0, 0);
if (dt == NULL || PyDict_SetItemString(d, "resolution", dt) < 0)
return;
--- 642,646 ----
Py_DECREF(dt);
! dt = new_delta(1, 0, 0, 0);
if (dt == NULL || PyDict_SetItemString(d, "resolution", dt) < 0)
return;
***************
*** 652,656 ****
Py_DECREF(dt);
! dt = new_delta(0, 0, 1);
if (dt == NULL || PyDict_SetItemString(d, "resolution", dt) < 0)
return;
--- 660,664 ----
Py_DECREF(dt);
! dt = new_delta(0, 0, 1, 0);
if (dt == NULL || PyDict_SetItemString(d, "resolution", dt) < 0)
return;
Index: obj_date.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_date.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -d -r1.19 -r1.20
*** obj_date.c 3 Dec 2002 19:32:27 -0000 1.19
--- obj_date.c 4 Dec 2002 05:08:14 -0000 1.20
***************
*** 305,309 ****
GET_MONTH(right),
GET_DAY(right));
! return new_delta(left_ord - right_ord, 0, 0);
}
if (PyType_IsSubtype(right_type, &PyDateTime_DeltaType)) {
--- 305,309 ----
GET_MONTH(right),
GET_DAY(right));
! return new_delta(left_ord - right_ord, 0, 0, 0);
}
if (PyType_IsSubtype(right_type, &PyDateTime_DeltaType)) {
Index: obj_datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_datetime.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -d -r1.14 -r1.15
*** obj_datetime.c 3 Dec 2002 19:32:27 -0000 1.14
--- obj_datetime.c 4 Dec 2002 05:08:14 -0000 1.15
***************
*** 77,81 ****
long delta_us = GET_MICROSECOND(left) - GET_MICROSECOND(right);
! return new_delta(days1 - days2, seconds1 - seconds2, delta_us);
}
--- 77,81 ----
long delta_us = GET_MICROSECOND(left) - GET_MICROSECOND(right);
! return new_delta(days1 - days2, seconds1 - seconds2, delta_us, 1);
}
Index: obj_delta.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_delta.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -d -r1.20 -r1.21
*** obj_delta.c 3 Dec 2002 20:43:44 -0000 1.20
--- obj_delta.c 4 Dec 2002 05:08:14 -0000 1.21
***************
*** 116,120 ****
if (d == -1 && PyErr_Occurred())
goto Done;
! result = new_delta(d, s, us);
Done:
--- 116,120 ----
if (d == -1 && PyErr_Occurred())
goto Done;
! result = new_delta(d, s, us, 0);
Done:
***************
*** 181,185 ****
long microseconds = GET_TD_MICROSECONDS(left) +
GET_TD_MICROSECONDS(right);
! result = new_delta(days, seconds, microseconds);
}
--- 181,185 ----
long microseconds = GET_TD_MICROSECONDS(left) +
GET_TD_MICROSECONDS(right);
! result = new_delta(days, seconds, microseconds, 1);
}
***************
*** 194,198 ****
return new_delta(-GET_TD_DAYS(self),
-GET_TD_SECONDS(self),
! -GET_TD_MICROSECONDS(self));
}
--- 194,199 ----
return new_delta(-GET_TD_DAYS(self),
-GET_TD_SECONDS(self),
! -GET_TD_MICROSECONDS(self),
! 1);
}
***************
*** 205,209 ****
return new_delta(GET_TD_DAYS(self),
GET_TD_SECONDS(self),
! GET_TD_MICROSECONDS(self));
}
--- 206,211 ----
return new_delta(GET_TD_DAYS(self),
GET_TD_SECONDS(self),
! GET_TD_MICROSECONDS(self),
! 0);
}