[Python-checkins] r63814 - in python/trunk: Include/bytesobject.h Include/floatobject.h Include/formatter_string.h Include/formatter_unicode.h Include/intobject.h Include/longobject.h Include/unicodeobject.h Objects/bytesobject.c Objects/floatobject.c Objects/intobject.c Objects/longobject.c Objects/stringlib/formatter.h Objects/unicodeobject.c Python/formatter_string.c Python/formatter_unicode.c

eric.smith python-checkins at python.org
Fri May 30 20:10:05 CEST 2008


Author: eric.smith
Date: Fri May 30 20:10:04 2008
New Revision: 63814

Log:
Refactor and clean up str.format() code (and helpers) in advance of optimizations.

Removed:
   python/trunk/Include/formatter_string.h
   python/trunk/Include/formatter_unicode.h
Modified:
   python/trunk/Include/bytesobject.h
   python/trunk/Include/floatobject.h
   python/trunk/Include/intobject.h
   python/trunk/Include/longobject.h
   python/trunk/Include/unicodeobject.h
   python/trunk/Objects/bytesobject.c
   python/trunk/Objects/floatobject.c
   python/trunk/Objects/intobject.c
   python/trunk/Objects/longobject.c
   python/trunk/Objects/stringlib/formatter.h
   python/trunk/Objects/unicodeobject.c
   python/trunk/Python/formatter_string.c
   python/trunk/Python/formatter_unicode.c

Modified: python/trunk/Include/bytesobject.h
==============================================================================
--- python/trunk/Include/bytesobject.h	(original)
+++ python/trunk/Include/bytesobject.h	Fri May 30 20:10:04 2008
@@ -188,6 +188,12 @@
 						  Py_ssize_t *count,
 						  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
 }
 #endif

Modified: python/trunk/Include/floatobject.h
==============================================================================
--- python/trunk/Include/floatobject.h	(original)
+++ python/trunk/Include/floatobject.h	Fri May 30 20:10:04 2008
@@ -115,6 +115,12 @@
 /* free list api */
 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
 }
 #endif

Deleted: python/trunk/Include/formatter_string.h
==============================================================================
--- python/trunk/Include/formatter_string.h	Fri May 30 20:10:04 2008
+++ (empty file)
@@ -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);
-

Deleted: python/trunk/Include/formatter_unicode.h
==============================================================================
--- python/trunk/Include/formatter_unicode.h	Fri May 30 20:10:04 2008
+++ (empty file)
@@ -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);
-

Modified: python/trunk/Include/intobject.h
==============================================================================
--- python/trunk/Include/intobject.h	(original)
+++ python/trunk/Include/intobject.h	Fri May 30 20:10:04 2008
@@ -68,6 +68,12 @@
    a leading "0" */
 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
 }
 #endif

Modified: python/trunk/Include/longobject.h
==============================================================================
--- python/trunk/Include/longobject.h	(original)
+++ python/trunk/Include/longobject.h	Fri May 30 20:10:04 2008
@@ -119,6 +119,12 @@
    a leading "0", instead of the prefix "0o" */
 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
 }
 #endif

Modified: python/trunk/Include/unicodeobject.h
==============================================================================
--- python/trunk/Include/unicodeobject.h	(original)
+++ python/trunk/Include/unicodeobject.h	Fri May 30 20:10:04 2008
@@ -553,6 +553,12 @@
 PyAPI_FUNC(PyObject *) PyUnicode_FromFormatV(const char*, va_list);
 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 --------------------- */
 
 #ifdef HAVE_WCHAR_H

Modified: python/trunk/Objects/bytesobject.c
==============================================================================
--- python/trunk/Objects/bytesobject.c	(original)
+++ python/trunk/Objects/bytesobject.c	Fri May 30 20:10:04 2008
@@ -3,9 +3,6 @@
 #define PY_SSIZE_T_CLEAN
 
 #include "Python.h"
-
-#include "formatter_string.h"
-
 #include <ctype.h>
 
 #ifdef COUNT_ALLOCS
@@ -3939,6 +3936,35 @@
 \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__,
 "S.__format__(format_spec) -> unicode\n\
 \n\

Modified: python/trunk/Objects/floatobject.c
==============================================================================
--- python/trunk/Objects/floatobject.c	(original)
+++ python/trunk/Objects/floatobject.c	Fri May 30 20:10:04 2008
@@ -14,9 +14,6 @@
 #include <ieeefp.h>
 #endif
 
-#include "formatter_string.h"
-
-
 #ifdef _OSF_SOURCE
 /* OSF1 5.1 doesn't make this available with XOPEN_SOURCE_EXTENDED defined */
 extern int finite(double);
@@ -1398,26 +1395,22 @@
 	if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
 		return NULL;
 	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)) {
 		/* Convert format_spec to a str */
-		PyObject *result = NULL;
-		PyObject *newargs = NULL;
-		PyObject *string_format_spec = NULL;
-
-		string_format_spec = PyObject_Str(format_spec);
-		if (string_format_spec == NULL)
-			goto done;
-
-		newargs = Py_BuildValue("(O)", string_format_spec);
-		if (newargs == NULL)
-			goto done;
-
-		result = string_float__format__(self, newargs);
-
-		done:
-		Py_XDECREF(string_format_spec);
-		Py_XDECREF(newargs);
+		PyObject *result;
+		PyObject *str_spec = PyObject_Str(format_spec);
+
+		if (str_spec == NULL)
+			return NULL;
+
+		result = _PyFloat_FormatAdvanced(self,
+						 PyBytes_AS_STRING(str_spec),
+						 PyBytes_GET_SIZE(str_spec));
+
+		Py_DECREF(str_spec);
 		return result;
 	}
 	PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");

Modified: python/trunk/Objects/intobject.c
==============================================================================
--- python/trunk/Objects/intobject.c	(original)
+++ python/trunk/Objects/intobject.c	Fri May 30 20:10:04 2008
@@ -3,7 +3,6 @@
 
 #include "Python.h"
 #include <ctype.h>
-#include "formatter_string.h"
 
 static PyObject *int_int(PyIntObject *v);
 
@@ -1117,26 +1116,22 @@
 	if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
 		return NULL;
 	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)) {
 		/* Convert format_spec to a str */
-		PyObject *result = NULL;
-		PyObject *newargs = NULL;
-		PyObject *string_format_spec = NULL;
-
-		string_format_spec = PyObject_Str(format_spec);
-		if (string_format_spec == NULL)
-			goto done;
-
-		newargs = Py_BuildValue("(O)", string_format_spec);
-		if (newargs == NULL)
-			goto done;
-
-		result = string_int__format__(self, newargs);
-
-		done:
-		Py_XDECREF(string_format_spec);
-		Py_XDECREF(newargs);
+		PyObject *result;
+		PyObject *str_spec = PyObject_Str(format_spec);
+
+		if (str_spec == NULL)
+			return NULL;
+
+		result = _PyInt_FormatAdvanced(self,
+					       PyBytes_AS_STRING(str_spec),
+					       PyBytes_GET_SIZE(str_spec));
+
+		Py_DECREF(str_spec);
 		return result;
 	}
 	PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");

Modified: python/trunk/Objects/longobject.c
==============================================================================
--- python/trunk/Objects/longobject.c	(original)
+++ python/trunk/Objects/longobject.c	Fri May 30 20:10:04 2008
@@ -6,7 +6,6 @@
 
 #include "Python.h"
 #include "longintrepr.h"
-#include "formatter_string.h"
 
 #include <ctype.h>
 
@@ -3415,26 +3414,22 @@
 	if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
 		return NULL;
 	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)) {
 		/* Convert format_spec to a str */
-		PyObject *result = NULL;
-		PyObject *newargs = NULL;
-		PyObject *string_format_spec = NULL;
-
-		string_format_spec = PyObject_Str(format_spec);
-		if (string_format_spec == NULL)
-			goto done;
-
-		newargs = Py_BuildValue("(O)", string_format_spec);
-		if (newargs == NULL)
-			goto done;
-
-		result = string_long__format__(self, newargs);
-
-		done:
-		Py_XDECREF(string_format_spec);
-		Py_XDECREF(newargs);
+		PyObject *result;
+		PyObject *str_spec = PyObject_Str(format_spec);
+
+		if (str_spec == NULL)
+			return NULL;
+
+		result = _PyLong_FormatAdvanced(self,
+						PyBytes_AS_STRING(str_spec),
+						PyBytes_GET_SIZE(str_spec));
+
+		Py_DECREF(str_spec);
 		return result;
 	}
 	PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");

