[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, &microseconds);
  
!  	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, &microseconds);
! 	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);
  }