Commit 3cc3601c authored by Stefan Behnel's avatar Stefan Behnel

clean up GetItemInt code and fix negative indexing of objects with length > max(Py_ssize_t)

parent ac90a80a
...@@ -238,6 +238,27 @@ static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { ...@@ -238,6 +238,27 @@ static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
/////////////// GetItemInt.proto /////////////// /////////////// GetItemInt.proto ///////////////
#define __Pyx_GetItemInt(o, i, size, to_py_func, is_list, wraparound, boundscheck) \
(((size) <= sizeof(Py_ssize_t)) ? \
__Pyx_GetItemInt_Fast(o, i, is_list, wraparound, boundscheck) : \
__Pyx_GetItemInt_Generic(o, to_py_func(i)))
{{for type in ['List', 'Tuple']}}
#define __Pyx_GetItemInt_{{type}}(o, i, size, to_py_func, is_list, wraparound, boundscheck) \
(((size) <= sizeof(Py_ssize_t)) ? \
__Pyx_GetItemInt_{{type}}_Fast(o, i, wraparound, boundscheck) : \
__Pyx_GetItemInt_Generic(o, to_py_func(i)))
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ssize_t i,
int wraparound, int boundscheck);
{{endfor}}
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j);
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
int is_list, int wraparound, int boundscheck);
/////////////// GetItemInt ///////////////
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
PyObject *r; PyObject *r;
if (!j) return NULL; if (!j) return NULL;
...@@ -247,11 +268,6 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j ...@@ -247,11 +268,6 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j
} }
{{for type in ['List', 'Tuple']}} {{for type in ['List', 'Tuple']}}
#define __Pyx_GetItemInt_{{type}}(o, i, size, to_py_func, is_list, wraparound, boundscheck) \
(((size) <= sizeof(Py_ssize_t)) ? \
__Pyx_GetItemInt_{{type}}_Fast(o, i, wraparound, boundscheck) : \
__Pyx_GetItemInt_Generic(o, to_py_func(i)))
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ssize_t i, static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ssize_t i,
int wraparound, int boundscheck) { int wraparound, int boundscheck) {
#if CYTHON_COMPILING_IN_CPYTHON #if CYTHON_COMPILING_IN_CPYTHON
...@@ -268,11 +284,6 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ss ...@@ -268,11 +284,6 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ss
} }
{{endfor}} {{endfor}}
#define __Pyx_GetItemInt(o, i, size, to_py_func, is_list, wraparound, boundscheck) \
(((size) <= sizeof(Py_ssize_t)) ? \
__Pyx_GetItemInt_Fast(o, i, is_list, wraparound, boundscheck) : \
__Pyx_GetItemInt_Generic(o, to_py_func(i)))
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
int is_list, int wraparound, int boundscheck) { int is_list, int wraparound, int boundscheck) {
#if CYTHON_COMPILING_IN_CPYTHON #if CYTHON_COMPILING_IN_CPYTHON
...@@ -291,13 +302,20 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, ...@@ -291,13 +302,20 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
Py_INCREF(r); Py_INCREF(r);
return r; return r;
} }
} else { /* inlined PySequence_GetItem() */ } else { /* inlined PySequence_GetItem() + special cased length overflow */
PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
if (likely(m && m->sq_item)) { if (likely(m && m->sq_item)) {
if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
Py_ssize_t l = m->sq_length(o); Py_ssize_t l = m->sq_length(o);
if (unlikely(l < 0)) return NULL; if (likely(l >= 0)) {
i += l; i += l;
} else {
// if length > max(Py_ssize_t), maybe the object can wrap around itself?
if (PyErr_ExceptionMatches(PyExc_OverflowError))
PyErr_Clear();
else
return NULL;
}
} }
return m->sq_item(o, i); return m->sq_item(o, i);
} }
......
...@@ -9,6 +9,9 @@ import sys ...@@ -9,6 +9,9 @@ import sys
if sys.version_info < (2,5): if sys.version_info < (2,5):
__doc__ = __doc__.replace(u"'int' object ...", u'unsubscriptable object') __doc__ = __doc__.replace(u"'int' object ...", u'unsubscriptable object')
cdef Py_ssize_t maxsize = getattr(sys, 'maxsize', getattr(sys, 'maxint', None))
py_maxsize = maxsize
import cython import cython
def index_tuple(tuple t, int i): def index_tuple(tuple t, int i):
...@@ -160,3 +163,39 @@ def large_literal_index(object o): ...@@ -160,3 +163,39 @@ def large_literal_index(object o):
True True
""" """
return o[1000000000000000000000000000000] return o[1000000000000000000000000000000]
class LargeIndexable(object):
def __len__(self):
raise OverflowError
def __getitem__(self, index):
return index
def test_large_indexing(obj):
"""
>>> obj = LargeIndexable()
>>> zero, pone, none, pmaxsize, nmaxsize = test_large_indexing(obj)
>>> # , p2maxsize, n2maxsize
>>> zero
0
>>> pone
1
>>> none
-1
>>> pmaxsize == py_maxsize
True
>>> nmaxsize == -py_maxsize
True
#>>> p2maxsize == py_maxsize*2
#True
#>>> n2maxsize == -py_maxsize*2
#True
"""
return (
obj[0], obj[1], obj[-1],
obj[maxsize], obj[-maxsize],
#obj[maxsize*2], obj[-maxsize*2] # FIXME!
)
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