Kaydet (Commit) 5e527ebe authored tarafından Eric Smith's avatar Eric Smith

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.
üst 14a1b8cc
...@@ -62,6 +62,12 @@ PyAPI_FUNC(long) PyOS_strtol(char *, char **, int); ...@@ -62,6 +62,12 @@ PyAPI_FUNC(long) PyOS_strtol(char *, char **, int);
/* free list api */ /* free list api */
PyAPI_FUNC(void) PyInt_CompactFreeList(size_t *, size_t *, size_t *); PyAPI_FUNC(void) PyInt_CompactFreeList(size_t *, size_t *, size_t *);
/* 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);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -112,6 +112,13 @@ PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v, ...@@ -112,6 +112,13 @@ PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v,
unsigned char* bytes, size_t n, unsigned char* bytes, size_t n,
int little_endian, int is_signed); int little_endian, int is_signed);
/* _PyLong_Format: Convert the long to a string object with given base,
appending a base prefix of 0[box] if base is 2, 8 or 16.
Add a trailing "L" if addL is non-zero.
If newstyle is zero, then use the pre-2.6 behavior of octal having
a leading "0", instead of the prefix "0o" */
PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *aa, int base, int addL, int newstyle);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -1262,6 +1262,25 @@ PyNumber_Float(PyObject *o) ...@@ -1262,6 +1262,25 @@ PyNumber_Float(PyObject *o)
return PyFloat_FromString(o, NULL); return PyFloat_FromString(o, NULL);
} }
PyObject *
PyNumber_ToBase(PyObject *n, int base)
{
PyObject *res = NULL;
PyObject *index = PyNumber_Index(n);
if (!index)
return NULL;
if (PyLong_Check(index))
res = _PyLong_Format(index, base, 0, 1);
else if (PyInt_Check(index))
res = _PyInt_Format((PyIntObject*)index, base, 1);
else
assert("PyNumber_ToBase: not long or int");
Py_DECREF(index);
return res;
}
/* Operations on sequences */ /* Operations on sequences */
int int
......
...@@ -437,9 +437,7 @@ int_print(PyIntObject *v, FILE *fp, int flags) ...@@ -437,9 +437,7 @@ int_print(PyIntObject *v, FILE *fp, int flags)
static PyObject * static PyObject *
int_repr(PyIntObject *v) int_repr(PyIntObject *v)
{ {
char buf[64]; return _PyInt_Format(v, 10, 0);
PyOS_snprintf(buf, sizeof(buf), "%ld", v->ob_ival);
return PyString_FromString(buf);
} }
static int static int
...@@ -938,27 +936,13 @@ int_float(PyIntObject *v) ...@@ -938,27 +936,13 @@ int_float(PyIntObject *v)
static PyObject * static PyObject *
int_oct(PyIntObject *v) int_oct(PyIntObject *v)
{ {
char buf[100]; return _PyInt_Format(v, 8, 0);
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);
} }
static PyObject * static PyObject *
int_hex(PyIntObject *v) int_hex(PyIntObject *v)
{ {
char buf[100]; return _PyInt_Format(v, 16, 0);
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);
} }
static PyObject * static PyObject *
...@@ -1056,6 +1040,74 @@ int_getN(PyIntObject *v, void *context) { ...@@ -1056,6 +1040,74 @@ int_getN(PyIntObject *v, void *context) {
return PyInt_FromLong((intptr_t)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[] = { static PyMethodDef int_methods[] = {
{"conjugate", (PyCFunction)int_int, METH_NOARGS, {"conjugate", (PyCFunction)int_int, METH_NOARGS,
"Returns self, the complex conjugate of any int."}, "Returns self, the complex conjugate of any int."},
......
...@@ -35,7 +35,6 @@ static PyLongObject *long_normalize(PyLongObject *); ...@@ -35,7 +35,6 @@ static PyLongObject *long_normalize(PyLongObject *);
static PyLongObject *mul1(PyLongObject *, wdigit); static PyLongObject *mul1(PyLongObject *, wdigit);
static PyLongObject *muladd1(PyLongObject *, wdigit, wdigit); static PyLongObject *muladd1(PyLongObject *, wdigit, wdigit);
static PyLongObject *divrem1(PyLongObject *, digit, digit *); static PyLongObject *divrem1(PyLongObject *, digit, digit *);
static PyObject *long_format(PyObject *aa, int base, int addL);
#define SIGCHECK(PyTryBlock) \ #define SIGCHECK(PyTryBlock) \
if (--_Py_Ticker < 0) { \ if (--_Py_Ticker < 0) { \
...@@ -1140,7 +1139,7 @@ muladd1(PyLongObject *a, wdigit n, wdigit extra) ...@@ -1140,7 +1139,7 @@ muladd1(PyLongObject *a, wdigit n, wdigit extra)
/* Divide long pin, w/ size digits, by non-zero digit n, storing quotient /* Divide long pin, w/ size digits, by non-zero digit n, storing quotient
in pout, and returning the remainder. pin and pout point at the LSD. in pout, and returning the remainder. pin and pout point at the LSD.
It's OK for pin == pout on entry, which saves oodles of mallocs/frees in It's OK for pin == pout on entry, which saves oodles of mallocs/frees in
long_format, but that should be done with great care since longs are _PyLong_Format, but that should be done with great care since longs are
immutable. */ immutable. */
static digit static digit
...@@ -1178,12 +1177,13 @@ divrem1(PyLongObject *a, digit n, digit *prem) ...@@ -1178,12 +1177,13 @@ divrem1(PyLongObject *a, digit n, digit *prem)
return long_normalize(z); return long_normalize(z);
} }
/* Convert a long int object to a string, using a given conversion base. /* Convert the long to a string object with given base,
Return a string object. appending a base prefix of 0[box] if base is 2, 8 or 16.
If base is 8 or 16, add the proper prefix '0' or '0x'. */ Add a trailing "L" if addL is non-zero.
If newstyle is zero, then use the pre-2.6 behavior of octal having
static PyObject * a leading "0", instead of the prefix "0o" */
long_format(PyObject *aa, int base, int addL) PyAPI_FUNC(PyObject *)
_PyLong_Format(PyObject *aa, int base, int addL, int newstyle)
{ {
register PyLongObject *a = (PyLongObject *)aa; register PyLongObject *a = (PyLongObject *)aa;
PyStringObject *str; PyStringObject *str;
...@@ -1309,9 +1309,18 @@ long_format(PyObject *aa, int base, int addL) ...@@ -1309,9 +1309,18 @@ long_format(PyObject *aa, int base, int addL)
Py_DECREF(scratch); Py_DECREF(scratch);
} }
if (base == 8) { if (base == 2) {
if (size_a != 0) *--p = 'b';
*--p = '0';
}
else if (base == 8) {
if (newstyle) {
*--p = 'o';
*--p = '0'; *--p = '0';
}
else
if (size_a != 0)
*--p = '0';
} }
else if (base == 16) { else if (base == 16) {
*--p = 'x'; *--p = 'x';
...@@ -1888,13 +1897,13 @@ long_dealloc(PyObject *v) ...@@ -1888,13 +1897,13 @@ long_dealloc(PyObject *v)
static PyObject * static PyObject *
long_repr(PyObject *v) long_repr(PyObject *v)
{ {
return long_format(v, 10, 1); return _PyLong_Format(v, 10, 1, 0);
} }
static PyObject * static PyObject *
long_str(PyObject *v) long_str(PyObject *v)
{ {
return long_format(v, 10, 0); return _PyLong_Format(v, 10, 0, 0);
} }
static int static int
...@@ -3268,13 +3277,13 @@ long_float(PyObject *v) ...@@ -3268,13 +3277,13 @@ long_float(PyObject *v)
static PyObject * static PyObject *
long_oct(PyObject *v) long_oct(PyObject *v)
{ {
return long_format(v, 8, 1); return _PyLong_Format(v, 8, 1, 0);
} }
static PyObject * static PyObject *
long_hex(PyObject *v) long_hex(PyObject *v)
{ {
return long_format(v, 16, 1); return _PyLong_Format(v, 16, 1, 0);
} }
static PyObject * static PyObject *
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment