[Python-checkins] r62356 - in python/branches/py3k: Misc/NEWS Objects/longobject.c
mark.dickinson
python-checkins at python.org
Tue Apr 15 23:42:42 CEST 2008
Author: mark.dickinson
Date: Tue Apr 15 23:42:42 2008
New Revision: 62356
Log:
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.
Modified:
python/branches/py3k/Misc/NEWS
python/branches/py3k/Objects/longobject.c
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Tue Apr 15 23:42:42 2008
@@ -12,6 +12,9 @@
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",
when the code executed by exec() raises an exception, and sys.stdout.flush()
also raises an error.
Modified: python/branches/py3k/Objects/longobject.c
==============================================================================
--- python/branches/py3k/Objects/longobject.c (original)
+++ python/branches/py3k/Objects/longobject.c Tue Apr 15 23:42:42 2008
@@ -1099,13 +1099,39 @@
PyObject *
PyLong_FromSsize_t(Py_ssize_t ival)
{
- Py_ssize_t bytes = ival;
- int one = 1;
- if (ival < PyLong_BASE)
- return PyLong_FromLong(ival);
- return _PyLong_FromByteArray(
- (unsigned char *)&bytes,
- SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 1);
+ PyLongObject *v;
+ size_t abs_ival;
+ size_t t; /* unsigned so >> doesn't propagate sign bit */
+ int ndigits = 0;
+ int negative = 0;
+
+ 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. */
@@ -1113,13 +1139,28 @@
PyObject *
PyLong_FromSize_t(size_t ival)
{
- size_t bytes = ival;
- int one = 1;
+ PyLongObject *v;
+ size_t t;
+ int ndigits = 0;
+
if (ival < PyLong_BASE)
return PyLong_FromLong(ival);
- return _PyLong_FromByteArray(
- (unsigned char *)&bytes,
- SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 0);
+ /* Count the number of Python digits. */
+ t = ival;
+ 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.
More information about the Python-checkins
mailing list