# Test PyUnicode_FromFormat()
def test_from_format(self):
support.import_module('ctypes')
- from ctypes import (pythonapi, py_object,
+ from ctypes import (
+ pythonapi, py_object, sizeof,
c_int, c_long, c_longlong, c_ssize_t,
- c_uint, c_ulong, c_ulonglong, c_size_t)
+ c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p)
name = "PyUnicode_FromFormat"
_PyUnicode_FromFormat = getattr(pythonapi, name)
_PyUnicode_FromFormat.restype = py_object
self.assertEqual(PyUnicode_FromFormat(b'%llu', c_ulonglong(123)), '123')
self.assertEqual(PyUnicode_FromFormat(b'%zu', c_size_t(123)), '123')
+ # test long output
+ min_longlong = -(2 ** (8 * sizeof(c_longlong) - 1))
+ max_longlong = -min_longlong - 1
+ self.assertEqual(PyUnicode_FromFormat(b'%lld', c_longlong(min_longlong)), str(min_longlong))
+ self.assertEqual(PyUnicode_FromFormat(b'%lld', c_longlong(max_longlong)), str(max_longlong))
+ max_ulonglong = 2 ** (8 * sizeof(c_ulonglong)) - 1
+ self.assertEqual(PyUnicode_FromFormat(b'%llu', c_ulonglong(max_ulonglong)), str(max_ulonglong))
+ PyUnicode_FromFormat(b'%p', c_void_p(-1))
+
# test padding (width and/or precision)
self.assertEqual(PyUnicode_FromFormat(b'%010i', c_int(123)), '123'.rjust(10, '0'))
self.assertEqual(PyUnicode_FromFormat(b'%100i', c_int(123)), '123'.rjust(100))
*fmt = '\0';
}
-/* maximum number of characters required for output of %ld. 21 characters
- allows for 64-bit integers (in decimal) and an optional sign. */
-#define MAX_LONG_CHARS 21
-/* maximum number of characters required for output of %lld.
+/* maximum number of characters required for output of %lld or %p.
We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
plus 1 for the sign. 53/22 is an upper bound for log10(256). */
#define MAX_LONG_LONG_CHARS (2 + (SIZEOF_LONG_LONG*53-1) / 22)
{
/* used by sprintf */
char fmt[10]; /* should be enough for "%0lld\0" */
- char small_buffer[MAX_LONG_CHARS];
- char *buffer;
- int err;
-
- if (sizeof(small_buffer) - 1 < precision) {
- buffer = PyMem_Malloc(precision + 1);
- if (buffer == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- }
- else
- buffer = small_buffer;
+ char buffer[MAX_LONG_LONG_CHARS];
if (*f == 'u') {
makefmt(fmt, longflag, longlongflag, size_tflag, *f);
}
assert(len >= 0);
- err = 0;
if (precision < len)
precision = len;
if (width > precision) {
Py_UCS4 fillchar;
fill = width - precision;
fillchar = zeropad?'0':' ';
- if (_PyUnicodeWriter_Prepare(writer, fill, fillchar) != -1) {
- if (PyUnicode_Fill(writer->buffer, writer->pos, fill, fillchar) == -1)
- err = 1;
- }
- else
- err = 1;
- if (!err)
- writer->pos += fill;
+ if (_PyUnicodeWriter_Prepare(writer, fill, fillchar) == -1)
+ return NULL;
+ if (PyUnicode_Fill(writer->buffer, writer->pos, fill, fillchar) == -1)
+ return NULL;
+ writer->pos += fill;
}
- if (!err && precision > len) {
+ if (precision > len) {
fill = precision - len;
- if (_PyUnicodeWriter_Prepare(writer, fill, '0') != -1) {
- if (PyUnicode_Fill(writer->buffer, writer->pos, fill, '0') == -1)
- err = 1;
- }
- else
- err = 1;
- if (!err)
- writer->pos += fill;
- }
- if (!err) {
- if (_PyUnicodeWriter_WriteCstr(writer, buffer, len) == -1)
- err = 1;
- }
-
- if (buffer != small_buffer) {
- PyMem_Free(buffer);
- buffer = small_buffer;
+ if (_PyUnicodeWriter_Prepare(writer, fill, '0') == -1)
+ return NULL;
+ if (PyUnicode_Fill(writer->buffer, writer->pos, fill, '0') == -1)
+ return NULL;
+ writer->pos += fill;
}
- if (err)
+ if (_PyUnicodeWriter_WriteCstr(writer, buffer, len) == -1)
return NULL;
-
break;
}