15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/////////////// ArrayAPI.proto ///////////////
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// arrayarray.h
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//    Artificial C-API for Python's <array.array> type,
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//    used by array.pxd
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//    last changes: 2009-05-15 rk
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//                  2012-05-02 andreasvc
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//                  (see revision control)
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef _ARRAYARRAY_H
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define _ARRAYARRAY_H
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// These two forward declarations are explicitly handled in the type
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// declaration code, as including them here is too late for cython-defined
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// types to use them.
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// struct arrayobject;
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// typedef struct arrayobject arrayobject;
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// All possible arraydescr values are defined in the vector "descriptors"
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// below.  That's defined later because the appropriate get and set
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// functions aren't visible yet.
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)typedef struct arraydescr {
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int typecode;
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int itemsize;
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PyObject * (*getitem)(struct arrayobject *, Py_ssize_t);
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if PY_VERSION_HEX >= 0x03000000
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    char *formats;
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} arraydescr;
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct arrayobject {
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PyObject_HEAD
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Py_ssize_t ob_size;
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    union {
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        char *ob_item;
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        float *as_floats;
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        double *as_doubles;
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        int *as_ints;
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        unsigned int *as_uints;
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        unsigned char *as_uchars;
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        signed char *as_schars;
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        char *as_chars;
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        unsigned long *as_ulongs;
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        long *as_longs;
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        short *as_shorts;
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        unsigned short *as_ushorts;
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Py_UNICODE *as_pyunicodes;
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        void *as_voidptr;
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } data;
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Py_ssize_t allocated;
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    struct arraydescr *ob_descr;
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PyObject *weakreflist; /* List of weak references */
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if PY_VERSION_HEX >= 0x03000000
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        int ob_exports;  /* Number of exported buffers */
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef NO_NEWARRAY_INLINE
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//  fast creation of a new array
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size,
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    struct arraydescr *descr) {
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    arrayobject *op;
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t nbytes;
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (size < 0) {
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        PyErr_BadInternalCall();
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return NULL;
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    nbytes = size * descr->itemsize;
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Check for overflow
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (nbytes / descr->itemsize != (size_t)size) {
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return PyErr_NoMemory();
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    op = (arrayobject *) type->tp_alloc(type, 0);
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (op == NULL) {
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return NULL;
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    op->ob_descr = descr;
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    op->allocated = size;
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    op->weakreflist = NULL;
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    op->ob_size = size;
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (size <= 0) {
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        op->data.ob_item = NULL;
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else {
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        op->data.ob_item = PyMem_NEW(char, nbytes);
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (op->data.ob_item == NULL) {
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            Py_DECREF(op);
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return PyErr_NoMemory();
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return (PyObject *) op;
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size,
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    struct arraydescr *descr);
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif /* ifndef NO_NEWARRAY_INLINE */
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// fast resize (reallocation to the point)
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// not designed for filing small increments (but for fast opaque array apps)
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    void *items = (void*) self->data.ob_item;
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PyMem_Resize(items, char, (size_t)(n * self->ob_descr->itemsize));
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (items == NULL) {
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        PyErr_NoMemory();
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return -1;
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    self->data.ob_item = (char*) items;
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    self->ob_size = n;
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    self->allocated = n;
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// suitable for small increments; over allocation 50% ;
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Remains non-smart in Python 2.3- ; but exists for compatibility
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    void *items = (void*) self->data.ob_item;
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Py_ssize_t newsize;
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (n < self->allocated) {
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (n*4 > self->allocated) {
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            self->ob_size = n;
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return 0;
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    newsize = n  * 3 / 2 + 1;
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PyMem_Resize(items, char, (size_t)(newsize * self->ob_descr->itemsize));
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (items == NULL) {
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        PyErr_NoMemory();
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return -1;
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    self->data.ob_item = (char*) items;
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    self->ob_size = n;
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    self->allocated = newsize;
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* _ARRAYARRAY_H */
145