1/////////////// ArrayAPI.proto ///////////////
2
3// arrayarray.h
4//
5//    Artificial C-API for Python's <array.array> type,
6//    used by array.pxd
7//
8//    last changes: 2009-05-15 rk
9//                  2012-05-02 andreasvc
10//                  (see revision control)
11//
12
13#ifndef _ARRAYARRAY_H
14#define _ARRAYARRAY_H
15
16// These two forward declarations are explicitly handled in the type
17// declaration code, as including them here is too late for cython-defined
18// types to use them.
19// struct arrayobject;
20// typedef struct arrayobject arrayobject;
21
22// All possible arraydescr values are defined in the vector "descriptors"
23// below.  That's defined later because the appropriate get and set
24// functions aren't visible yet.
25typedef struct arraydescr {
26    int typecode;
27    int itemsize;
28    PyObject * (*getitem)(struct arrayobject *, Py_ssize_t);
29    int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
30#if PY_VERSION_HEX >= 0x03000000
31    char *formats;
32#endif
33} arraydescr;
34
35
36struct arrayobject {
37    PyObject_HEAD
38    Py_ssize_t ob_size;
39    union {
40        char *ob_item;
41        float *as_floats;
42        double *as_doubles;
43        int *as_ints;
44        unsigned int *as_uints;
45        unsigned char *as_uchars;
46        signed char *as_schars;
47        char *as_chars;
48        unsigned long *as_ulongs;
49        long *as_longs;
50        short *as_shorts;
51        unsigned short *as_ushorts;
52        Py_UNICODE *as_pyunicodes;
53        void *as_voidptr;
54    } data;
55    Py_ssize_t allocated;
56    struct arraydescr *ob_descr;
57    PyObject *weakreflist; /* List of weak references */
58#if PY_VERSION_HEX >= 0x03000000
59        int ob_exports;  /* Number of exported buffers */
60#endif
61};
62
63#ifndef NO_NEWARRAY_INLINE
64//  fast creation of a new array
65static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size,
66    struct arraydescr *descr) {
67    arrayobject *op;
68    size_t nbytes;
69
70    if (size < 0) {
71        PyErr_BadInternalCall();
72        return NULL;
73    }
74
75    nbytes = size * descr->itemsize;
76    // Check for overflow
77    if (nbytes / descr->itemsize != (size_t)size) {
78        return PyErr_NoMemory();
79    }
80    op = (arrayobject *) type->tp_alloc(type, 0);
81    if (op == NULL) {
82        return NULL;
83    }
84    op->ob_descr = descr;
85    op->allocated = size;
86    op->weakreflist = NULL;
87    op->ob_size = size;
88    if (size <= 0) {
89        op->data.ob_item = NULL;
90    }
91    else {
92        op->data.ob_item = PyMem_NEW(char, nbytes);
93        if (op->data.ob_item == NULL) {
94            Py_DECREF(op);
95            return PyErr_NoMemory();
96        }
97    }
98    return (PyObject *) op;
99}
100#else
101PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size,
102    struct arraydescr *descr);
103#endif /* ifndef NO_NEWARRAY_INLINE */
104
105// fast resize (reallocation to the point)
106// not designed for filing small increments (but for fast opaque array apps)
107static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
108    void *items = (void*) self->data.ob_item;
109    PyMem_Resize(items, char, (size_t)(n * self->ob_descr->itemsize));
110    if (items == NULL) {
111        PyErr_NoMemory();
112        return -1;
113    }
114    self->data.ob_item = (char*) items;
115    self->ob_size = n;
116    self->allocated = n;
117    return 0;
118}
119
120// suitable for small increments; over allocation 50% ;
121// Remains non-smart in Python 2.3- ; but exists for compatibility
122static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
123    void *items = (void*) self->data.ob_item;
124    Py_ssize_t newsize;
125    if (n < self->allocated) {
126        if (n*4 > self->allocated) {
127            self->ob_size = n;
128            return 0;
129        }
130    }
131    newsize = n  * 3 / 2 + 1;
132    PyMem_Resize(items, char, (size_t)(newsize * self->ob_descr->itemsize));
133    if (items == NULL) {
134        PyErr_NoMemory();
135        return -1;
136    }
137    self->data.ob_item = (char*) items;
138    self->ob_size = n;
139    self->allocated = newsize;
140    return 0;
141}
142
143#endif
144/* _ARRAYARRAY_H */
145