Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4a7d76d

Browse files
committed
Refactor and clean up str.format() code (and helpers) in advance of optimizations.
1 parent eb2c964 commit 4a7d76d

10 files changed

Lines changed: 98 additions & 99 deletions

File tree

Include/floatobject.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le);
105105
/* free list api */
106106
PyAPI_FUNC(void) PyFloat_CompactFreeList(size_t *, size_t *, size_t *);
107107

108+
/* Format the object based on the format_spec, as defined in PEP 3101
109+
(Advanced String Formatting). */
110+
PyAPI_FUNC(PyObject *) _PyFloat_FormatAdvanced(PyObject *obj,
111+
Py_UNICODE *format_spec,
112+
Py_ssize_t format_spec_len);
113+
108114
#ifdef __cplusplus
109115
}
110116
#endif

Include/formatter_unicode.h

Lines changed: 0 additions & 9 deletions
This file was deleted.

Include/longobject.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v,
127127
appending a base prefix of 0[box] if base is 2, 8 or 16. */
128128
PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *aa, int base);
129129

130+
/* Format the object based on the format_spec, as defined in PEP 3101
131+
(Advanced String Formatting). */
132+
PyAPI_FUNC(PyObject *) _PyLong_FormatAdvanced(PyObject *obj,
133+
Py_UNICODE *format_spec,
134+
Py_ssize_t format_spec_len);
135+
130136
/* These aren't really part of the long object, but they're handy. The
131137
functions are in Python/mystrtoul.c.
132138
*/

