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.
25 typedef 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_MAJOR_VERSION >= 3
31     char *formats;
32 #endif
33 } arraydescr;
34 
35 
36 struct 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 #if PY_MAJOR_VERSION >= 3
51         unsigned long long *as_ulonglongs;
52         long long *as_longlongs;
53 #endif
54         short *as_shorts;
55         unsigned short *as_ushorts;
56         Py_UNICODE *as_pyunicodes;
57         void *as_voidptr;
58     } data;
59     Py_ssize_t allocated;
60     struct arraydescr *ob_descr;
61     PyObject *weakreflist; /* List of weak references */
62 #if PY_MAJOR_VERSION >= 3
63         int ob_exports;  /* Number of exported buffers */
64 #endif
65 };
66 
67 #ifndef NO_NEWARRAY_INLINE
68 //  fast creation of a new array
newarrayobject(PyTypeObject * type,Py_ssize_t size,struct arraydescr * descr)69 static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size,
70     struct arraydescr *descr) {
71     arrayobject *op;
72     size_t nbytes;
73 
74     if (size < 0) {
75         PyErr_BadInternalCall();
76         return NULL;
77     }
78 
79     nbytes = size * descr->itemsize;
80     // Check for overflow
81     if (nbytes / descr->itemsize != (size_t)size) {
82         return PyErr_NoMemory();
83     }
84     op = (arrayobject *) type->tp_alloc(type, 0);
85     if (op == NULL) {
86         return NULL;
87     }
88     op->ob_descr = descr;
89     op->allocated = size;
90     op->weakreflist = NULL;
91     __Pyx_SET_SIZE(op, size);
92     if (size <= 0) {
93         op->data.ob_item = NULL;
94     }
95     else {
96         op->data.ob_item = PyMem_NEW(char, nbytes);
97         if (op->data.ob_item == NULL) {
98             Py_DECREF(op);
99             return PyErr_NoMemory();
100         }
101     }
102     return (PyObject *) op;
103 }
104 #else
105 PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size,
106     struct arraydescr *descr);
107 #endif /* ifndef NO_NEWARRAY_INLINE */
108 
109 // fast resize (reallocation to the point)
110 // not designed for filing small increments (but for fast opaque array apps)
resize(arrayobject * self,Py_ssize_t n)111 static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
112     void *items = (void*) self->data.ob_item;
113     PyMem_Resize(items, char, (size_t)(n * self->ob_descr->itemsize));
114     if (items == NULL) {
115         PyErr_NoMemory();
116         return -1;
117     }
118     self->data.ob_item = (char*) items;
119     __Pyx_SET_SIZE(self, n);
120     self->allocated = n;
121     return 0;
122 }
123 
124 // suitable for small increments; over allocation 50% ;
resize_smart(arrayobject * self,Py_ssize_t n)125 static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
126     void *items = (void*) self->data.ob_item;
127     Py_ssize_t newsize;
128     if (n < self->allocated && n*4 > self->allocated) {
129         __Pyx_SET_SIZE(self, n);
130         return 0;
131     }
132     newsize = n + (n / 2) + 1;
133     if (newsize <= n) {   /* overflow */
134         PyErr_NoMemory();
135         return -1;
136     }
137     PyMem_Resize(items, char, (size_t)(newsize * self->ob_descr->itemsize));
138     if (items == NULL) {
139         PyErr_NoMemory();
140         return -1;
141     }
142     self->data.ob_item = (char*) items;
143     __Pyx_SET_SIZE(self, n);
144     self->allocated = newsize;
145     return 0;
146 }
147 
148 #endif
149 /* _ARRAYARRAY_H */
150