Commit 646af4e4 authored by Stefan Behnel's avatar Stefan Behnel

support slicing with negative indices for C strings and C++ strings during decoding

parent 0cbc0f43
......@@ -506,16 +506,19 @@ static CYTHON_INLINE PyObject* __Pyx_decode_cpp_string(
const char* cstring = cppstring.data();
Py_ssize_t length = cppstring.size();
if (start < 0)
if (unlikely(start < 0)) {
start += length;
if (stop < 0)
length += stop;
else if (length > stop)
length = stop;
if ((start < 0) | (start >= length))
if (unlikely(start < 0))
start = 0;
}
if (unlikely(stop < 0))
stop += length;
else if (stop >= length)
stop = length;
if (unlikely(start >= stop))
return PyUnicode_FromUnicode(NULL, 0);
cstring += start;
length -= start;
length = stop - start;
if (decode_func) {
return decode_func(cstring, length, errors);
......@@ -532,12 +535,26 @@ static CYTHON_INLINE PyObject* __Pyx_decode_c_string(
PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors));
/////////////// decode_c_string ///////////////
//@requires StringTools.c::IncludeStringH
static CYTHON_INLINE PyObject* __Pyx_decode_c_string(
const char* cstring, Py_ssize_t start, Py_ssize_t stop,
const char* encoding, const char* errors,
PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) {
Py_ssize_t length = stop - start;
Py_ssize_t length;
if (unlikely((start < 0) | (stop < 0))) {
length = strlen(cstring);
if (start < 0) {
start += length;
if (start < 0)
start = 0;
}
if (stop < 0)
stop += length;
}
length = stop - start;
if (unlikely(length <= 0))
return PyUnicode_FromUnicode(NULL, 0);
cstring += start;
if (decode_func) {
return decode_func(cstring, length, errors);
......
......@@ -60,11 +60,14 @@ def slice_charptr_decode_slice2():
def slice_charptr_decode_strlen():
"""
>>> print(str(slice_charptr_decode_strlen()).replace("u'", "'"))
('abcABCqtp', 'bcABCqtp', '')
('abcABCqtp', 'bcABCqtp', '', 'BCq', 'abcA', '')
"""
return (cstring.decode('UTF-8'),
cstring[1:].decode('UTF-8'),
cstring[9:].decode('UTF-8'))
cstring[9:].decode('UTF-8'),
cstring[-5:-2].decode('UTF-8'),
cstring[:-5].decode('UTF-8'),
cstring[:-9].decode('UTF-8'))
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
......
......@@ -165,15 +165,50 @@ def test_decode_sliced(char* a):
cdef string b = string(a)
return b[1:3].decode('ascii')
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_negative(char* a):
"""
>>> a,b,c,d = test_decode_sliced_negative(b_asdf)
>>> print(a)
sd
>>> print(b)
a
>>> print(c)
<BLANKLINE>
>>> print(d)
<BLANKLINE>
"""
cdef string b = string(a)
return b[-3:-1].decode('ascii'), b[-5:-3].decode('ascii'), b[-20:-4].decode('ascii'), b[-2:-20].decode('ascii')
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_end(char* a):
"""
>>> print(test_decode_sliced_end(b_asdf))
>>> a,b = test_decode_sliced_end(b_asdf)
>>> print(a)
asd
>>> print(b)
asdf
"""
cdef string b = string(a)
return b[:3].decode('ascii')
return b[:3].decode('ascii'), b[:42].decode('ascii')
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_end_negative(char* a):
"""
>>> a,b,c = test_decode_sliced_end_negative(b_asdf)
>>> print(a)
asd
>>> print(b)
a
>>> print(c)
<BLANKLINE>
"""
cdef string b = string(a)
return b[:-1].decode('ascii'), b[:-3].decode('ascii'), b[:-4].decode('ascii')
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
......@@ -185,6 +220,19 @@ def test_decode_sliced_start(char* a):
cdef string b = string(a)
return b[2:].decode('ascii')
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_start_negative(char* a):
"""
>>> a,b = test_decode_sliced_start_negative(b_asdf)
>>> print(a)
df
>>> print(b)
asdf
"""
cdef string b = string(a)
return b[-2:].decode('ascii'), b[-20:].decode('ascii')
def test_equals_operator(char *a, char *b):
"""
>>> test_equals_operator(b_asdf, b_asdf)
......
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