Include/unicodeobject.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,12 @@ PyAPI_FUNC(PyObject*) PyUnicode_FromObject(
571571
PyAPI_FUNC(PyObject *) PyUnicode_FromFormatV(const char*, va_list);
572572
PyAPI_FUNC(PyObject *) PyUnicode_FromFormat(const char*, ...);
573573

574+
/* Format the object based on the format_spec, as defined in PEP 3101
575+
(Advanced String Formatting). */
576+
PyAPI_FUNC(PyObject *) _PyUnicode_FormatAdvanced(PyObject *obj,
577+
Py_UNICODE *format_spec,
578+
Py_ssize_t format_spec_len);
579+
574580
PyAPI_FUNC(void) PyUnicode_InternInPlace(PyObject **);
575581
PyAPI_FUNC(void) PyUnicode_InternImmortal(PyObject **);
576582
PyAPI_FUNC(PyObject *) PyUnicode_InternFromString(const char *);

Makefile.pre.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,6 @@ PYTHON_HEADERS= \
596596
Include/eval.h \
597597
Include/fileobject.h \
598598
Include/floatobject.h \
599-
Include/formatter_unicode.h \
600599
Include/frameobject.h \
601600
Include/funcobject.h \
602601
Include/genobject.h \

Objects/floatobject.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
#include "Python.h"
88
#include "structseq.h"
99

10-
#include "formatter_unicode.h"
11-
1210
#include <ctype.h>
1311
#include <float.h>
1412

@@ -1303,10 +1301,13 @@ float_getzero(PyObject *v, void *closure)
13031301
static PyObject *
13041302
float__format__(PyObject *self, PyObject *args)
13051303
{
1306-
/* when back porting this to 2.6, check type of the format_spec
1307-
and call either unicode_long__format__ or
1308-
string_long__format__ */
1309-
return unicode_float__format__(self, args);
1304+
PyObject *format_spec;
1305+
1306+
if (!PyArg_ParseTuple(args, "U:__format__", &format_spec))
1307+
return NULL;
1308+
return _PyFloat_FormatAdvanced(self,
1309+
PyUnicode_AS_UNICODE(format_spec),
1310+
PyUnicode_GET_SIZE(format_spec));
13101311
}
13111312

13121313
PyDoc_STRVAR(float__format__doc,

Objects/longobject.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
#include "Python.h"
66
#include "longintrepr.h"
77

8-
#include "formatter_unicode.h"
9-
108
#include <ctype.h>
119

1210
#ifndef NSMALLPOSINTS
@@ -3590,10 +3588,13 @@ long_getN(PyLongObject *v, void *context) {
35903588
static PyObject *
35913589
long__format__(PyObject *self, PyObject *args)
35923590
{
3593-
/* when back porting this to 2.6, check type of the format_spec
3594-
and call either unicode_long__format__ or
3595-
string_long__format__ */
3596-
return unicode_long__format__(self, args);
3591+
PyObject *format_spec;
3592+
3593+
if (!PyArg_ParseTuple(args, "U:__format__", &format_spec))
3594+
return NULL;
3595+
return _PyLong_FormatAdvanced(self,
3596+
PyUnicode_AS_UNICODE(format_spec),
3597+
PyUnicode_GET_SIZE(format_spec));
35973598
}
35983599

35993600

Objects/stringlib/formatter.h

Lines changed: 47 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,13 @@ typedef struct {
102102
if failure, sets the exception
103103
*/
104104
static int
105-
parse_internal_render_format_spec(PyObject *format_spec,
105+
parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
106+
Py_ssize_t format_spec_len,
106107
InternalFormatSpec *format,
107108
char default_type)
108109
{
109-
STRINGLIB_CHAR *ptr = STRINGLIB_STR(format_spec);
110-
STRINGLIB_CHAR *end = ptr + STRINGLIB_LEN(format_spec);
110+
STRINGLIB_CHAR *ptr = format_spec;
111+
STRINGLIB_CHAR *end = format_spec + format_spec_len;
111112

112113
/* end-ptr is used throughout this code to specify the length of
113114
the input string */
@@ -756,56 +757,31 @@ format_float_internal(PyObject *value,
756757
/************************************************************************/
757758
/*********** built in formatters ****************************************/
758759
/************************************************************************/
759-
#ifdef FORMAT_STRING
760760
PyObject *
761-
FORMAT_STRING(PyObject* value, PyObject* args)
761+
FORMAT_STRING(PyObject *obj,
762+
STRINGLIB_CHAR *format_spec,
763+
Py_ssize_t format_spec_len)
762764
{
763-
PyObject *format_spec;
764-
PyObject *result = NULL;
765-
#if PY_VERSION_HEX < 0x03000000
766-
PyObject *tmp = NULL;
767-
#endif
768765
InternalFormatSpec format;
769-
770-
/* If 2.x, we accept either str or unicode, and try to convert it
771-
to the right type. In 3.x, we insist on only unicode */
772-
#if PY_VERSION_HEX >= 0x03000000
773-
if (!PyArg_ParseTuple(args, STRINGLIB_PARSE_CODE ":__format__",
774-
&format_spec))
775-
goto done;
776-
#else
777-
/* If 2.x, convert format_spec to the same type as value */
778-
/* This is to allow things like u''.format('') */
779-
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
780-
goto done;
781-
if (!(PyBytes_Check(format_spec) || PyUnicode_Check(format_spec))) {
782-
PyErr_Format(PyExc_TypeError, "__format__ arg must be str "
783-
"or unicode, not %s", Py_TYPE(format_spec)->tp_name);
784-
goto done;
785-
}
786-
tmp = STRINGLIB_TOSTR(format_spec);
787-
if (tmp == NULL)
788-
goto done;
789-
format_spec = tmp;
790-
#endif
766+
PyObject *result = NULL;
791767

792768
/* check for the special case of zero length format spec, make
793-
it equivalent to str(value) */
794-
if (STRINGLIB_LEN(format_spec) == 0) {
795-
result = STRINGLIB_TOSTR(value);
769+
it equivalent to str(obj) */
770+
if (format_spec_len == 0) {
771+
result = STRINGLIB_TOSTR(obj);
796772
goto done;
797773
}
798774

799-
800775
/* parse the format_spec */
801-
if (!parse_internal_render_format_spec(format_spec, &format, 's'))
776+
if (!parse_internal_render_format_spec(format_spec, format_spec_len,
777+
&format, 's'))
802778
goto done;
803779

804780
/* type conversion? */
805781
switch (format.type) {
806782
case 's':
807783
/* no type conversion needed, already a string. do the formatting */
808-
result = format_string_internal(value, &format);
784+
result = format_string_internal(obj, &format);
809785
break;
810786
default:
811787
/* unknown */
@@ -826,35 +802,31 @@ FORMAT_STRING(PyObject* value, PyObject* args)
826802
}
827803

828804
done:
829-
#if PY_VERSION_HEX < 0x03000000
830-
Py_XDECREF(tmp);
831-
#endif
832805
return result;
833806
}
834-
#endif /* FORMAT_STRING */
835807

836808
#if defined FORMAT_LONG || defined FORMAT_INT
837809
static PyObject*
838-
format_int_or_long(PyObject* value, PyObject* args, IntOrLongToString tostring)
810+
format_int_or_long(PyObject* obj,
811+
STRINGLIB_CHAR *format_spec,
812+
Py_ssize_t format_spec_len,
813+
IntOrLongToString tostring)
839814
{
840-
PyObject *format_spec;
841815
PyObject *result = NULL;
842816
PyObject *tmp = NULL;
843817
InternalFormatSpec format;
844818

845-
if (!PyArg_ParseTuple(args, STRINGLIB_PARSE_CODE ":__format__",
846-
&format_spec))
847-
goto done;
848-
849819
/* check for the special case of zero length format spec, make
850-
it equivalent to str(value) */
851-
if (STRINGLIB_LEN(format_spec) == 0) {
852-
result = STRINGLIB_TOSTR(value);
820+
it equivalent to str(obj) */
821+
if (format_spec_len == 0) {
822+
result = STRINGLIB_TOSTR(obj);
853823
goto done;
854824
}
855825

856826
/* parse the format_spec */
857-
if (!parse_internal_render_format_spec(format_spec, &format, 'd'))
827+
if (!parse_internal_render_format_spec(format_spec,
828+
format_spec_len,
829+
&format, 'd'))
858830
goto done;
859831

860832
/* type conversion? */
@@ -868,7 +840,7 @@ format_int_or_long(PyObject* value, PyObject* args, IntOrLongToString tostring)
868840
case 'n':
869841
/* no type conversion needed, already an int (or long). do
870842
the formatting */
871-
result = format_int_or_long_internal(value, &format, tostring);
843+
result = format_int_or_long_internal(obj, &format, tostring);
872844
break;
873845

874846
case 'e':
@@ -879,10 +851,10 @@ format_int_or_long(PyObject* value, PyObject* args, IntOrLongToString tostring)
879851
case 'G':
880852
case '%':
881853
/* convert to float */
882-
tmp = PyNumber_Float(value);
854+
tmp = PyNumber_Float(obj);
883855
if (tmp == NULL)
884856
goto done;
885-
result = format_float_internal(value, &format);
857+
result = format_float_internal(obj, &format);
886858
break;
887859

888860
default:
@@ -917,9 +889,12 @@ long_format(PyObject* value, int base)
917889
#endif
918890

919891
PyObject *
920-
FORMAT_LONG(PyObject* value, PyObject* args)
892+
FORMAT_LONG(PyObject *obj,
893+
STRINGLIB_CHAR *format_spec,
894+
Py_ssize_t format_spec_len)
921895
{
922-
return format_int_or_long(value, args, long_format);
896+
return format_int_or_long(obj, format_spec, format_spec_len,
897+
long_format);
923898
}
924899
#endif /* FORMAT_LONG */
925900

@@ -935,32 +910,35 @@ int_format(PyObject* value, int base)
935910
}
936911

937912
PyObject *
938-
FORMAT_INT(PyObject* value, PyObject* args)
913+
FORMAT_INT(PyObject *obj,
914+
STRINGLIB_CHAR *format_spec,
915+
Py_ssize_t format_spec_len)
939916
{
940-
return format_int_or_long(value, args, int_format);
917+
return format_int_or_long(obj, format_spec, format_spec_len,
918+
int_format);
941919
}
942920
#endif /* FORMAT_INT */
943921

944922
#ifdef FORMAT_FLOAT
945923
PyObject *
946-
FORMAT_FLOAT(PyObject *value, PyObject *args)
924+
FORMAT_FLOAT(PyObject *obj,
925+
STRINGLIB_CHAR *format_spec,
926+
Py_ssize_t format_spec_len)
947927
{
948-
PyObject *format_spec;
949928
PyObject *result = NULL;
950929
InternalFormatSpec format;
951930

952-
if (!PyArg_ParseTuple(args, STRINGLIB_PARSE_CODE ":__format__", &format_spec))
953-
goto done;
954-
955931
/* check for the special case of zero length format spec, make
956-
it equivalent to str(value) */
957-
if (STRINGLIB_LEN(format_spec) == 0) {
958-
result = STRINGLIB_TOSTR(value);
932+
it equivalent to str(obj) */
933+
if (format_spec_len == 0) {
934+
result = STRINGLIB_TOSTR(obj);
959935
goto done;
960936
}
961937

962938
/* parse the format_spec */
963-
if (!parse_internal_render_format_spec(format_spec, &format, '\0'))
939+
if (!parse_internal_render_format_spec(format_spec,
940+
format_spec_len,
941+
&format, '\0'))
964942
goto done;
965943

966944
/* type conversion? */
@@ -979,7 +957,7 @@ FORMAT_FLOAT(PyObject *value, PyObject *args)
979957
case 'n':
980958
case '%':
981959
/* no conversion, already a float. do the formatting */
982-
result = format_float_internal(value, &format);
960+
result = format_float_internal(obj, &format);
983961
break;
984962

985963
default:

Objects/unicodeobject.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4646
#include "unicodeobject.h"
4747
#include "ucnhash.h"
4848

49-
#include "formatter_unicode.h"
50-
5149
#ifdef MS_WINDOWS
5250
#include <windows.h>
5351
#endif
@@ -8202,6 +8200,19 @@ PyDoc_STRVAR(format__doc__,
82028200
\n\
82038201
");
82048202

8203+
static PyObject *
8204+
unicode__format__(PyObject* self, PyObject* args)
8205+
{
8206+
PyObject *format_spec;
8207+
8208+
if (!PyArg_ParseTuple(args, "U:__format__", &format_spec))
8209+
return NULL;
8210+
8211+
return _PyUnicode_FormatAdvanced(self,
8212+
PyUnicode_AS_UNICODE(format_spec),
8213+
PyUnicode_GET_SIZE(format_spec));
8214+
}
8215+
82058216
PyDoc_STRVAR(p_format__doc__,
82068217
"S.__format__(format_spec) -> str\n\
82078218
\n\
@@ -8259,7 +8270,7 @@ static PyMethodDef unicode_methods[] = {
82598270
{"isidentifier", (PyCFunction) unicode_isidentifier, METH_NOARGS, isidentifier__doc__},
82608271
{"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__},
82618272
{"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__},
8262-
{"__format__", (PyCFunction) unicode_unicode__format__, METH_VARARGS, p_format__doc__},
8273+
{"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__},
82638274
{"_formatter_field_name_split", (PyCFunction) formatter_field_name_split, METH_NOARGS},
82648275
{"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS},
82658276
{"maketrans", (PyCFunction) unicode_maketrans,

Python/formatter_unicode.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
of int.__float__, etc., that take and return unicode objects */
44

55
#include "Python.h"
6-
#include "formatter_unicode.h"
7-
86
#include "../Objects/stringlib/unicodedefs.h"
97

10-
#define FORMAT_STRING unicode_unicode__format__
11-
#define FORMAT_LONG unicode_long__format__
12-
#define FORMAT_FLOAT unicode_float__format__
8+
9+
#define FORMAT_STRING _PyUnicode_FormatAdvanced
10+
#define FORMAT_LONG _PyLong_FormatAdvanced
11+
#define FORMAT_FLOAT _PyFloat_FormatAdvanced
12+
1313
#include "../Objects/stringlib/formatter.h"

0 commit comments

Comments
 (0)