Commit 059eac4e authored by Stefan Behnel's avatar Stefan Behnel

optimise str % formatting

parent 48975c91
......@@ -9463,9 +9463,14 @@ class ModNode(DivNode):
def py_operation_function(self):
if self.operand1.type is unicode_type:
if self.operand1.may_be_none():
return '__Pyx_PyUnicode_Format'
return '__Pyx_PyUnicode_FormatSafe'
else:
return 'PyUnicode_Format'
elif self.operand1.type is str_type:
if self.operand1.may_be_none():
return '__Pyx_PyString_FormatSafe'
else:
return '__Pyx_PyString_Format'
return super(ModNode, self).py_operation_function()
......
......@@ -157,10 +157,17 @@
#define __Pyx_PyUnicode_READ(k, d, i) ((k=k), (Py_UCS4)(((Py_UNICODE*)d)[i]))
#endif
#define __Pyx_PyUnicode_Format(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
#define __Pyx_PyUnicode_Concat(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
PyNumber_Add(a, b) : PyUnicode_Concat(a, b))
#if PY_MAJOR_VERSION >= 3
#define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b)
#else
#define __Pyx_PyString_Format(a, b) PyString_Format(a, b)
#endif
#if PY_MAJOR_VERSION >= 3
#define PyBaseString_Type PyUnicode_Type
#define PyStringObject PyUnicodeObject
......
......@@ -83,3 +83,52 @@ def literal_join(args):
result = '|'.join(args)
assert cython.typeof(result) == 'basestring object', cython.typeof(result)
return result
# unicode.__mod__(format, values)
format1 = 'abc%sdef'
format2 = 'abc%sdef%sghi'
def mod_format(str s, values):
"""
>>> mod_format(format1, 'sa') == 'abcsadef' or mod_format(format1, 'sa')
True
>>> mod_format(format2, ('XYZ', 'ABC')) == 'abcXYZdefABCghi' or mod_format(format2, ('XYZ', 'ABC'))
True
>>> mod_format(None, 'sa')
Traceback (most recent call last):
TypeError: unsupported operand type(s) for %: 'NoneType' and 'str'
>>> class RMod(object):
... def __rmod__(self, other):
... return 123
>>> mod_format(None, RMod())
123
"""
assert cython.typeof(s % values) == 'basestring object', cython.typeof(s % values)
return s % values
def mod_format_literal(values):
"""
>>> mod_format_literal('sa') == 'abcsadef' or mod_format(format1, 'sa')
True
>>> mod_format_literal(('sa',)) == 'abcsadef' or mod_format(format1, ('sa',))
True
>>> mod_format_literal(['sa']) == "abc['sa']def" or mod_format(format1, ['sa'])
True
"""
assert cython.typeof('abc%sdef' % values) == 'basestring object', cython.typeof('abc%sdef' % values)
return 'abc%sdef' % values
def mod_format_tuple(*values):
"""
>>> mod_format_tuple('sa') == 'abcsadef' or mod_format(format1, 'sa')
True
>>> mod_format_tuple()
Traceback (most recent call last):
TypeError: not enough arguments for format string
"""
assert cython.typeof('abc%sdef' % values) == 'basestring object', cython.typeof('abc%sdef' % values)
return 'abc%sdef' % values
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment