mirror of
https://github.com/python/cpython.git
synced 2025-10-25 07:48:51 +00:00
PyLong_FromSsize_t was incorrect when sizeof(size_t) > sizeof(long);
rewrite it so that it doesn't care about relative sizes of size_t, long and long long. The rewrite is modeled on PyLong_FromLong, instead of using PyLong_FromByteArray; this makes the algorithm simpler and more direct, and possibly also slightly faster.
This commit is contained in:
parent
32dde22186
commit
7ab6be216a
2 changed files with 56 additions and 12 deletions
|
|
@ -12,6 +12,9 @@ What's New in Python 3.0a5?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Fix misbehaviour of PyLong_FromSsize_t on systems where sizeof(size_t) >
|
||||||
|
sizeof(long).
|
||||||
|
|
||||||
- Issue #2221: Corrected a SystemError "error return without exception set",
|
- Issue #2221: Corrected a SystemError "error return without exception set",
|
||||||
when the code executed by exec() raises an exception, and sys.stdout.flush()
|
when the code executed by exec() raises an exception, and sys.stdout.flush()
|
||||||
also raises an error.
|
also raises an error.
|
||||||
|
|
|
||||||
|
|
@ -1099,13 +1099,39 @@ PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG ival)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyLong_FromSsize_t(Py_ssize_t ival)
|
PyLong_FromSsize_t(Py_ssize_t ival)
|
||||||
{
|
{
|
||||||
Py_ssize_t bytes = ival;
|
PyLongObject *v;
|
||||||
int one = 1;
|
size_t abs_ival;
|
||||||
if (ival < PyLong_BASE)
|
size_t t; /* unsigned so >> doesn't propagate sign bit */
|
||||||
return PyLong_FromLong(ival);
|
int ndigits = 0;
|
||||||
return _PyLong_FromByteArray(
|
int negative = 0;
|
||||||
(unsigned char *)&bytes,
|
|
||||||
SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 1);
|
CHECK_SMALL_INT(ival);
|
||||||
|
if (ival < 0) {
|
||||||
|
/* avoid signed overflow when ival = SIZE_T_MIN */
|
||||||
|
abs_ival = (size_t)(-1-ival)+1;
|
||||||
|
negative = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
abs_ival = (size_t)ival;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count the number of Python digits. */
|
||||||
|
t = abs_ival;
|
||||||
|
while (t) {
|
||||||
|
++ndigits;
|
||||||
|
t >>= PyLong_SHIFT;
|
||||||
|
}
|
||||||
|
v = _PyLong_New(ndigits);
|
||||||
|
if (v != NULL) {
|
||||||
|
digit *p = v->ob_digit;
|
||||||
|
Py_SIZE(v) = negative ? -ndigits : ndigits;
|
||||||
|
t = abs_ival;
|
||||||
|
while (t) {
|
||||||
|
*p++ = (digit)(t & PyLong_MASK);
|
||||||
|
t >>= PyLong_SHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (PyObject *)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new long int object from a C size_t. */
|
/* Create a new long int object from a C size_t. */
|
||||||
|
|
@ -1113,13 +1139,28 @@ PyLong_FromSsize_t(Py_ssize_t ival)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyLong_FromSize_t(size_t ival)
|
PyLong_FromSize_t(size_t ival)
|
||||||
{
|
{
|
||||||
size_t bytes = ival;
|
PyLongObject *v;
|
||||||
int one = 1;
|
size_t t;
|
||||||
|
int ndigits = 0;
|
||||||
|
|
||||||
if (ival < PyLong_BASE)
|
if (ival < PyLong_BASE)
|
||||||
return PyLong_FromLong(ival);
|
return PyLong_FromLong(ival);
|
||||||
return _PyLong_FromByteArray(
|
/* Count the number of Python digits. */
|
||||||
(unsigned char *)&bytes,
|
t = ival;
|
||||||
SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 0);
|
while (t) {
|
||||||
|
++ndigits;
|
||||||
|
t >>= PyLong_SHIFT;
|
||||||
|
}
|
||||||
|
v = _PyLong_New(ndigits);
|
||||||
|
if (v != NULL) {
|
||||||
|
digit *p = v->ob_digit;
|
||||||
|
Py_SIZE(v) = ndigits;
|
||||||
|
while (ival) {
|
||||||
|
*p++ = (digit)(ival & PyLong_MASK);
|
||||||
|
ival >>= PyLong_SHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (PyObject *)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a C PY_LONG_LONG int from a long int object.
|
/* Get a C PY_LONG_LONG int from a long int object.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue