[Python-checkins] CVS: python/dist/src/Objects longobject.c,1.74,1.75

Tim Peters tim_one@users.sourceforge.net
Tue, 12 Jun 2001 17:36:00 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv10010/python/dist/src/Objects

Modified Files:
	longobject.c 
Log Message:
longobject.c:
    Replaced PyLong_{As,From}{Unsigned,}LongLong guts with calls
    to _PyLong_{As,From}ByteArray.
_testcapimodule.c:
    Added strong tests of PyLong_{As,From}{Unsigned,}LongLong.

Fixes SF bug #432552 PyLong_AsLongLong() problems.
Possible bugfix candidate, but the fix relies on code added to longobject
to support the new q/Q structmodule format codes.


Index: longobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v
retrieving revision 1.74
retrieving revision 1.75
diff -C2 -r1.74 -r1.75
*** longobject.c	2001/06/12 19:17:03	1.74
--- longobject.c	2001/06/13 00:35:57	1.75
***************
*** 523,688 ****
  
  #ifdef HAVE_LONG_LONG
! /*
!  * LONG_LONG support by Chris Herborth (chrish@qnx.com)
!  *
!  * For better or worse :-), I tried to follow the coding style already
!  * here.
   */
  
! /* Create a new long int object from a C LONG_LONG int */
  
  PyObject *
  PyLong_FromLongLong(LONG_LONG ival)
  {
! #if SIZEOF_LONG_LONG == SIZEOF_LONG
! 	/* In case the compiler is faking it. */
! 	return PyLong_FromLong( (long)ival );
! #else
! 	if ((LONG_LONG)LONG_MIN <= ival && ival <= (LONG_LONG)LONG_MAX) {
! 		return PyLong_FromLong( (long)ival );
! 	}
! 	else if (0 <= ival && ival <= (unsigned LONG_LONG)ULONG_MAX) {
! 		return PyLong_FromUnsignedLong( (unsigned long)ival );
! 	}
! 	else {
! 		/* Assume a C LONG_LONG fits in at most 10 'digits'.
! 		 * Should be OK if we're assuming long fits in 5.
! 		 */
! 		PyLongObject *v = _PyLong_New(10);
! 
! 		if (v != NULL) {
! 			unsigned LONG_LONG t = ival;
! 			int i;
! 			if (ival < 0) {
! 				t = -ival;
! 				v->ob_size = -(v->ob_size);
!   			}
! 
! 			for (i = 0; i < 10; i++) {
! 				v->ob_digit[i] = (digit) (t & MASK);
! 				t >>= SHIFT;
! 			}
! 
! 			v = long_normalize(v);
! 		}
! 
! 		return (PyObject *)v;
! 	}
! #endif
  }
  
- /* Create a new long int object from a C unsigned LONG_LONG int */
  PyObject *
  PyLong_FromUnsignedLongLong(unsigned LONG_LONG ival)
  {
! #if SIZEOF_LONG_LONG == SIZEOF_LONG
! 	/* In case the compiler is faking it. */
! 	return PyLong_FromUnsignedLong( (unsigned long)ival );
! #else
! 	if( ival <= (unsigned LONG_LONG)ULONG_MAX ) {
! 		return PyLong_FromUnsignedLong( (unsigned long)ival );
! 	}
! 	else {
! 		/* Assume a C long fits in at most 10 'digits'. */
! 		PyLongObject *v = _PyLong_New(10);
! 
! 		if (v != NULL) {
! 			unsigned LONG_LONG t = ival;
! 			int i;
! 			for (i = 0; i < 10; i++) {
! 				v->ob_digit[i] = (digit) (t & MASK);
! 				t >>= SHIFT;
! 			}
! 
! 			v = long_normalize(v);
! 		}
! 
! 		return (PyObject *)v;
! 	}
! #endif
  }
  
  /* Get a C LONG_LONG int from a long int object.
!    Returns -1 and sets an error condition if overflow occurs. */
  
  LONG_LONG
  PyLong_AsLongLong(PyObject *vv)
  {
! #if SIZEOF_LONG_LONG == SIZEOF_LONG
! 	/* In case the compiler is faking it. */
! 	return (LONG_LONG)PyLong_AsLong( vv );
! #else
! 	register PyLongObject *v;
! 	LONG_LONG x, prev;
! 	int i, sign;
! 	
  	if (vv == NULL || !PyLong_Check(vv)) {
  		PyErr_BadInternalCall();
  		return -1;
  	}
- 
- 	v = (PyLongObject *)vv;
- 	i = v->ob_size;
- 	sign = 1;
- 	x = 0;
- 
- 	if (i < 0) {
- 		sign = -1;
- 		i = -(i);
- 	}
  
! 	while (--i >= 0) {
! 		prev = x;
! 		x = (x << SHIFT) + v->ob_digit[i];
! 		if ((x >> SHIFT) != prev) {
! 			PyErr_SetString(PyExc_OverflowError,
! 				"long int too long to convert");
! 			return -1;
! 		}
! 	}
  
! 	return x * sign;
! #endif
  }
  
  unsigned LONG_LONG
  PyLong_AsUnsignedLongLong(PyObject *vv)
  {
! #if SIZEOF_LONG_LONG == 4
! 	/* In case the compiler is faking it. */
! 	return (unsigned LONG_LONG)PyLong_AsUnsignedLong( vv );
! #else
! 	register PyLongObject *v;
! 	unsigned LONG_LONG x, prev;
! 	int i;
! 	
  	if (vv == NULL || !PyLong_Check(vv)) {
  		PyErr_BadInternalCall();
! 		return (unsigned LONG_LONG) -1;
! 	}
! 
! 	v = (PyLongObject *)vv;
! 	i = v->ob_size;
! 	x = 0;
! 
! 	if (i < 0) {
! 		PyErr_SetString(PyExc_OverflowError,
! 			   "can't convert negative value to unsigned long");
! 		return (unsigned LONG_LONG) -1;
  	}
  
! 	while (--i >= 0) {
! 		prev = x;
! 		x = (x << SHIFT) + v->ob_digit[i];
! 		if ((x >> SHIFT) != prev) {
! 			PyErr_SetString(PyExc_OverflowError,
! 				"long int too long to convert");
! 			return (unsigned LONG_LONG) -1;
! 		}
! 	}
  
! 	return x;
! #endif
  }
  #endif /* HAVE_LONG_LONG */
  
--- 523,603 ----
  
  #ifdef HAVE_LONG_LONG
! 
! /* Initial LONG_LONG support by Chris Herborth (chrish@qnx.com), later
!  * rewritten to use the newer PyLong_{As,From}ByteArray API.
   */
+ 
+ #define IS_LITTLE_ENDIAN *(char*)&one != '\0'
  
! /* Create a new long int object from a C LONG_LONG int. */
  
  PyObject *
  PyLong_FromLongLong(LONG_LONG ival)
  {
! 	LONG_LONG bytes = ival;
! 	int one = 1;
! 	return _PyLong_FromByteArray(
! 			(unsigned char *)&bytes,
! 			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
  }
+ 
+ /* Create a new long int object from a C unsigned LONG_LONG int. */
  
  PyObject *
  PyLong_FromUnsignedLongLong(unsigned LONG_LONG ival)
  {
! 	unsigned LONG_LONG bytes = ival;
! 	int one = 1;
! 	return _PyLong_FromByteArray(
! 			(unsigned char *)&bytes,
! 			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
  }
  
  /* Get a C LONG_LONG int from a long int object.
!    Return -1 and set an error if overflow occurs. */
  
  LONG_LONG
  PyLong_AsLongLong(PyObject *vv)
  {
! 	LONG_LONG bytes;
! 	int one = 1;
! 	int res;
! 
  	if (vv == NULL || !PyLong_Check(vv)) {
  		PyErr_BadInternalCall();
  		return -1;
  	}
  
! 	res = _PyLong_AsByteArray(
! 			(PyLongObject *)vv, (unsigned char *)&bytes,
! 			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
  
! 	return (LONG_LONG)(res < 0 ? res : bytes);
  }
  
+ /* Get a C unsigned LONG_LONG int from a long int object.
+    Return -1 and set an error if overflow occurs. */
+ 
  unsigned LONG_LONG
  PyLong_AsUnsignedLongLong(PyObject *vv)
  {
! 	unsigned LONG_LONG bytes;
! 	int one = 1;
! 	int res;
! 
  	if (vv == NULL || !PyLong_Check(vv)) {
  		PyErr_BadInternalCall();
! 		return -1;
  	}
  
! 	res = _PyLong_AsByteArray(
! 			(PyLongObject *)vv, (unsigned char *)&bytes,
! 			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
  
! 	return (unsigned LONG_LONG)(res < 0 ? res : bytes);
  }
+ 
+ #undef IS_LITTLE_ENDIAN
+ 
  #endif /* HAVE_LONG_LONG */