mirror of
https://github.com/python/cpython.git
synced 2025-11-26 21:33:10 +00:00
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
5 changed files with 126 additions and 33 deletions
|
|
@ -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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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) {
|
||||||
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 *);
|
||||||
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)
|
||||||
/* 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)
|
||||||
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,7 +1309,16 @@ long_format(PyObject *aa, int base, int addL)
|
||||||
Py_DECREF(scratch);
|
Py_DECREF(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base == 8) {
|
if (base == 2) {
|
||||||
|
*--p = 'b';
|
||||||
|
*--p = '0';
|
||||||
|
}
|
||||||
|
else if (base == 8) {
|
||||||
|
if (newstyle) {
|
||||||
|
*--p = 'o';
|
||||||
|
*--p = '0';
|
||||||
|
}
|
||||||
|
else
|
||||||
if (size_a != 0)
|
if (size_a != 0)
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
||||||
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 *
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue