diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 3213d6cd723617f7d068afedf65b90fb85817ac7..50b29877c6033bf55271d507af9bf152038c6384 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -6908,7 +6908,7 @@ getitem_int_pyunicode_utility_code = UtilityCode( proto = ''' #define __Pyx_GetItemInt_Unicode(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\ __Pyx_GetItemInt_Unicode_Fast(o, i) : \\ - __Pyx_GetItemInt_Generic(o, to_py_func(i))) + __Pyx_GetItemInt_Unicode_Generic(o, to_py_func(i))) static CYTHON_INLINE Py_UNICODE __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py_ssize_t i) { if (likely((0 <= i) & (i < PyUnicode_GET_SIZE(ustring)))) { diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 23f9e6088f671acb35d45fa981b1999d81a17e6b..c5b17d456832980c81b35175e761765c76858d8f 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -1305,15 +1305,6 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): return self._optimise_int_indexing(node, arg, index_node) return node - PyUnicode_GetItemInt_func_type = PyrexTypes.CFuncType( - PyrexTypes.c_py_unicode_type, [ - PyrexTypes.CFuncTypeArg("unicode", Builtin.unicode_type, None), - PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_py_ssize_t_type, None), - PyrexTypes.CFuncTypeArg("check_bounds", PyrexTypes.c_int_type, None), - ], - exception_value = "((Py_UNICODE)-1)", - exception_check = True) - PyBytes_GetItemInt_func_type = PyrexTypes.CFuncType( PyrexTypes.c_char_type, [ PyrexTypes.CFuncTypeArg("bytes", Builtin.bytes_type, None), @@ -1326,23 +1317,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): def _optimise_int_indexing(self, coerce_node, arg, index_node): env = self.current_env() bound_check_bool = env.directives['boundscheck'] and 1 or 0 - if arg.base.type is Builtin.unicode_type: - if coerce_node.type is PyrexTypes.c_py_unicode_type: - # unicode[index] -> Py_UNICODE - bound_check_node = ExprNodes.IntNode( - coerce_node.pos, value=str(bound_check_bool), - constant_result=bound_check_bool) - return ExprNodes.PythonCapiCallNode( - coerce_node.pos, "__Pyx_PyUnicode_GetItemInt", - self.PyUnicode_GetItemInt_func_type, - args = [ - arg.base.as_none_safe_node("'NoneType' object is not subscriptable"), - index_node.coerce_to(PyrexTypes.c_py_ssize_t_type, env), - bound_check_node, - ], - is_temp = True, - utility_code=unicode_index_utility_code) - elif arg.base.type is Builtin.bytes_type: + if arg.base.type is Builtin.bytes_type: if coerce_node.type in (PyrexTypes.c_char_type, PyrexTypes.c_uchar_type): # bytes[index] -> char bound_check_node = ExprNodes.IntNode( @@ -2527,27 +2502,6 @@ bad: ) -unicode_index_utility_code = UtilityCode( -proto = """ -static CYTHON_INLINE Py_UNICODE __Pyx_PyUnicode_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds); /* proto */ -""", -impl = """ -static CYTHON_INLINE Py_UNICODE __Pyx_PyUnicode_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds) { - if (check_bounds) { - if (unlikely(index >= PyUnicode_GET_SIZE(unicode)) | - ((index < 0) & unlikely(index < -PyUnicode_GET_SIZE(unicode)))) { - PyErr_Format(PyExc_IndexError, "string index out of range"); - return (Py_UNICODE)-1; - } - } - if (index < 0) - index += PyUnicode_GET_SIZE(unicode); - return PyUnicode_AS_UNICODE(unicode)[index]; -} -""" -) - - bytes_index_utility_code = UtilityCode( proto = """ static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds); /* proto */ diff --git a/tests/run/py_unicode_type.pyx b/tests/run/py_unicode_type.pyx index 7bd4c7fdb84c460970cc569b722307654a48c53c..6655dd865918afc9f1b8a28af7c3f3bc72ce152d 100644 --- a/tests/run/py_unicode_type.pyx +++ b/tests/run/py_unicode_type.pyx @@ -29,80 +29,6 @@ def compare_klingon(): print(char_KLINGON == u'B') -def index_literal(int i): - """ - >>> index_literal(0) == '1' - True - >>> index_literal(-5) == '1' - True - >>> index_literal(2) == '3' - True - >>> index_literal(4) == '5' - True - """ - return u"12345"[i] - - -@cython.test_assert_path_exists("//PythonCapiCallNode") -@cython.test_fail_if_path_exists("//IndexNode", - "//CoerceFromPyTypeNode") -def index_literal_pyunicode_cast(int i): - """ - >>> index_literal_pyunicode_cast(0) == '1' - True - >>> index_literal_pyunicode_cast(-5) == '1' - True - >>> index_literal_pyunicode_cast(2) == '3' - True - >>> index_literal_pyunicode_cast(4) == '5' - True - >>> index_literal_pyunicode_coerce(6) - Traceback (most recent call last): - IndexError: string index out of range - """ - return <Py_UNICODE>(u"12345"[i]) - - -@cython.test_assert_path_exists("//PythonCapiCallNode") -@cython.test_fail_if_path_exists("//IndexNode", - "//CoerceFromPyTypeNode") -def index_literal_pyunicode_coerce(int i): - """ - >>> index_literal_pyunicode_coerce(0) == '1' - True - >>> index_literal_pyunicode_coerce(-5) == '1' - True - >>> index_literal_pyunicode_coerce(2) == '3' - True - >>> index_literal_pyunicode_coerce(4) == '5' - True - >>> index_literal_pyunicode_coerce(6) - Traceback (most recent call last): - IndexError: string index out of range - """ - cdef Py_UNICODE result = u"12345"[i] - return result - - -@cython.test_assert_path_exists("//PythonCapiCallNode") -@cython.test_fail_if_path_exists("//IndexNode", - "//CoerceFromPyTypeNode") -@cython.boundscheck(False) -def index_literal_pyunicode_coerce_no_check(int i): - """ - >>> index_literal_pyunicode_coerce_no_check(0) == '1' - True - >>> index_literal_pyunicode_coerce_no_check(-5) == '1' - True - >>> index_literal_pyunicode_coerce_no_check(2) == '3' - True - >>> index_literal_pyunicode_coerce_no_check(4) == '5' - True - """ - cdef Py_UNICODE result = u"12345"[i] - return result - - from cpython.unicode cimport PyUnicode_FromOrdinal import sys diff --git a/tests/run/unicode_indexing.pyx b/tests/run/unicode_indexing.pyx index 1032d52dbc397c550a0794609090af3c163d6b3f..9750dc5098ca033623a48464bb0e801f3bbd3f6f 100644 --- a/tests/run/unicode_indexing.pyx +++ b/tests/run/unicode_indexing.pyx @@ -2,9 +2,9 @@ cimport cython cdef unicode _ustring = u'azerty123456' - ustring = _ustring + @cython.test_assert_path_exists("//CoerceToPyTypeNode", "//IndexNode") @cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode") @@ -25,6 +25,8 @@ def index(unicode ustring, Py_ssize_t i): """ return ustring[i] + + @cython.test_assert_path_exists("//CoerceToPyTypeNode", "//IndexNode") @cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode") @@ -45,6 +47,65 @@ def index_literal(Py_ssize_t i): """ return u'azerty123456'[i] + +@cython.test_assert_path_exists("//IndexNode") +@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode") +def index_literal_pyunicode_cast(int i): + """ + >>> index_literal_pyunicode_cast(0) == '1' + True + >>> index_literal_pyunicode_cast(-5) == '1' + True + >>> index_literal_pyunicode_cast(2) == '3' + True + >>> index_literal_pyunicode_cast(4) == '5' + True + >>> index_literal_pyunicode_coerce(6) + Traceback (most recent call last): + IndexError: string index out of range + """ + return <Py_UNICODE>(u"12345"[i]) + + +@cython.test_assert_path_exists("//IndexNode", + "//SingleAssignmentNode") +@cython.test_fail_if_path_exists("//SingleAssignmentNode//CoerceToPyTypeNode") +def index_literal_pyunicode_coerce(int i): + """ + >>> index_literal_pyunicode_coerce(0) == '1' + True + >>> index_literal_pyunicode_coerce(-5) == '1' + True + >>> index_literal_pyunicode_coerce(2) == '3' + True + >>> index_literal_pyunicode_coerce(4) == '5' + True + >>> index_literal_pyunicode_coerce(6) + Traceback (most recent call last): + IndexError: string index out of range + """ + cdef Py_UNICODE result = u"12345"[i] + return result + + +@cython.test_assert_path_exists("//SingleAssignmentNode") +@cython.test_fail_if_path_exists("//SingleAssignmentNode//CoerceFromPyTypeNode") +@cython.boundscheck(False) +def index_literal_pyunicode_coerce_no_check(int i): + """ + >>> index_literal_pyunicode_coerce_no_check(0) == '1' + True + >>> index_literal_pyunicode_coerce_no_check(-5) == '1' + True + >>> index_literal_pyunicode_coerce_no_check(2) == '3' + True + >>> index_literal_pyunicode_coerce_no_check(4) == '5' + True + """ + cdef Py_UNICODE result = u"12345"[i] + return result + + @cython.test_assert_path_exists("//CoerceToPyTypeNode", "//IndexNode") @cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode") @@ -64,6 +125,7 @@ def index_no_boundscheck(unicode ustring, Py_ssize_t i): """ return ustring[i] + @cython.test_assert_path_exists("//CoerceToPyTypeNode", "//IndexNode") @cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode") @@ -100,6 +162,7 @@ def index_compare(unicode ustring, Py_ssize_t i): """ return ustring[i] == u'a' + @cython.test_assert_path_exists("//CoerceToPyTypeNode", "//IndexNode", "//PrimaryCmpNode") @@ -127,6 +190,7 @@ def index_compare_string(unicode ustring, Py_ssize_t i, unicode other): """ return ustring[i] == other + @cython.test_assert_path_exists("//CoerceToPyTypeNode", "//IndexNode", "//MulNode", @@ -141,6 +205,7 @@ def index_multiply(unicode ustring, Py_ssize_t i, int mul): """ return ustring[i] * mul + @cython.test_assert_path_exists("//CoerceToPyTypeNode", "//IndexNode", "//AddNode",