/////////////// ArrayAPI.proto /////////////// // arrayarray.h // // Artificial C-API for Python's type, // used by array.pxd // // last changes: 2009-05-15 rk // 2012-05-02 andreasvc // (see revision control) // #ifndef _ARRAYARRAY_H #define _ARRAYARRAY_H // These two forward declarations are explicitly handled in the type // declaration code, as including them here is too late for cython-defined // types to use them. // struct arrayobject; // typedef struct arrayobject arrayobject; // All possible arraydescr values are defined in the vector "descriptors" // below. That's defined later because the appropriate get and set // functions aren't visible yet. typedef struct arraydescr { int typecode; int itemsize; PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); #if PY_MAJOR_VERSION >= 3 char *formats; #endif } arraydescr; struct arrayobject { PyObject_HEAD Py_ssize_t ob_size; union { char *ob_item; float *as_floats; double *as_doubles; int *as_ints; unsigned int *as_uints; unsigned char *as_uchars; signed char *as_schars; char *as_chars; unsigned long *as_ulongs; long *as_longs; #if PY_MAJOR_VERSION >= 3 unsigned long long *as_ulonglongs; long long *as_longlongs; #endif short *as_shorts; unsigned short *as_ushorts; Py_UNICODE *as_pyunicodes; void *as_voidptr; } data; Py_ssize_t allocated; struct arraydescr *ob_descr; PyObject *weakreflist; /* List of weak references */ #if PY_MAJOR_VERSION >= 3 int ob_exports; /* Number of exported buffers */ #endif }; #ifndef NO_NEWARRAY_INLINE // fast creation of a new array static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr) { arrayobject *op; size_t nbytes; if (size < 0) { PyErr_BadInternalCall(); return NULL; } nbytes = size * descr->itemsize; // Check for overflow if (nbytes / descr->itemsize != (size_t)size) { return PyErr_NoMemory(); } op = (arrayobject *) type->tp_alloc(type, 0); if (op == NULL) { return NULL; } op->ob_descr = descr; op->allocated = size; op->weakreflist = NULL; op->ob_size = size; if (size <= 0) { op->data.ob_item = NULL; } else { op->data.ob_item = PyMem_NEW(char, nbytes); if (op->data.ob_item == NULL) { Py_DECREF(op); return PyErr_NoMemory(); } } return (PyObject *) op; } #else PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr); #endif /* ifndef NO_NEWARRAY_INLINE */ // fast resize (reallocation to the point) // not designed for filing small increments (but for fast opaque array apps) static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) { void *items = (void*) self->data.ob_item; PyMem_Resize(items, char, (size_t)(n * self->ob_descr->itemsize)); if (items == NULL) { PyErr_NoMemory(); return -1; } self->data.ob_item = (char*) items; self->ob_size = n; self->allocated = n; return 0; } // suitable for small increments; over allocation 50% ; static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) { void *items = (void*) self->data.ob_item; Py_ssize_t newsize; if (n < self->allocated && n*4 > self->allocated) { self->ob_size = n; return 0; } newsize = n + (n / 2) + 1; if (newsize <= n) { /* overflow */ PyErr_NoMemory(); return -1; } PyMem_Resize(items, char, (size_t)(newsize * self->ob_descr->itemsize)); if (items == NULL) { PyErr_NoMemory(); return -1; } self->data.ob_item = (char*) items; self->ob_size = n; self->allocated = newsize; return 0; } #endif /* _ARRAYARRAY_H */