Modified: python/trunk/Objects/stringlib/formatter.h
==============================================================================
--- python/trunk/Objects/stringlib/formatter.h	(original)
+++ python/trunk/Objects/stringlib/formatter.h	Fri May 30 20:10:04 2008
@@ -102,12 +102,13 @@
   if failure, sets the exception
 */
 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,
                                   char default_type)
 {
-    STRINGLIB_CHAR *ptr = STRINGLIB_STR(format_spec);
-    STRINGLIB_CHAR *end = ptr + STRINGLIB_LEN(format_spec);
+    STRINGLIB_CHAR *ptr = format_spec;
+    STRINGLIB_CHAR *end = format_spec + format_spec_len;
 
     /* end-ptr is used throughout this code to specify the length of
        the input string */
@@ -756,56 +757,31 @@
 /************************************************************************/
 /*********** built in formatters ****************************************/
 /************************************************************************/
-#ifdef FORMAT_STRING
 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;
-
-    /* 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
+    PyObject *result = NULL;
 
     /* check for the special case of zero length format spec, make
-       it equivalent to str(value) */
-    if (STRINGLIB_LEN(format_spec) == 0) {
-        result = STRINGLIB_TOSTR(value);
+       it equivalent to str(obj) */
+    if (format_spec_len == 0) {
+        result = STRINGLIB_TOSTR(obj);
         goto done;
     }
 
-
     /* 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;
 
     /* type conversion? */
     switch (format.type) {
     case 's':
         /* no type conversion needed, already a string.  do the formatting */
-        result = format_string_internal(value, &format);
+        result = format_string_internal(obj, &format);
         break;
     default:
         /* unknown */
@@ -826,35 +802,31 @@
     }
 
 done:
-#if PY_VERSION_HEX < 0x03000000
-    Py_XDECREF(tmp);
-#endif
     return result;
 }
-#endif /* FORMAT_STRING */
 
 #if defined FORMAT_LONG || defined FORMAT_INT
 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 *tmp = NULL;
     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
-       it equivalent to str(value) */
-    if (STRINGLIB_LEN(format_spec) == 0) {
-        result = STRINGLIB_TOSTR(value);
+       it equivalent to str(obj) */
+    if (format_spec_len == 0) {
+        result = STRINGLIB_TOSTR(obj);
         goto done;
     }
 
     /* 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;
 
     /* type conversion? */
@@ -868,7 +840,7 @@
     case 'n':
         /* no type conversion needed, already an int (or long).  do
 	   the formatting */
-	    result = format_int_or_long_internal(value, &format, tostring);
+	    result = format_int_or_long_internal(obj, &format, tostring);
         break;
 
     case 'e':
@@ -879,10 +851,10 @@
     case 'G':
     case '%':
         /* convert to float */
-        tmp = PyNumber_Float(value);
+        tmp = PyNumber_Float(obj);
         if (tmp == NULL)
             goto done;
-        result = format_float_internal(value, &format);
+        result = format_float_internal(obj, &format);
         break;
 
     default:
@@ -917,9 +889,12 @@
 #endif
 
 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 */
 
@@ -935,32 +910,35 @@
 }
 
 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 */
 
 #ifdef FORMAT_FLOAT
 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;
     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
-       it equivalent to str(value) */
-    if (STRINGLIB_LEN(format_spec) == 0) {
-        result = STRINGLIB_TOSTR(value);
+       it equivalent to str(obj) */
+    if (format_spec_len == 0) {
+        result = STRINGLIB_TOSTR(obj);
         goto done;
     }
 
     /* 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;
 
     /* type conversion? */
@@ -979,7 +957,7 @@
     case 'n':
     case '%':
         /* no conversion, already a float.  do the formatting */
-        result = format_float_internal(value, &format);
+        result = format_float_internal(obj, &format);
         break;
 
     default:

Modified: python/trunk/Objects/unicodeobject.c
==============================================================================
--- python/trunk/Objects/unicodeobject.c	(original)
+++ python/trunk/Objects/unicodeobject.c	Fri May 30 20:10:04 2008
@@ -42,8 +42,6 @@
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
 
-#include "formatter_unicode.h"
-
 #include "unicodeobject.h"
 #include "ucnhash.h"
 
@@ -7863,6 +7861,35 @@
 \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__,
 "S.__format__(format_spec) -> unicode\n\
 \n\

Modified: python/trunk/Python/formatter_string.c
==============================================================================
--- python/trunk/Python/formatter_string.c	(original)
+++ python/trunk/Python/formatter_string.c	Fri May 30 20:10:04 2008
@@ -4,12 +4,11 @@
    of int.__float__, etc., that take and return string objects */
 
 #include "Python.h"
-#include "formatter_string.h"
-
 #include "../Objects/stringlib/stringdefs.h"
 
-#define FORMAT_STRING string__format__
-#define FORMAT_LONG   string_long__format__
-#define FORMAT_INT    string_int__format__
-#define FORMAT_FLOAT  string_float__format__
+#define FORMAT_STRING _PyBytes_FormatAdvanced
+#define FORMAT_LONG   _PyLong_FormatAdvanced
+#define FORMAT_INT    _PyInt_FormatAdvanced
+#define FORMAT_FLOAT  _PyFloat_FormatAdvanced
+
 #include "../Objects/stringlib/formatter.h"

Modified: python/trunk/Python/formatter_unicode.c
==============================================================================
--- python/trunk/Python/formatter_unicode.c	(original)
+++ python/trunk/Python/formatter_unicode.c	Fri May 30 20:10:04 2008
@@ -2,12 +2,12 @@
    built-in formatter for unicode.  That is, unicode.__format__(). */
 
 #include "Python.h"
-#include "formatter_unicode.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
    with only the string versions of those.  The builtin format()
    will convert them to unicode. */
+
 #include "../Objects/stringlib/formatter.h"


More information about the Python-checkins mailing list