optimise unicode.replace()
authorStefan Behnel <scoder@users.berlios.de>
Sun, 21 Mar 2010 20:10:25 +0000 (21:10 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Sun, 21 Mar 2010 20:10:25 +0000 (21:10 +0100)
Cython/Compiler/Optimize.py
tests/run/unicodemethods.pyx

index 07ddf88bc71216e5f41aad30eeaf46c3553664a0..134538c79c113b4a6f324b93a04d2ee265ca869b 100644 (file)
@@ -1629,6 +1629,32 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
         return ExprNodes.CoerceToPyTypeNode(
             method_call, self.env_stack[-1], PyrexTypes.py_object_type)
 
+    PyUnicode_Replace_func_type = PyrexTypes.CFuncType(
+        Builtin.unicode_type, [
+            PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None),
+            PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None),
+            PyrexTypes.CFuncTypeArg("replstr", PyrexTypes.py_object_type, None),
+            PyrexTypes.CFuncTypeArg("maxcount", PyrexTypes.c_py_ssize_t_type, None),
+            ])
+
+    def _handle_simple_method_unicode_replace(self, node, args, is_unbound_method):
+        """Replace unicode.replace(...) by a direct call to the
+        corresponding C-API function.
+        """
+        if len(args) not in (3,4):
+            self._error_wrong_arg_count('unicode.replace', node, args, "3-4")
+            return node
+        if len(args) < 4:
+            args.append(ExprNodes.IntNode(
+                node.pos, value="-1", type=PyrexTypes.c_py_ssize_t_type))
+        else:
+            args[3] = args[3].coerce_to(PyrexTypes.c_py_ssize_t_type,
+                                        self.env_stack[-1])
+
+        return self._substitute_method_call(
+            node, "PyUnicode_Replace", self.PyUnicode_Replace_func_type,
+            'replace', is_unbound_method, args)
+
     PyUnicode_AsEncodedString_func_type = PyrexTypes.CFuncType(
         Builtin.bytes_type, [
             PyrexTypes.CFuncTypeArg("obj", Builtin.unicode_type, None),
index 6882b11a618c454cad1bb8a20758104b2097868b..2bb350133d421ac8f3f8be1e8adce4ff6bf6ff56 100644 (file)
@@ -434,3 +434,34 @@ def count_start_end(unicode s, substring, start, end):
     """
     cdef Py_ssize_t pos = s.count(substring, start, end)
     return pos
+
+
+# unicode.replace(s, sub, repl, [maxcount])
+
+@cython.test_fail_if_path_exists(
+    "//CoerceFromPyTypeNode",
+    "//CastNode", "//TypecastNode")
+@cython.test_assert_path_exists(
+    "//PythonCapiCallNode")
+def replace(unicode s, substring, repl):
+    """
+    >>> print( text.replace('sa', 'SA') )
+    ab jd  sdflk as SA  SAdas asdas fsdf 
+    >>> print( replace(text, 'sa', 'SA') )
+    ab jd  sdflk as SA  SAdas asdas fsdf 
+    """
+    return s.replace(substring, repl)
+
+@cython.test_fail_if_path_exists(
+    "//CastNode", "//TypecastNode")
+@cython.test_assert_path_exists(
+    "//CoerceFromPyTypeNode",
+    "//PythonCapiCallNode")
+def replace_maxcount(unicode s, substring, repl, maxcount):
+    """
+    >>> print( text.replace('sa', 'SA', 1) )
+    ab jd  sdflk as SA  sadas asdas fsdf 
+    >>> print( replace_maxcount(text, 'sa', 'SA', 1) )
+    ab jd  sdflk as SA  sadas asdas fsdf 
+    """
+    return s.replace(substring, repl, maxcount)