mirror of
https://github.com/python/cpython.git
synced 2025-07-28 21:55:21 +00:00
Refactor and clean up str.format() code (and helpers) in advance of optimizations.
This commit is contained in:
parent
30fadc1799
commit
dc13b79a38
15 changed files with 176 additions and 157 deletions
|
@ -188,6 +188,12 @@ PyAPI_FUNC(int) _PyBytes_InsertThousandsGrouping(char *buffer,
|
||||||
Py_ssize_t *count,
|
Py_ssize_t *count,
|
||||||
int append_zero_char);
|
int append_zero_char);
|
||||||
|
|
||||||
|
/* Format the object based on the format_spec, as defined in PEP 3101
|
||||||
|
(Advanced String Formatting). */
|
||||||
|
PyAPI_FUNC(PyObject *) _PyBytes_FormatAdvanced(PyObject *obj,
|
||||||
|
char *format_spec,
|
||||||
|
Py_ssize_t format_spec_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -115,6 +115,12 @@ PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le);
|
||||||
/* free list api */
|
/* free list api */
|
||||||
PyAPI_FUNC(void) PyFloat_CompactFreeList(size_t *, size_t *, size_t *);
|
PyAPI_FUNC(void) PyFloat_CompactFreeList(size_t *, size_t *, size_t *);
|
||||||
|
|
||||||
|
/* Format the object based on the format_spec, as defined in PEP 3101
|
||||||
|
(Advanced String Formatting). */
|
||||||
|
PyAPI_FUNC(PyObject *) _PyFloat_FormatAdvanced(PyObject *obj,
|
||||||
|
char *format_spec,
|
||||||
|
Py_ssize_t format_spec_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
PyObject *
|
|
||||||
string__format__(PyObject *self, PyObject *args);
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
string_long__format__(PyObject *self, PyObject *args);
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
string_int__format__(PyObject *self, PyObject *args);
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
string_float__format__(PyObject *self, PyObject *args);
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
PyObject *
|
|
||||||
unicode__format__(PyObject *self, PyObject *args);
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
unicode_long__format__(PyObject *self, PyObject *args);
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
unicode_int__format__(PyObject *self, PyObject *args);
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
unicode_float__format__(PyObject *self, PyObject *args);
|
|
||||||
|
|
|
@ -68,6 +68,12 @@ PyAPI_FUNC(void) PyInt_CompactFreeList(size_t *, size_t *, size_t *);
|
||||||
a leading "0" */
|
a leading "0" */
|
||||||
PyAPI_FUNC(PyObject*) _PyInt_Format(PyIntObject* v, int base, int newstyle);
|
PyAPI_FUNC(PyObject*) _PyInt_Format(PyIntObject* v, int base, int newstyle);
|
||||||
|
|
||||||
|
/* Format the object based on the format_spec, as defined in PEP 3101
|
||||||
|
(Advanced String Formatting). */
|
||||||
|
PyAPI_FUNC(PyObject *) _PyInt_FormatAdvanced(PyObject *obj,
|
||||||
|
char *format_spec,
|
||||||
|
Py_ssize_t format_spec_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -119,6 +119,12 @@ PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v,
|
||||||
a leading "0", instead of the prefix "0o" */
|
a leading "0", instead of the prefix "0o" */
|
||||||
PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *aa, int base, int addL, int newstyle);
|
PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *aa, int base, int addL, int newstyle);
|
||||||
|
|
||||||
|
/* Format the object based on the format_spec, as defined in PEP 3101
|
||||||
|
(Advanced String Formatting). */
|
||||||
|
PyAPI_FUNC(PyObject *) _PyLong_FormatAdvanced(PyObject *obj,
|
||||||
|
char *format_spec,
|
||||||
|
Py_ssize_t format_spec_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -553,6 +553,12 @@ PyAPI_FUNC(PyObject*) PyUnicode_FromObject(
|
||||||
PyAPI_FUNC(PyObject *) PyUnicode_FromFormatV(const char*, va_list);
|
PyAPI_FUNC(PyObject *) PyUnicode_FromFormatV(const char*, va_list);
|
||||||
PyAPI_FUNC(PyObject *) PyUnicode_FromFormat(const char*, ...);
|
PyAPI_FUNC(PyObject *) PyUnicode_FromFormat(const char*, ...);
|
||||||
|
|
||||||
|
/* Format the object based on the format_spec, as defined in PEP 3101
|
||||||
|
(Advanced String Formatting). */
|
||||||
|
PyAPI_FUNC(PyObject *) _PyUnicode_FormatAdvanced(PyObject *obj,
|
||||||
|
Py_UNICODE *format_spec,
|
||||||
|
Py_ssize_t format_spec_len);
|
||||||
|
|
||||||
/* --- wchar_t support for platforms which support it --------------------- */
|
/* --- wchar_t support for platforms which support it --------------------- */
|
||||||
|
|
||||||
#ifdef HAVE_WCHAR_H
|
#ifdef HAVE_WCHAR_H
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
#define PY_SSIZE_T_CLEAN
|
#define PY_SSIZE_T_CLEAN
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
#include "formatter_string.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
|
@ -3939,6 +3936,35 @@ PyDoc_STRVAR(format__doc__,
|
||||||
\n\
|
\n\
|
||||||
");
|
");
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
string__format__(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
PyObject *format_spec;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
PyObject *tmp = NULL;
|
||||||
|
|
||||||
|
/* If 2.x, convert format_spec to the same type as value */
|
||||||
|
/* This is to allow things like u''.format('') */
|
||||||
|
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
||||||
|
goto done;
|
||||||
|
if (!(PyBytes_Check(format_spec) || PyUnicode_Check(format_spec))) {
|
||||||
|
PyErr_Format(PyExc_TypeError, "__format__ arg must be str "
|
||||||
|
"or unicode, not %s", Py_TYPE(format_spec)->tp_name);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
tmp = PyObject_Str(format_spec);
|
||||||
|
if (tmp == NULL)
|
||||||
|
goto done;
|
||||||
|
format_spec = tmp;
|
||||||
|
|
||||||
|
result = _PyBytes_FormatAdvanced(self,
|
||||||
|
PyBytes_AS_STRING(format_spec),
|
||||||
|
PyBytes_GET_SIZE(format_spec));
|
||||||
|
done:
|
||||||
|
Py_XDECREF(tmp);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(p_format__doc__,
|
PyDoc_STRVAR(p_format__doc__,
|
||||||
"S.__format__(format_spec) -> unicode\n\
|
"S.__format__(format_spec) -> unicode\n\
|
||||||
\n\
|
\n\
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
#include <ieeefp.h>
|
#include <ieeefp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "formatter_string.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _OSF_SOURCE
|
#ifdef _OSF_SOURCE
|
||||||
/* OSF1 5.1 doesn't make this available with XOPEN_SOURCE_EXTENDED defined */
|
/* OSF1 5.1 doesn't make this available with XOPEN_SOURCE_EXTENDED defined */
|
||||||
extern int finite(double);
|
extern int finite(double);
|
||||||
|
@ -1398,26 +1395,22 @@ float__format__(PyObject *self, PyObject *args)
|
||||||
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (PyBytes_Check(format_spec))
|
if (PyBytes_Check(format_spec))
|
||||||
return string_float__format__(self, args);
|
return _PyFloat_FormatAdvanced(self,
|
||||||
|
PyBytes_AS_STRING(format_spec),
|
||||||
|
PyBytes_GET_SIZE(format_spec));
|
||||||
if (PyUnicode_Check(format_spec)) {
|
if (PyUnicode_Check(format_spec)) {
|
||||||
/* Convert format_spec to a str */
|
/* Convert format_spec to a str */
|
||||||
PyObject *result = NULL;
|
PyObject *result;
|
||||||
PyObject *newargs = NULL;
|
PyObject *str_spec = PyObject_Str(format_spec);
|
||||||
PyObject *string_format_spec = NULL;
|
|
||||||
|
|
||||||
string_format_spec = PyObject_Str(format_spec);
|
if (str_spec == NULL)
|
||||||
if (string_format_spec == NULL)
|
return NULL;
|
||||||
goto done;
|
|
||||||
|
|
||||||
newargs = Py_BuildValue("(O)", string_format_spec);
|
result = _PyFloat_FormatAdvanced(self,
|
||||||
if (newargs == NULL)
|
PyBytes_AS_STRING(str_spec),
|
||||||
goto done;
|
PyBytes_GET_SIZE(str_spec));
|
||||||
|
|
||||||
result = string_float__format__(self, newargs);
|
Py_DECREF(str_spec);
|
||||||
|
|
||||||
done:
|
|
||||||
Py_XDECREF(string_format_spec);
|
|
||||||
Py_XDECREF(newargs);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
|
PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "formatter_string.h"
|
|
||||||
|
|
||||||
static PyObject *int_int(PyIntObject *v);
|
static PyObject *int_int(PyIntObject *v);
|
||||||
|
|
||||||
|
@ -1117,26 +1116,22 @@ int__format__(PyObject *self, PyObject *args)
|
||||||
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (PyBytes_Check(format_spec))
|
if (PyBytes_Check(format_spec))
|
||||||
return string_int__format__(self, args);
|
return _PyInt_FormatAdvanced(self,
|
||||||
|
PyBytes_AS_STRING(format_spec),
|
||||||
|
PyBytes_GET_SIZE(format_spec));
|
||||||
if (PyUnicode_Check(format_spec)) {
|
if (PyUnicode_Check(format_spec)) {
|
||||||
/* Convert format_spec to a str */
|
/* Convert format_spec to a str */
|
||||||
PyObject *result = NULL;
|
PyObject *result;
|
||||||
PyObject *newargs = NULL;
|
PyObject *str_spec = PyObject_Str(format_spec);
|
||||||
PyObject *string_format_spec = NULL;
|
|
||||||
|
|
||||||
string_format_spec = PyObject_Str(format_spec);
|
if (str_spec == NULL)
|
||||||
if (string_format_spec == NULL)
|
return NULL;
|
||||||
goto done;
|
|
||||||
|
|
||||||
newargs = Py_BuildValue("(O)", string_format_spec);
|
result = _PyInt_FormatAdvanced(self,
|
||||||
if (newargs == NULL)
|
PyBytes_AS_STRING(str_spec),
|
||||||
goto done;
|
PyBytes_GET_SIZE(str_spec));
|
||||||
|
|
||||||
result = string_int__format__(self, newargs);
|
Py_DECREF(str_spec);
|
||||||
|
|
||||||
done:
|
|
||||||
Py_XDECREF(string_format_spec);
|
|
||||||
Py_XDECREF(newargs);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
|
PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "longintrepr.h"
|
#include "longintrepr.h"
|
||||||
#include "formatter_string.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
@ -3415,26 +3414,22 @@ long__format__(PyObject *self, PyObject *args)
|
||||||
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (PyBytes_Check(format_spec))
|
if (PyBytes_Check(format_spec))
|
||||||
return string_long__format__(self, args);
|
return _PyLong_FormatAdvanced(self,
|
||||||
|
PyBytes_AS_STRING(format_spec),
|
||||||
|
PyBytes_GET_SIZE(format_spec));
|
||||||
if (PyUnicode_Check(format_spec)) {
|
if (PyUnicode_Check(format_spec)) {
|
||||||
/* Convert format_spec to a str */
|
/* Convert format_spec to a str */
|
||||||
PyObject *result = NULL;
|
PyObject *result;
|
||||||
PyObject *newargs = NULL;
|
PyObject *str_spec = PyObject_Str(format_spec);
|
||||||
PyObject *string_format_spec = NULL;
|
|
||||||
|
|
||||||
string_format_spec = PyObject_Str(format_spec);
|
if (str_spec == NULL)
|
||||||
if (string_format_spec == NULL)
|
return NULL;
|
||||||
goto done;
|
|
||||||
|
|
||||||
newargs = Py_BuildValue("(O)", string_format_spec);
|
result = _PyLong_FormatAdvanced(self,
|
||||||
if (newargs == NULL)
|
PyBytes_AS_STRING(str_spec),
|
||||||
goto done;
|
PyBytes_GET_SIZE(str_spec));
|
||||||
|
|
||||||
result = string_long__format__(self, newargs);
|
Py_DECREF(str_spec);
|
||||||
|
|
||||||
done:
|
|
||||||
Py_XDECREF(string_format_spec);
|
|
||||||
Py_XDECREF(newargs);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
|
PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
|
||||||
|
|
|
@ -102,12 +102,13 @@ typedef struct {
|
||||||
if failure, sets the exception
|
if failure, sets the exception
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
parse_internal_render_format_spec(PyObject *format_spec,
|
parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
|
||||||
|
Py_ssize_t format_spec_len,
|
||||||
InternalFormatSpec *format,
|
InternalFormatSpec *format,
|
||||||
char default_type)
|
char default_type)
|
||||||
{
|
{
|
||||||
STRINGLIB_CHAR *ptr = STRINGLIB_STR(format_spec);
|
STRINGLIB_CHAR *ptr = format_spec;
|
||||||
STRINGLIB_CHAR *end = ptr + STRINGLIB_LEN(format_spec);
|
STRINGLIB_CHAR *end = format_spec + format_spec_len;
|
||||||
|
|
||||||
/* end-ptr is used throughout this code to specify the length of
|
/* end-ptr is used throughout this code to specify the length of
|
||||||
the input string */
|
the input string */
|
||||||
|
@ -756,56 +757,31 @@ done:
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/*********** built in formatters ****************************************/
|
/*********** built in formatters ****************************************/
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
#ifdef FORMAT_STRING
|
|
||||||
PyObject *
|
PyObject *
|
||||||
FORMAT_STRING(PyObject* value, PyObject* args)
|
FORMAT_STRING(PyObject *obj,
|
||||||
|
STRINGLIB_CHAR *format_spec,
|
||||||
|
Py_ssize_t format_spec_len)
|
||||||
{
|
{
|
||||||
PyObject *format_spec;
|
|
||||||
PyObject *result = NULL;
|
|
||||||
#if PY_VERSION_HEX < 0x03000000
|
|
||||||
PyObject *tmp = NULL;
|
|
||||||
#endif
|
|
||||||
InternalFormatSpec format;
|
InternalFormatSpec format;
|
||||||
|
PyObject *result = NULL;
|
||||||
/* If 2.x, we accept either str or unicode, and try to convert it
|
|
||||||
to the right type. In 3.x, we insist on only unicode */
|
|
||||||
#if PY_VERSION_HEX >= 0x03000000
|
|
||||||
if (!PyArg_ParseTuple(args, STRINGLIB_PARSE_CODE ":__format__",
|
|
||||||
&format_spec))
|
|
||||||
goto done;
|
|
||||||
#else
|
|
||||||
/* If 2.x, convert format_spec to the same type as value */
|
|
||||||
/* This is to allow things like u''.format('') */
|
|
||||||
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
|
||||||
goto done;
|
|
||||||
if (!(PyBytes_Check(format_spec) || PyUnicode_Check(format_spec))) {
|
|
||||||
PyErr_Format(PyExc_TypeError, "__format__ arg must be str "
|
|
||||||
"or unicode, not %s", Py_TYPE(format_spec)->tp_name);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
tmp = STRINGLIB_TOSTR(format_spec);
|
|
||||||
if (tmp == NULL)
|
|
||||||
goto done;
|
|
||||||
format_spec = tmp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* check for the special case of zero length format spec, make
|
/* check for the special case of zero length format spec, make
|
||||||
it equivalent to str(value) */
|
it equivalent to str(obj) */
|
||||||
if (STRINGLIB_LEN(format_spec) == 0) {
|
if (format_spec_len == 0) {
|
||||||
result = STRINGLIB_TOSTR(value);
|
result = STRINGLIB_TOSTR(obj);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* parse the format_spec */
|
/* parse the format_spec */
|
||||||
if (!parse_internal_render_format_spec(format_spec, &format, 's'))
|
if (!parse_internal_render_format_spec(format_spec, format_spec_len,
|
||||||
|
&format, 's'))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* type conversion? */
|
/* type conversion? */
|
||||||
switch (format.type) {
|
switch (format.type) {
|
||||||
case 's':
|
case 's':
|
||||||
/* no type conversion needed, already a string. do the formatting */
|
/* no type conversion needed, already a string. do the formatting */
|
||||||
result = format_string_internal(value, &format);
|
result = format_string_internal(obj, &format);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* unknown */
|
/* unknown */
|
||||||
|
@ -826,35 +802,31 @@ FORMAT_STRING(PyObject* value, PyObject* args)
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
#if PY_VERSION_HEX < 0x03000000
|
|
||||||
Py_XDECREF(tmp);
|
|
||||||
#endif
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif /* FORMAT_STRING */
|
|
||||||
|
|
||||||
#if defined FORMAT_LONG || defined FORMAT_INT
|
#if defined FORMAT_LONG || defined FORMAT_INT
|
||||||
static PyObject*
|
static PyObject*
|
||||||
format_int_or_long(PyObject* value, PyObject* args, IntOrLongToString tostring)
|
format_int_or_long(PyObject* obj,
|
||||||
|
STRINGLIB_CHAR *format_spec,
|
||||||
|
Py_ssize_t format_spec_len,
|
||||||
|
IntOrLongToString tostring)
|
||||||
{
|
{
|
||||||
PyObject *format_spec;
|
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
PyObject *tmp = NULL;
|
PyObject *tmp = NULL;
|
||||||
InternalFormatSpec format;
|
InternalFormatSpec format;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, STRINGLIB_PARSE_CODE ":__format__",
|
|
||||||
&format_spec))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* check for the special case of zero length format spec, make
|
/* check for the special case of zero length format spec, make
|
||||||
it equivalent to str(value) */
|
it equivalent to str(obj) */
|
||||||
if (STRINGLIB_LEN(format_spec) == 0) {
|
if (format_spec_len == 0) {
|
||||||
result = STRINGLIB_TOSTR(value);
|
result = STRINGLIB_TOSTR(obj);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse the format_spec */
|
/* parse the format_spec */
|
||||||
if (!parse_internal_render_format_spec(format_spec, &format, 'd'))
|
if (!parse_internal_render_format_spec(format_spec,
|
||||||
|
format_spec_len,
|
||||||
|
&format, 'd'))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* type conversion? */
|
/* type conversion? */
|
||||||
|
@ -868,7 +840,7 @@ format_int_or_long(PyObject* value, PyObject* args, IntOrLongToString tostring)
|
||||||
case 'n':
|
case 'n':
|
||||||
/* no type conversion needed, already an int (or long). do
|
/* no type conversion needed, already an int (or long). do
|
||||||
the formatting */
|
the formatting */
|
||||||
result = format_int_or_long_internal(value, &format, tostring);
|
result = format_int_or_long_internal(obj, &format, tostring);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
|
@ -879,10 +851,10 @@ format_int_or_long(PyObject* value, PyObject* args, IntOrLongToString tostring)
|
||||||
case 'G':
|
case 'G':
|
||||||
case '%':
|
case '%':
|
||||||
/* convert to float */
|
/* convert to float */
|
||||||
tmp = PyNumber_Float(value);
|
tmp = PyNumber_Float(obj);
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
result = format_float_internal(value, &format);
|
result = format_float_internal(obj, &format);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -917,9 +889,12 @@ long_format(PyObject* value, int base)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
FORMAT_LONG(PyObject* value, PyObject* args)
|
FORMAT_LONG(PyObject *obj,
|
||||||
|
STRINGLIB_CHAR *format_spec,
|
||||||
|
Py_ssize_t format_spec_len)
|
||||||
{
|
{
|
||||||
return format_int_or_long(value, args, long_format);
|
return format_int_or_long(obj, format_spec, format_spec_len,
|
||||||
|
long_format);
|
||||||
}
|
}
|
||||||
#endif /* FORMAT_LONG */
|
#endif /* FORMAT_LONG */
|
||||||
|
|
||||||
|
@ -935,32 +910,35 @@ int_format(PyObject* value, int base)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
FORMAT_INT(PyObject* value, PyObject* args)
|
FORMAT_INT(PyObject *obj,
|
||||||
|
STRINGLIB_CHAR *format_spec,
|
||||||
|
Py_ssize_t format_spec_len)
|
||||||
{
|
{
|
||||||
return format_int_or_long(value, args, int_format);
|
return format_int_or_long(obj, format_spec, format_spec_len,
|
||||||
|
int_format);
|
||||||
}
|
}
|
||||||
#endif /* FORMAT_INT */
|
#endif /* FORMAT_INT */
|
||||||
|
|
||||||
#ifdef FORMAT_FLOAT
|
#ifdef FORMAT_FLOAT
|
||||||
PyObject *
|
PyObject *
|
||||||
FORMAT_FLOAT(PyObject *value, PyObject *args)
|
FORMAT_FLOAT(PyObject *obj,
|
||||||
|
STRINGLIB_CHAR *format_spec,
|
||||||
|
Py_ssize_t format_spec_len)
|
||||||
{
|
{
|
||||||
PyObject *format_spec;
|
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
InternalFormatSpec format;
|
InternalFormatSpec format;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, STRINGLIB_PARSE_CODE ":__format__", &format_spec))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* check for the special case of zero length format spec, make
|
/* check for the special case of zero length format spec, make
|
||||||
it equivalent to str(value) */
|
it equivalent to str(obj) */
|
||||||
if (STRINGLIB_LEN(format_spec) == 0) {
|
if (format_spec_len == 0) {
|
||||||
result = STRINGLIB_TOSTR(value);
|
result = STRINGLIB_TOSTR(obj);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse the format_spec */
|
/* parse the format_spec */
|
||||||
if (!parse_internal_render_format_spec(format_spec, &format, '\0'))
|
if (!parse_internal_render_format_spec(format_spec,
|
||||||
|
format_spec_len,
|
||||||
|
&format, '\0'))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* type conversion? */
|
/* type conversion? */
|
||||||
|
@ -979,7 +957,7 @@ FORMAT_FLOAT(PyObject *value, PyObject *args)
|
||||||
case 'n':
|
case 'n':
|
||||||
case '%':
|
case '%':
|
||||||
/* no conversion, already a float. do the formatting */
|
/* no conversion, already a float. do the formatting */
|
||||||
result = format_float_internal(value, &format);
|
result = format_float_internal(obj, &format);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -42,8 +42,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#define PY_SSIZE_T_CLEAN
|
#define PY_SSIZE_T_CLEAN
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
#include "formatter_unicode.h"
|
|
||||||
|
|
||||||
#include "unicodeobject.h"
|
#include "unicodeobject.h"
|
||||||
#include "ucnhash.h"
|
#include "ucnhash.h"
|
||||||
|
|
||||||
|
@ -7863,6 +7861,35 @@ PyDoc_STRVAR(format__doc__,
|
||||||
\n\
|
\n\
|
||||||
");
|
");
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode__format__(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *format_spec;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
PyObject *tmp = NULL;
|
||||||
|
|
||||||
|
/* If 2.x, convert format_spec to the same type as value */
|
||||||
|
/* This is to allow things like u''.format('') */
|
||||||
|
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
|
||||||
|
goto done;
|
||||||
|
if (!(PyBytes_Check(format_spec) || PyUnicode_Check(format_spec))) {
|
||||||
|
PyErr_Format(PyExc_TypeError, "__format__ arg must be str "
|
||||||
|
"or unicode, not %s", Py_TYPE(format_spec)->tp_name);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
tmp = PyObject_Unicode(format_spec);
|
||||||
|
if (tmp == NULL)
|
||||||
|
goto done;
|
||||||
|
format_spec = tmp;
|
||||||
|
|
||||||
|
result = _PyUnicode_FormatAdvanced(self,
|
||||||
|
PyUnicode_AS_UNICODE(format_spec),
|
||||||
|
PyUnicode_GET_SIZE(format_spec));
|
||||||
|
done:
|
||||||
|
Py_XDECREF(tmp);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(p_format__doc__,
|
PyDoc_STRVAR(p_format__doc__,
|
||||||
"S.__format__(format_spec) -> unicode\n\
|
"S.__format__(format_spec) -> unicode\n\
|
||||||
\n\
|
\n\
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
of int.__float__, etc., that take and return string objects */
|
of int.__float__, etc., that take and return string objects */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "formatter_string.h"
|
|
||||||
|
|
||||||
#include "../Objects/stringlib/stringdefs.h"
|
#include "../Objects/stringlib/stringdefs.h"
|
||||||
|
|
||||||
#define FORMAT_STRING string__format__
|
#define FORMAT_STRING _PyBytes_FormatAdvanced
|
||||||
#define FORMAT_LONG string_long__format__
|
#define FORMAT_LONG _PyLong_FormatAdvanced
|
||||||
#define FORMAT_INT string_int__format__
|
#define FORMAT_INT _PyInt_FormatAdvanced
|
||||||
#define FORMAT_FLOAT string_float__format__
|
#define FORMAT_FLOAT _PyFloat_FormatAdvanced
|
||||||
|
|
||||||
#include "../Objects/stringlib/formatter.h"
|
#include "../Objects/stringlib/formatter.h"
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
built-in formatter for unicode. That is, unicode.__format__(). */
|
built-in formatter for unicode. That is, unicode.__format__(). */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "formatter_unicode.h"
|
|
||||||
|
|
||||||
#include "../Objects/stringlib/unicodedefs.h"
|
#include "../Objects/stringlib/unicodedefs.h"
|
||||||
|
|
||||||
#define FORMAT_STRING unicode__format__
|
#define FORMAT_STRING _PyUnicode_FormatAdvanced
|
||||||
|
|
||||||
/* don't define FORMAT_LONG and FORMAT_FLOAT, since we can live
|
/* don't define FORMAT_LONG and FORMAT_FLOAT, since we can live
|
||||||
with only the string versions of those. The builtin format()
|
with only the string versions of those. The builtin format()
|
||||||
will convert them to unicode. */
|
will convert them to unicode. */
|
||||||
|
|
||||||
#include "../Objects/stringlib/formatter.h"
|
#include "../Objects/stringlib/formatter.h"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue