mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +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 @@ format_float_internal(PyObject *value, | ||||||
| /************************************************************************/ | /************************************************************************/ | ||||||
| /*********** 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
	
	 Eric Smith
						Eric Smith