Home | History | Annotate | Download | only in Utility
      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