mirror of https://github.com/python/cpython.git
Added better handling of unsigned longs -- a Python long returned by
unpack('L', ...) is now acceptable to pack('L', ...).
This commit is contained in:
parent
36bb181cdf
commit
60c50614e1
|
@ -73,34 +73,75 @@ typedef struct { char c; double x; } s_double;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Helper routine to turn a (signed) long into an unsigned long */
|
/* Global that will contain 2**<bits-per-long> */
|
||||||
|
|
||||||
|
static PyObject *offset = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper to create 2**<bits-per-long> */
|
||||||
/* XXX This assumes 2's complement arithmetic */
|
/* XXX This assumes 2's complement arithmetic */
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
init_offset()
|
||||||
|
{
|
||||||
|
PyObject *result = NULL;
|
||||||
|
PyObject *one = PyLong_FromLong(1L);
|
||||||
|
PyObject *shiftcount = PyLong_FromLong(8 * sizeof(long));
|
||||||
|
if (one == NULL || shiftcount == NULL)
|
||||||
|
goto finally;
|
||||||
|
result = PyNumber_Lshift(one, shiftcount);
|
||||||
|
finally:
|
||||||
|
Py_XDECREF(one);
|
||||||
|
Py_XDECREF(shiftcount);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper to add offset to a number */
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
add_offset(v)
|
||||||
|
PyObject *v;
|
||||||
|
{
|
||||||
|
PyObject *result = NULL;
|
||||||
|
if (offset == NULL) {
|
||||||
|
if ((offset = init_offset()) == NULL)
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
result = PyNumber_Add(v, offset);
|
||||||
|
finally:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Same, but subtracting */
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sub_offset(v)
|
||||||
|
PyObject *v;
|
||||||
|
{
|
||||||
|
PyObject *result = NULL;
|
||||||
|
if (offset == NULL) {
|
||||||
|
if ((offset = init_offset()) == NULL)
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
result = PyNumber_Subtract(v, offset);
|
||||||
|
finally:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper routine to turn a (signed) long into an unsigned long */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
make_ulong(x)
|
make_ulong(x)
|
||||||
long x;
|
long x;
|
||||||
{
|
{
|
||||||
PyObject *v = PyLong_FromLong(x);
|
PyObject *v = PyLong_FromLong(x);
|
||||||
if (x < 0 && v != NULL) {
|
if (x < 0 && v != NULL) {
|
||||||
static PyObject *offset = NULL;
|
PyObject *w = add_offset(v);
|
||||||
PyObject *result = NULL;
|
|
||||||
if (offset == NULL) {
|
|
||||||
PyObject *one = PyLong_FromLong(1L);
|
|
||||||
PyObject *shiftcount =
|
|
||||||
PyLong_FromLong(8 * sizeof(long));
|
|
||||||
if (one == NULL || shiftcount == NULL)
|
|
||||||
goto bad;
|
|
||||||
offset = PyNumber_Lshift(one, shiftcount);
|
|
||||||
bad:
|
|
||||||
Py_XDECREF(one);
|
|
||||||
Py_XDECREF(shiftcount);
|
|
||||||
if (offset == NULL)
|
|
||||||
goto finally;
|
|
||||||
}
|
|
||||||
result = PyNumber_Add(v, offset);
|
|
||||||
finally:
|
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
return result;
|
return w;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return v;
|
return v;
|
||||||
|
@ -126,6 +167,39 @@ get_long(v, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Same, but handling unsigned long */
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_ulong(v, p)
|
||||||
|
PyObject *v;
|
||||||
|
unsigned long *p;
|
||||||
|
{
|
||||||
|
long x = PyInt_AsLong(v);
|
||||||
|
PyObject *exc;
|
||||||
|
if (x == -1 && (exc = PyErr_Occurred()) != NULL) {
|
||||||
|
if (exc == PyExc_OverflowError) {
|
||||||
|
/* Try again after subtracting offset */
|
||||||
|
PyObject *w;
|
||||||
|
PyErr_Clear();
|
||||||
|
if ((w = sub_offset(v)) == NULL)
|
||||||
|
return -1;
|
||||||
|
x = PyInt_AsLong(w);
|
||||||
|
Py_DECREF(w);
|
||||||
|
if (x != -1 || (exc = PyErr_Occurred()) == NULL)
|
||||||
|
goto okay;
|
||||||
|
}
|
||||||
|
if (exc == PyExc_TypeError)
|
||||||
|
PyErr_SetString(StructError,
|
||||||
|
"required argument is not an integer");
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
okay:
|
||||||
|
*p = x;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The translation function for each format character is table driven */
|
/* The translation function for each format character is table driven */
|
||||||
|
|
||||||
typedef struct _formatdef {
|
typedef struct _formatdef {
|
||||||
|
@ -290,6 +364,19 @@ np_int(p, v, f)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
np_uint(p, v, f)
|
||||||
|
char *p;
|
||||||
|
PyObject *v;
|
||||||
|
const formatdef *f;
|
||||||
|
{
|
||||||
|
unsigned long x;
|
||||||
|
if (get_ulong(v, &x) < 0)
|
||||||
|
return -1;
|
||||||
|
* (unsigned int *)p = x;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
np_long(p, v, f)
|
np_long(p, v, f)
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -303,6 +390,19 @@ np_long(p, v, f)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
np_ulong(p, v, f)
|
||||||
|
char *p;
|
||||||
|
PyObject *v;
|
||||||
|
const formatdef *f;
|
||||||
|
{
|
||||||
|
unsigned long x;
|
||||||
|
if (get_ulong(v, &x) < 0)
|
||||||
|
return -1;
|
||||||
|
* (unsigned long *)p = x;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
np_float(p, v, f)
|
np_float(p, v, f)
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -344,9 +444,9 @@ static formatdef native_table[] = {
|
||||||
{'h', sizeof(short), SHORT_ALIGN, nu_short, np_short},
|
{'h', sizeof(short), SHORT_ALIGN, nu_short, np_short},
|
||||||
{'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_short},
|
{'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_short},
|
||||||
{'i', sizeof(int), INT_ALIGN, nu_int, np_int},
|
{'i', sizeof(int), INT_ALIGN, nu_int, np_int},
|
||||||
{'I', sizeof(int), INT_ALIGN, nu_uint, np_int},
|
{'I', sizeof(int), INT_ALIGN, nu_uint, np_uint},
|
||||||
{'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
|
{'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
|
||||||
{'L', sizeof(long), LONG_ALIGN, nu_ulong, np_long},
|
{'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong},
|
||||||
{'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
|
{'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
|
||||||
{'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
|
{'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
|
||||||
{0}
|
{0}
|
||||||
|
@ -404,6 +504,24 @@ bp_int(p, v, f)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bp_uint(p, v, f)
|
||||||
|
char *p;
|
||||||
|
PyObject *v;
|
||||||
|
const formatdef *f;
|
||||||
|
{
|
||||||
|
unsigned long x;
|
||||||
|
int i;
|
||||||
|
if (get_ulong(v, &x) < 0)
|
||||||
|
return -1;
|
||||||
|
i = f->size;
|
||||||
|
do {
|
||||||
|
p[--i] = x;
|
||||||
|
x >>= 8;
|
||||||
|
} while (i > 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static formatdef bigendian_table[] = {
|
static formatdef bigendian_table[] = {
|
||||||
{'x', 1, 0, NULL},
|
{'x', 1, 0, NULL},
|
||||||
{'b', 1, 0, bu_int, bp_int},
|
{'b', 1, 0, bu_int, bp_int},
|
||||||
|
@ -411,11 +529,11 @@ static formatdef bigendian_table[] = {
|
||||||
{'c', 1, 0, nu_char, np_char},
|
{'c', 1, 0, nu_char, np_char},
|
||||||
{'s', 1, 0, NULL},
|
{'s', 1, 0, NULL},
|
||||||
{'h', 2, 0, bu_int, bp_int},
|
{'h', 2, 0, bu_int, bp_int},
|
||||||
{'H', 2, 0, bu_uint, bp_int},
|
{'H', 2, 0, bu_uint, bp_uint},
|
||||||
{'i', 4, 0, bu_int, bp_int},
|
{'i', 4, 0, bu_int, bp_int},
|
||||||
{'I', 4, 0, bu_uint, bp_int},
|
{'I', 4, 0, bu_uint, bp_uint},
|
||||||
{'l', 4, 0, bu_int, bp_int},
|
{'l', 4, 0, bu_int, bp_int},
|
||||||
{'L', 4, 0, bu_uint, bp_int},
|
{'L', 4, 0, bu_uint, bp_uint},
|
||||||
/* No float and double! */
|
/* No float and double! */
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
@ -472,6 +590,24 @@ lp_int(p, v, f)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lp_uint(p, v, f)
|
||||||
|
char *p;
|
||||||
|
PyObject *v;
|
||||||
|
const formatdef *f;
|
||||||
|
{
|
||||||
|
unsigned long x;
|
||||||
|
int i;
|
||||||
|
if (get_ulong(v, &x) < 0)
|
||||||
|
return -1;
|
||||||
|
i = f->size;
|
||||||
|
do {
|
||||||
|
*p++ = x;
|
||||||
|
x >>= 8;
|
||||||
|
} while (--i > 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static formatdef lilendian_table[] = {
|
static formatdef lilendian_table[] = {
|
||||||
{'x', 1, 0, NULL},
|
{'x', 1, 0, NULL},
|
||||||
{'b', 1, 0, lu_int, lp_int},
|
{'b', 1, 0, lu_int, lp_int},
|
||||||
|
@ -479,11 +615,11 @@ static formatdef lilendian_table[] = {
|
||||||
{'c', 1, 0, nu_char, np_char},
|
{'c', 1, 0, nu_char, np_char},
|
||||||
{'s', 1, 0, NULL},
|
{'s', 1, 0, NULL},
|
||||||
{'h', 2, 0, lu_int, lp_int},
|
{'h', 2, 0, lu_int, lp_int},
|
||||||
{'H', 2, 0, lu_uint, lp_int},
|
{'H', 2, 0, lu_uint, lp_uint},
|
||||||
{'i', 4, 0, lu_int, lp_int},
|
{'i', 4, 0, lu_int, lp_int},
|
||||||
{'I', 4, 0, lu_uint, lp_int},
|
{'I', 4, 0, lu_uint, lp_uint},
|
||||||
{'l', 4, 0, lu_int, lp_int},
|
{'l', 4, 0, lu_int, lp_int},
|
||||||
{'L', 4, 0, lu_uint, lp_int},
|
{'L', 4, 0, lu_uint, lp_uint},
|
||||||
/* No float and double! */
|
/* No float and double! */
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue