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_VERSION_HEX >= 0x03000000 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 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 65 static 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 101 PyObject* 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) 107 static 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 122 static 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