summaryrefslogtreecommitdiffstats
path: root/Objects/intobject.c
diff options
context:
space:
mode:
authorEric Smith <eric@trueblade.com>2008-02-10 01:36:53 (GMT)
committerEric Smith <eric@trueblade.com>2008-02-10 01:36:53 (GMT)
commit5e527ebee1580f052fc53aacabe3906ffcdd4805 (patch)
treeb77c8ca7e6fcd8a2cd31c184c764a79633e2fb85 /Objects/intobject.c
parent14a1b8cc469375577ea42152bfe559fa52d6ece7 (diff)
downloadcpython-5e527ebee1580f052fc53aacabe3906ffcdd4805.zip
cpython-5e527ebee1580f052fc53aacabe3906ffcdd4805.tar.gz
cpython-5e527ebee1580f052fc53aacabe3906ffcdd4805.tar.bz2
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.
Diffstat (limited to 'Objects/intobject.c')
-rw-r--r--Objects/intobject.c90
1 files changed, 71 insertions, 19 deletions
diff --git a/Objects/intobject.c b/Objects/intobject.c
index 7c2a6fb..2fdea25 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -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."},