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:
parent
14a1b8cc46
commit
5e527ebee1
|
@ -62,6 +62,12 @@ PyAPI_FUNC(long) PyOS_strtol(char *, char **, int);
|
|||
/* free list api */
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -112,6 +112,13 @@ PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v,
|
|||
unsigned char* bytes, size_t n,
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1262,6 +1262,25 @@ PyNumber_Float(PyObject *o)
|
|||
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 */
|
||||
|
||||
int
|
||||
|
|
|
@ -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."},
|
||||
|
|
|
@ -35,7 +35,6 @@ static PyLongObject *long_normalize(PyLongObject *);
|
|||
static PyLongObject *mul1(PyLongObject *, wdigit);
|
||||
static PyLongObject *muladd1(PyLongObject *, wdigit, wdigit);
|
||||
static PyLongObject *divrem1(PyLongObject *, digit, digit *);
|
||||
static PyObject *long_format(PyObject *aa, int base, int addL);
|
||||
|
||||
#define SIGCHECK(PyTryBlock) \
|
||||
if (--_Py_Ticker < 0) { \
|
||||
|
@ -1140,7 +1139,7 @@ muladd1(PyLongObject *a, wdigit n, wdigit extra)
|
|||
/* 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.
|
||||
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. */
|
||||
|
||||
static digit
|
||||
|
@ -1178,12 +1177,13 @@ divrem1(PyLongObject *a, digit n, digit *prem)
|
|||
return long_normalize(z);
|
||||
}
|
||||
|
||||
/* Convert a long int object to a string, using a given conversion base.
|
||||
Return a string object.
|
||||
If base is 8 or 16, add the proper prefix '0' or '0x'. */
|
||||
|
||||
static PyObject *
|
||||
long_format(PyObject *aa, int base, int addL)
|
||||
/* 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)
|
||||
{
|
||||
register PyLongObject *a = (PyLongObject *)aa;
|
||||
PyStringObject *str;
|
||||
|
@ -1309,9 +1309,18 @@ long_format(PyObject *aa, int base, int addL)
|
|||
Py_DECREF(scratch);
|
||||
}
|
||||
|
||||
if (base == 8) {
|
||||
if (size_a != 0)
|
||||
if (base == 2) {
|
||||
*--p = 'b';
|
||||
*--p = '0';
|
||||
}
|
||||
else if (base == 8) {
|
||||
if (newstyle) {
|
||||
*--p = 'o';
|
||||
*--p = '0';
|
||||
}
|
||||
else
|
||||
if (size_a != 0)
|
||||
*--p = '0';
|
||||
}
|
||||
else if (base == 16) {
|
||||
*--p = 'x';
|
||||
|
@ -1888,13 +1897,13 @@ long_dealloc(PyObject *v)
|
|||
static PyObject *
|
||||
long_repr(PyObject *v)
|
||||
{
|
||||
return long_format(v, 10, 1);
|
||||
return _PyLong_Format(v, 10, 1, 0);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
long_str(PyObject *v)
|
||||
{
|
||||
return long_format(v, 10, 0);
|
||||
return _PyLong_Format(v, 10, 0, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -3268,13 +3277,13 @@ long_float(PyObject *v)
|
|||
static PyObject *
|
||||
long_oct(PyObject *v)
|
||||
{
|
||||
return long_format(v, 8, 1);
|
||||
return _PyLong_Format(v, 8, 1, 0);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
long_hex(PyObject *v)
|
||||
{
|
||||
return long_format(v, 16, 1);
|
||||
return _PyLong_Format(v, 16, 1, 0);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
Loading…
Reference in New Issue