diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-09-18 14:53:08 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-09-18 14:53:08 (GMT) |
commit | cd06812971dede4c6b459eb9e1295fdbc247dacc (patch) | |
tree | 62f3c1b7aa8442c18797669d4dfb54682467bce9 /Objects | |
parent | 81fd8040341a991b482bf3fecec454286274ef79 (diff) | |
download | cpython-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.c | 133 |
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)) { |