summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-09-18 14:53:08 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-09-18 14:53:08 (GMT)
commitcd06812971dede4c6b459eb9e1295fdbc247dacc (patch)
tree62f3c1b7aa8442c18797669d4dfb54682467bce9 /Objects
parent81fd8040341a991b482bf3fecec454286274ef79 (diff)
downloadcpython-cd06812971dede4c6b459eb9e1295fdbc247dacc.zip
cpython-cd06812971dede4c6b459eb9e1295fdbc247dacc.tar.gz
cpython-cd06812971dede4c6b459eb9e1295fdbc247dacc.tar.bz2
Issue #6713 (continued): remove unused arbitrary-base conversion code
from _PyLong_Format.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/longobject.c133
1 files changed, 34 insertions, 99 deletions
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 9f414ca..e56602e 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -1763,8 +1763,8 @@ long_to_decimal_string(PyObject *aa)
return (PyObject *)str;
}
-/* Convert a long int object to a string, using a given conversion base.
- Return a string object.
+/* Convert a long int object to a string, using a given conversion base,
+ which should be one of 2, 8, 10 or 16. Return a string object.
If base is 2, 8 or 16, add the proper prefix '0b', '0o' or '0x'. */
PyObject *
@@ -1774,10 +1774,10 @@ _PyLong_Format(PyObject *aa, int base)
PyObject *str;
Py_ssize_t i, sz;
Py_ssize_t size_a;
- Py_UNICODE *p;
+ Py_UNICODE *p, sign = '\0';
int bits;
- char sign = '\0';
+ assert(base == 2 || base == 8 || base == 10 || base == 16);
if (base == 10)
return long_to_decimal_string((PyObject *)a);
@@ -1785,24 +1785,33 @@ _PyLong_Format(PyObject *aa, int base)
PyErr_BadInternalCall();
return NULL;
}
- assert(base >= 2 && base <= 36);
size_a = ABS(Py_SIZE(a));
/* Compute a rough upper bound for the length of the string */
- i = base;
- bits = 0;
- while (i > 1) {
- ++bits;
- i >>= 1;
- }
- i = 5;
- /* ensure we don't get signed overflow in sz calculation */
- if (size_a > (PY_SSIZE_T_MAX - i) / PyLong_SHIFT) {
+ switch (base) {
+ case 16:
+ bits = 4;
+ break;
+ case 8:
+ bits = 3;
+ break;
+ case 2:
+ bits = 1;
+ break;
+ default:
+ assert(0); /* shouldn't ever get here */
+ bits = 0; /* to silence gcc warning */
+ }
+ /* compute length of output string: allow 2 characters for prefix and
+ 1 for possible '-' sign. */
+ if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT) {
PyErr_SetString(PyExc_OverflowError,
"int is too large to format");
return NULL;
}
- sz = i + 1 + (size_a * PyLong_SHIFT - 1) / bits;
+ /* now size_a * PyLong_SHIFT + 3 <= PY_SSIZE_T_MAX, so the RHS below
+ is safe from overflow */
+ sz = 3 + (size_a * PyLong_SHIFT + (bits - 1)) / bits;
assert(sz >= 0);
str = PyUnicode_FromUnicode(NULL, sz);
if (str == NULL)
@@ -1815,106 +1824,32 @@ _PyLong_Format(PyObject *aa, int base)
if (Py_SIZE(a) == 0) {
*--p = '0';
}
- else if ((base & (base - 1)) == 0) {
+ else {
/* JRH: special case for power-of-2 bases */
twodigits accum = 0;
int accumbits = 0; /* # of bits in accum */
- int basebits = 1; /* # of bits in base-1 */
- i = base;
- while ((i >>= 1) > 1)
- ++basebits;
-
for (i = 0; i < size_a; ++i) {
accum |= (twodigits)a->ob_digit[i] << accumbits;
accumbits += PyLong_SHIFT;
- assert(accumbits >= basebits);
+ assert(accumbits >= bits);
do {
- char cdigit = (char)(accum & (base - 1));
+ Py_UNICODE cdigit = accum & (base - 1);
cdigit += (cdigit < 10) ? '0' : 'a'-10;
assert(p > PyUnicode_AS_UNICODE(str));
*--p = cdigit;
- accumbits -= basebits;
- accum >>= basebits;
- } while (i < size_a-1 ? accumbits >= basebits :
- accum > 0);
- }
- }
- else {
- /* Not 0, and base not a power of 2. Divide repeatedly by
- base, but for speed use the highest power of base that
- fits in a digit. */
- Py_ssize_t size = size_a;
- digit *pin = a->ob_digit;
- PyLongObject *scratch;
- /* powbasw <- largest power of base that fits in a digit. */
- digit powbase = base; /* powbase == base ** power */
- int power = 1;
- for (;;) {
- twodigits newpow = powbase * (twodigits)base;
- if (newpow >> PyLong_SHIFT)
- /* doesn't fit in a digit */
- break;
- powbase = (digit)newpow;
- ++power;
- }
-
- /* Get a scratch area for repeated division. */
- scratch = _PyLong_New(size);
- if (scratch == NULL) {
- Py_DECREF(str);
- return NULL;
+ accumbits -= bits;
+ accum >>= bits;
+ } while (i < size_a-1 ? accumbits >= bits : accum > 0);
}
-
- /* Repeatedly divide by powbase. */
- do {
- int ntostore = power;
- digit rem = inplace_divrem1(scratch->ob_digit,
- pin, size, powbase);
- pin = scratch->ob_digit; /* no need to use a again */
- if (pin[size - 1] == 0)
- --size;
- SIGCHECK({
- Py_DECREF(scratch);
- Py_DECREF(str);
- return NULL;
- })
-
- /* Break rem into digits. */
- assert(ntostore > 0);
- do {
- digit nextrem = (digit)(rem / base);
- char c = (char)(rem - nextrem * base);
- assert(p > PyUnicode_AS_UNICODE(str));
- c += (c < 10) ? '0' : 'a'-10;
- *--p = c;
- rem = nextrem;
- --ntostore;
- /* Termination is a bit delicate: must not
- store leading zeroes, so must get out if
- remaining quotient and rem are both 0. */
- } while (ntostore && (size || rem));
- } while (size != 0);
- Py_DECREF(scratch);
}
- if (base == 16) {
+ if (base == 16)
*--p = 'x';
- *--p = '0';
- }
- else if (base == 8) {
+ else if (base == 8)
*--p = 'o';
- *--p = '0';
- }
- else if (base == 2) {
+ else /* (base == 2) */
*--p = 'b';
- *--p = '0';
- }
- else if (base != 10) {
- *--p = '#';
- *--p = '0' + base%10;
- if (base > 10)
- *--p = '0' + base/10;
- }
+ *--p = '0';
if (sign)
*--p = sign;
if (p != PyUnicode_AS_UNICODE(str)) {