[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},