[Python-checkins] CVS: python/dist/src/Modules structmodule.c,2.46,2.47

Tim Peters tim_one@users.sourceforge.net
Mon, 11 Jun 2001 18:22:24 -0700


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

Modified Files:
	structmodule.c 
Log Message:
Added q/Q standard (x-platform 8-byte ints) mode in struct module.
This completes the q/Q project.

longobject.c _PyLong_AsByteArray:  The original code had a gross bug:
the most-significant Python digit doesn't necessarily have SHIFT
significant bits, and you really need to count how many copies of the sign
bit it has else spurious overflow errors result.

test_struct.py:  This now does exhaustive std q/Q testing at, and on both
sides of, all relevant power-of-2 boundaries, both positive and negative.

NEWS:  Added brief dict news while I was at it.


Index: structmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v
retrieving revision 2.46
retrieving revision 2.47
diff -C2 -r2.46 -r2.47
*** structmodule.c	2001/06/11 16:57:33	2.46
--- structmodule.c	2001/06/12 01:22:21	2.47
***************
*** 81,84 ****
--- 81,112 ----
  #endif
  
+ /* Helper to get a PyLongObject by hook or by crook.  Caller should decref. */
+ 
+ static PyObject *
+ get_pylong(PyObject *v)
+ {
+ 	PyNumberMethods *m;
+ 
+ 	assert(v != NULL);
+ 	if (PyInt_Check(v))
+ 		return PyLong_FromLong(PyInt_AS_LONG(v));
+ 	if (PyLong_Check(v)) {
+ 		Py_INCREF(v);
+ 		return v;
+ 	}
+ 	m = v->ob_type->tp_as_number;
+ 	if (m != NULL && m->nb_long != NULL) {
+ 		v = m->nb_long(v);
+ 		if (v == NULL)
+ 			return NULL;
+ 		if (PyLong_Check(v))
+ 			return v;
+ 		Py_DECREF(v);
+ 	}
+ 	PyErr_SetString(StructError,
+ 			"cannot convert argument to long");
+ 	return NULL;
+ }
+ 
  /* Helper routine to get a Python integer and raise the appropriate error
     if it isn't one */
***************
*** 124,154 ****
  {
  	LONG_LONG x;
- 	int v_needs_decref = 0;
  
! 	if (PyInt_Check(v)) {
! 		x = (LONG_LONG)PyInt_AS_LONG(v);
! 		*p = x;
! 		return 0;
! 	}
! 	if (!PyLong_Check(v)) {
! 		PyNumberMethods *m = v->ob_type->tp_as_number;
! 		if (m != NULL && m->nb_long != NULL) {
! 			v = m->nb_long(v);
! 			if (v == NULL)
! 				return -1;
! 			v_needs_decref = 1;
! 		}
! 		if (!PyLong_Check(v)) {
! 			PyErr_SetString(StructError,
! 					"cannot convert argument to long");
! 			if (v_needs_decref)
! 				Py_DECREF(v);
! 			return -1;
! 		}
! 	}
  	assert(PyLong_Check(v));
  	x = PyLong_AsLongLong(v);
! 	if (v_needs_decref)
! 		Py_DECREF(v);
  	if (x == (LONG_LONG)-1 && PyErr_Occurred())
  		return -1;
--- 152,162 ----
  {
  	LONG_LONG x;
  
! 	v = get_pylong(v);
! 	if (v == NULL)
! 		return -1;
  	assert(PyLong_Check(v));
  	x = PyLong_AsLongLong(v);
! 	Py_DECREF(v);
  	if (x == (LONG_LONG)-1 && PyErr_Occurred())
  		return -1;
***************
*** 163,199 ****
  {
  	unsigned LONG_LONG x;
- 	int v_needs_decref = 0;
  
! 	if (PyInt_Check(v)) {
! 		long i = PyInt_AS_LONG(v);
! 		if (i < 0) {
! 			PyErr_SetString(StructError, "can't convert negative "
! 					"int to unsigned");
! 			return -1;
! 		}
! 		x = (unsigned LONG_LONG)i;
! 		*p = x;
! 		return 0;
! 	}
! 	if (!PyLong_Check(v)) {
! 		PyNumberMethods *m = v->ob_type->tp_as_number;
! 		if (m != NULL && m->nb_long != NULL) {
! 			v = m->nb_long(v);
! 			if (v == NULL)
! 				return -1;
! 			v_needs_decref = 1;
! 		}
! 		if (!PyLong_Check(v)) {
! 			PyErr_SetString(StructError,
! 					"cannot convert argument to long");
! 			if (v_needs_decref)
! 				Py_DECREF(v);
! 			return -1;
! 		}
! 	}
  	assert(PyLong_Check(v));
  	x = PyLong_AsUnsignedLongLong(v);
! 	if (v_needs_decref)
! 		Py_DECREF(v);
  	if (x == (unsigned LONG_LONG)-1 && PyErr_Occurred())
  		return -1;
--- 171,181 ----
  {
  	unsigned LONG_LONG x;
  
! 	v = get_pylong(v);
! 	if (v == NULL)
! 		return -1;
  	assert(PyLong_Check(v));
  	x = PyLong_AsUnsignedLongLong(v);
! 	Py_DECREF(v);
  	if (x == (unsigned LONG_LONG)-1 && PyErr_Occurred())
  		return -1;
***************
*** 501,505 ****
  */
  
! /* Native mode routines. */
  
  static PyObject *
--- 483,487 ----
  */
  
! /* Native mode routines. ****************************************************/
  
  static PyObject *
***************
*** 798,801 ****
--- 780,785 ----
  };
  
+ /* Big-endian routines. *****************************************************/
+ 
  static PyObject *
  bu_int(const char *p, const formatdef *f)
***************
*** 827,830 ****
--- 811,832 ----
  
  static PyObject *
+ bu_longlong(const char *p, const formatdef *f)
+ {
+ 	return _PyLong_FromByteArray((const unsigned char *)p,
+ 				      8,
+ 				      0, /* little-endian */
+ 				      1  /* signed */);
+ }
+ 
+ static PyObject *
+ bu_ulonglong(const char *p, const formatdef *f)
+ {
+ 	return _PyLong_FromByteArray((const unsigned char *)p,
+ 				      8,
+ 				      0, /* little-endian */
+ 				      0  /* signed */);
+ }
+ 
+ static PyObject *
  bu_float(const char *p, const formatdef *f)
  {
***************
*** 869,872 ****
--- 871,902 ----
  
  static int
+ bp_longlong(char *p, PyObject *v, const formatdef *f)
+ {
+ 	int res;
+ 	v = get_pylong(v);
+ 	res = _PyLong_AsByteArray((PyLongObject *)v,
+ 			   	  (unsigned char *)p,
+ 				  8,
+ 				  0, /* little_endian */
+ 				  1  /* signed */);
+ 	Py_DECREF(v);
+ 	return res;
+ }
+ 
+ static int
+ bp_ulonglong(char *p, PyObject *v, const formatdef *f)
+ {
+ 	int res;
+ 	v = get_pylong(v);
+ 	res = _PyLong_AsByteArray((PyLongObject *)v,
+ 			   	  (unsigned char *)p,
+ 				  8,
+ 				  0, /* little_endian */
+ 				  0  /* signed */);
+ 	Py_DECREF(v);
+ 	return res;
+ }
+ 
+ static int
  bp_float(char *p, PyObject *v, const formatdef *f)
  {
***************
*** 905,908 ****
--- 935,940 ----
  	{'l',	4,		0,		bu_int,		bp_int},
  	{'L',	4,		0,		bu_uint,	bp_uint},
+ 	{'q',	8,		0,		bu_longlong,	bp_longlong},
+ 	{'Q',	8,		0,		bu_ulonglong,	bp_ulonglong},
  	{'f',	4,		0,		bu_float,	bp_float},
  	{'d',	8,		0,		bu_double,	bp_double},
***************
*** 910,913 ****
--- 942,947 ----
  };
  
+ /* Little-endian routines. *****************************************************/
+ 
  static PyObject *
  lu_int(const char *p, const formatdef *f)
***************
*** 939,942 ****
--- 973,994 ----
  
  static PyObject *
+ lu_longlong(const char *p, const formatdef *f)
+ {
+ 	return _PyLong_FromByteArray((const unsigned char *)p,
+ 				      8,
+ 				      1, /* little-endian */
+ 				      1  /* signed */);
+ }
+ 
+ static PyObject *
+ lu_ulonglong(const char *p, const formatdef *f)
+ {
+ 	return _PyLong_FromByteArray((const unsigned char *)p,
+ 				      8,
+ 				      1, /* little-endian */
+ 				      0  /* signed */);
+ }
+ 
+ static PyObject *
  lu_float(const char *p, const formatdef *f)
  {
***************
*** 981,984 ****
--- 1033,1064 ----
  
  static int
+ lp_longlong(char *p, PyObject *v, const formatdef *f)
+ {
+ 	int res;
+ 	v = get_pylong(v);
+ 	res = _PyLong_AsByteArray((PyLongObject*)v,
+ 			   	  (unsigned char *)p,
+ 				  8,
+ 				  1, /* little_endian */
+ 				  1  /* signed */);
+ 	Py_DECREF(v);
+ 	return res;
+ }
+ 
+ static int
+ lp_ulonglong(char *p, PyObject *v, const formatdef *f)
+ {
+ 	int res;
+ 	v = get_pylong(v);
+ 	res = _PyLong_AsByteArray((PyLongObject*)v,
+ 			   	  (unsigned char *)p,
+ 				  8,
+ 				  1, /* little_endian */
+ 				  0  /* signed */);
+ 	Py_DECREF(v);
+ 	return res;
+ }
+ 
+ static int
  lp_float(char *p, PyObject *v, const formatdef *f)
  {
***************
*** 1017,1020 ****
--- 1097,1102 ----
  	{'l',	4,		0,		lu_int,		lp_int},
  	{'L',	4,		0,		lu_uint,	lp_uint},
+ 	{'q',	8,		0,		lu_longlong,	lp_longlong},
+ 	{'Q',	8,		0,		lu_ulonglong,	lp_ulonglong},
  	{'f',	4,		0,		lu_float,	lp_float},
  	{'d',	8,		0,		lu_double,	lp_double},