From a00905e59bdcff64ec96a11fa29dc3791f6110b3 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 26 Nov 2009 20:49:09 +0100 Subject: [PATCH] support len(char*) efficiently by calling strlen() instead --- Cython/Compiler/Optimize.py | 29 +++++++++++++++++ tests/run/charptr_len.pyx | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 tests/run/charptr_len.pyx diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 3e5482af..51dbd767 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -1045,6 +1045,28 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ) return node + Pyx_strlen_func_type = PyrexTypes.CFuncType( + PyrexTypes.c_size_t_type, [ + PyrexTypes.CFuncTypeArg("bytes", PyrexTypes.c_char_ptr_type, None) + ]) + + def _handle_simple_function_len(self, node, pos_args): + if len(pos_args) != 1: + self._error_wrong_arg_count('len', node, pos_args, 1) + return node + arg = pos_args[0] + if isinstance(arg, ExprNodes.CoerceToPyTypeNode): + arg = arg.arg + if not arg.type.is_string: + return node + node = ExprNodes.PythonCapiCallNode( + node.pos, "strlen", self.Pyx_strlen_func_type, + args = [arg], + is_temp = node.is_temp, + utility_code = include_string_h_utility_code, + ) + return node + ### special methods Pyx_tp_new_func_type = PyrexTypes.CFuncType( @@ -1483,6 +1505,13 @@ static INLINE PyObject* __Pyx_Type(PyObject* o) { ) +include_string_h_utility_code = UtilityCode( +proto = """ +#include +""" +) + + tpnew_utility_code = UtilityCode( proto = """ static INLINE PyObject* __Pyx_tp_new(PyObject* type_obj) { diff --git a/tests/run/charptr_len.pyx b/tests/run/charptr_len.pyx new file mode 100644 index 00000000..84c94008 --- /dev/null +++ b/tests/run/charptr_len.pyx @@ -0,0 +1,65 @@ +__doc__ = """ +>>> lentest_char() +7 +>>> lentest_char_c() +7 + +>>> lentest_uchar() +7 +>>> lentest_uchar_c() +7 + +>>> lentest_py() +7 +>>> lentest_py_c() +7 +""" + + +cimport cython + +cdef char* s = b"abcdefg" +cdef unsigned char* us = b"abcdefg" +cdef bytes pystr = b"abcdefg" + + +@cython.test_assert_path_exists( + "//PythonCapiCallNode", + ) +def lentest_char(): + return len(s) + +@cython.test_assert_path_exists( + "//PythonCapiCallNode", + ) +def lentest_char_c(): + cdef Py_ssize_t l = len(s) + return l + + +@cython.test_assert_path_exists( + "//PythonCapiCallNode", + ) +def lentest_uchar(): + return len(us) + +@cython.test_assert_path_exists( + "//PythonCapiCallNode", + ) +def lentest_uchar_c(): + cdef Py_ssize_t l = len(us) + return l + + +@cython.test_assert_path_exists( + "//SimpleCallNode", + ) +def lentest_py(): + return len(pystr) + +@cython.test_assert_path_exists( + "//SimpleCallNode", + ) +def lentest_py_c(): + cdef Py_ssize_t l = len(pystr) + return l -- 2.26.2