Added PyNumber_ToBase and supporting routines _PyInt_Format and

_PyLong_Format.  In longobject.c, changed long_format to
_PyLong_Format.  In intobject.c, changed uses of PyOS_snprintf to
_PyInt_Format instead.

_PyLong_Format is similar to py3k's routine of the same name, except
it has 2 additional parameters: addL and newstyle.  addL was existing
in long_format, and controls adding the trailing "L".  This is
unneeded in py3k.  newstyle is used to control whether octal prepends
"0" (the pre-2.6 style), or "0o" (the 3.0 sytle).

PyNumber_ToBase is needed for PEP 3127 (Integer Literal Support and
Syntax) and PEP 3101 (Advanced String Formatting).

This changeset does not need merging into py3k.
This commit is contained in:
Eric Smith 2008-02-10 01:36:53 +00:00
parent 14a1b8cc46
commit 5e527ebee1
5 changed files with 126 additions and 33 deletions

View file

@ -437,9 +437,7 @@ int_print(PyIntObject *v, FILE *fp, int flags)
static PyObject *
int_repr(PyIntObject *v)
{
char buf[64];
PyOS_snprintf(buf, sizeof(buf), "%ld", v->ob_ival);
return PyString_FromString(buf);
return _PyInt_Format(v, 10, 0);
}
static int
@ -938,27 +936,13 @@ int_float(PyIntObject *v)
static PyObject *
int_oct(PyIntObject *v)
{
char buf[100];
long x = v -> ob_ival;
if (x < 0)
PyOS_snprintf(buf, sizeof(buf), "-0%lo", -x);
else if (x == 0)
strcpy(buf, "0");
else
PyOS_snprintf(buf, sizeof(buf), "0%lo", x);
return PyString_FromString(buf);
return _PyInt_Format(v, 8, 0);
}
static PyObject *
int_hex(PyIntObject *v)
{
char buf[100];
long x = v -> ob_ival;
if (x < 0)
PyOS_snprintf(buf, sizeof(buf), "-0x%lx", -x);
else
PyOS_snprintf(buf, sizeof(buf), "0x%lx", x);
return PyString_FromString(buf);
return _PyInt_Format(v, 16, 0);
}
static PyObject *
@ -1056,6 +1040,74 @@ int_getN(PyIntObject *v, void *context) {
return PyInt_FromLong((intptr_t)context);
}
/* Convert an integer to the given base. Returns a string.
If base is 2, 8 or 16, add the proper prefix '0b', '0o' or '0x'.
If newstyle is zero, then use the pre-2.6 behavior of octal having
a leading "0" */
PyAPI_FUNC(PyObject*)
_PyInt_Format(PyIntObject *v, int base, int newstyle)
{
/* There are no doubt many, many ways to optimize this, using code
similar to _PyLong_Format */
long n = v->ob_ival;
int negative = n < 0;
int is_zero = n == 0;
/* For the reasoning behind this size, see
http://c-faq.com/misc/hexio.html. Then, add a few bytes for
the possible sign and prefix "0[box]" */
char buf[sizeof(n)*CHAR_BIT+6];
/* Start by pointing to the end of the buffer. We fill in from
the back forward. */
char* p = &buf[sizeof(buf)];
assert(base >= 2 && base <= 36);
do {
/* I'd use i_divmod, except it doesn't produce the results
I want when n is negative. So just duplicate the salient
part here. */
long div = n / base;
long mod = n - div * base;
/* convert abs(mod) to the right character in [0-9, a-z] */
char cdigit = (char)(mod < 0 ? -mod : mod);
cdigit += (cdigit < 10) ? '0' : 'a'-10;
*--p = cdigit;
n = div;
} while(n);
if (base == 2) {
*--p = 'b';
*--p = '0';
}
else if (base == 8) {
if (newstyle) {
*--p = 'o';
*--p = '0';
}
else
if (!is_zero)
*--p = '0';
}
else if (base == 16) {
*--p = 'x';
*--p = '0';
}
else if (base != 10) {
*--p = '#';
*--p = '0' + base%10;
if (base > 10)
*--p = '0' + base/10;
}
if (negative)
*--p = '-';
return PyString_FromStringAndSize(p, &buf[sizeof(buf)] - p);
}
static PyMethodDef int_methods[] = {
{"conjugate", (PyCFunction)int_int, METH_NOARGS,
"Returns self, the complex conjugate of any int."},