[pypy-svn] r54643 - pypy/branch/io-improvements/pypy/objspace/std

fijal at codespeak.net fijal at codespeak.net
Sun May 11 03:14:08 CEST 2008


Author: fijal
Date: Sun May 11 03:14:05 2008
New Revision: 54643

Modified:
   pypy/branch/io-improvements/pypy/objspace/std/formatting.py
Log:
Actually use string builder for '%' formatting. This (for boehm) nicely speeds
up microbenchs by 15-35% depending on benchmark used


Modified: pypy/branch/io-improvements/pypy/objspace/std/formatting.py
==============================================================================
--- pypy/branch/io-improvements/pypy/objspace/std/formatting.py	(original)
+++ pypy/branch/io-improvements/pypy/objspace/std/formatting.py	Sun May 11 03:14:05 2008
@@ -5,7 +5,7 @@
 from pypy.rlib.rarithmetic import ovfcheck, formatd_overflow, isnan, isinf
 from pypy.interpreter.error import OperationError
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.rlib.debug import check_annotation
+from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
 
 class BaseStringFormatter(object):
     def __init__(self, space, values_w, w_valuedict):
@@ -256,7 +256,10 @@
             return result
 
         def format(self):
-            result = []      # list of characters or unichars
+            if do_unicode:
+                result = UnicodeBuilder()
+            else:
+                result = StringBuilder()
             self.result = result
             while True:
                 # fast path: consume as many characters as possible
@@ -267,9 +270,9 @@
                         break
                     i += 1
                 else:
-                    result += const(fmt[i0:])
-                    break     # end of 'fmt' string 
-                result += const(fmt[i0:i])
+                    result.append_slice(fmt, i0, len(fmt))
+                    break     # end of 'fmt' string
+                result.append_slice(fmt, i0, i)
                 self.fmtpos = i + 1
 
                 # interpret the next formatter
@@ -295,7 +298,7 @@
                     self.unknown_fmtchar()
 
             self.checkconsumed()
-            return result
+            return result.build()
 
         def unknown_fmtchar(self):
             space = self.space
@@ -316,22 +319,28 @@
 
         def std_wp(self, r):
             length = len(r)
+            if do_unicode and isinstance(r, str):
+                # convert string to unicode explicitely here
+                r = unicode(r)
             prec = self.prec
             if prec == -1 and self.width == 0:
                 # fast path
-                self.result += const(r)
+                self.result.append(const(r))
                 return
             if prec >= 0 and prec < length:
                 length = prec   # ignore the end of the string if too long
             result = self.result
             padding = self.width - length
+            if padding < 0:
+                padding = 0
+            assert padding >= 0
             if not self.f_ljust and padding > 0:
-                result += const(' ') * padding
+                result.append_multiple_char(const(' '), padding)
                 # add any padding at the left of 'r'
                 padding = 0
-            result += const(r[:length])       # add 'r' itself
+            result.append_slice(r, 0, length)       # add 'r' itself
             if padding > 0:
-                result += const(' ') * padding
+                result.append_multiple_char(const(' '), padding)
             # add any remaining padding at the right
         std_wp._annspecialcase_ = 'specialize:argtype(1)'
 
@@ -350,6 +359,8 @@
             # by pushing the pad character into self.result
             result = self.result
             padding = self.width - len(r) - len(prefix)
+            if padding <= 0:
+                padding = 0
 
             if self.f_ljust:
                 padnumber = '<'
@@ -358,16 +369,20 @@
             else:
                 padnumber = '>'
 
+            assert padding >= 0
             if padnumber == '>':
-                result += const(' ') * padding    # pad with spaces on the left
+                result.append_multiple_char(const(' '), padding)
+                # pad with spaces on the left
             if sign:
-                result += const(r[0])        # the sign
-            result += const(prefix)               # the prefix
+                result.append(const(r[0]))        # the sign
+            result.append(const(prefix))               # the prefix
             if padnumber == '0':
-                result += const('0') * padding    # pad with zeroes
-            result += const(r[int(sign):])        # the rest of the number
+                result.append_multiple_char(const('0'), padding)
+                # pad with zeroes
+            result.append_slice(const(r), int(sign), len(r))
+            # the rest of the number
             if padnumber == '<':           # spaces on the right
-                result += const(' ') * padding
+                result.append_multiple_char(const(' '), padding)
 
         def fmt_s(self, w_value):
             space = self.space
@@ -454,14 +469,12 @@
             # fall through to the unicode case
             fmt = unicode(fmt)
         else:
-            check_annotation(result, is_list_of_chars_or_unichars)
-            return space.wrap(''.join(result))
+            return space.wrap(result)
     else:
         fmt = space.unicode_w(w_fmt)
     formatter = UnicodeFormatter(space, fmt, values_w, w_valuedict)
     result = formatter.format()
-    check_annotation(result, is_list_of_chars_or_unichars)
-    return space.wrap(u''.join(result))
+    return space.wrap(result)
 
 def mod_format(space, w_format, w_values, do_unicode=False):
     if space.is_true(space.isinstance(w_values, space.w_tuple)):



More information about the Pypy-commit mailing list