150 lines
4.0 KiB
C
150 lines
4.0 KiB
C
|
/////////////// ArrayAPI.proto ///////////////
|
||
|
|
||
|
// arrayarray.h
|
||
|
//
|
||
|
// Artificial C-API for Python's <array.array> type,
|
||
|
// used by array.pxd
|
||
|
//
|
||
|
// last changes: 2009-05-15 rk
|
||
|
// 2012-05-02 andreasvc
|
||
|
// (see revision control)
|
||
|
//
|
||
|
|
||
|
#ifndef _ARRAYARRAY_H
|
||
|
#define _ARRAYARRAY_H
|
||
|
|
||
|
// These two forward declarations are explicitly handled in the type
|
||
|
// declaration code, as including them here is too late for cython-defined
|
||
|
// types to use them.
|
||
|
// struct arrayobject;
|
||
|
// typedef struct arrayobject arrayobject;
|
||
|
|
||
|
// All possible arraydescr values are defined in the vector "descriptors"
|
||
|
// below. That's defined later because the appropriate get and set
|
||
|
// functions aren't visible yet.
|
||
|
typedef struct arraydescr {
|
||
|
int typecode;
|
||
|
int itemsize;
|
||
|
PyObject * (*getitem)(struct arrayobject *, Py_ssize_t);
|
||
|
int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
|
||
|
#if PY_MAJOR_VERSION >= 3
|
||
|
char *formats;
|
||
|
#endif
|
||
|
} arraydescr;
|
||
|
|
||
|
|
||
|
struct arrayobject {
|
||
|
PyObject_HEAD
|
||
|
Py_ssize_t ob_size;
|
||
|
union {
|
||
|
char *ob_item;
|
||
|
float *as_floats;
|
||
|
double *as_doubles;
|
||
|
int *as_ints;
|
||
|
unsigned int *as_uints;
|
||
|
unsigned char *as_uchars;
|
||
|
signed char *as_schars;
|
||
|
char *as_chars;
|
||
|
unsigned long *as_ulongs;
|
||
|
long *as_longs;
|
||
|
#if PY_MAJOR_VERSION >= 3
|
||
|
unsigned long long *as_ulonglongs;
|
||
|
long long *as_longlongs;
|
||
|
#endif
|
||
|
short *as_shorts;
|
||
|
unsigned short *as_ushorts;
|
||
|
Py_UNICODE *as_pyunicodes;
|
||
|
void *as_voidptr;
|
||
|
} data;
|
||
|
Py_ssize_t allocated;
|
||
|
struct arraydescr *ob_descr;
|
||
|
PyObject *weakreflist; /* List of weak references */
|
||
|
#if PY_MAJOR_VERSION >= 3
|
||
|
int ob_exports; /* Number of exported buffers */
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
#ifndef NO_NEWARRAY_INLINE
|
||
|
// fast creation of a new array
|
||
|
static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size,
|
||
|
struct arraydescr *descr) {
|
||
|
arrayobject *op;
|
||
|
size_t nbytes;
|
||
|
|
||
|
if (size < 0) {
|
||
|
PyErr_BadInternalCall();
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
nbytes = size * descr->itemsize;
|
||
|
// Check for overflow
|
||
|
if (nbytes / descr->itemsize != (size_t)size) {
|
||
|
return PyErr_NoMemory();
|
||
|
}
|
||
|
op = (arrayobject *) type->tp_alloc(type, 0);
|
||
|
if (op == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
op->ob_descr = descr;
|
||
|
op->allocated = size;
|
||
|
op->weakreflist = NULL;
|
||
|
op->ob_size = size;
|
||
|
if (size <= 0) {
|
||
|
op->data.ob_item = NULL;
|
||
|
}
|
||
|
else {
|
||
|
op->data.ob_item = PyMem_NEW(char, nbytes);
|
||
|
if (op->data.ob_item == NULL) {
|
||
|
Py_DECREF(op);
|
||
|
return PyErr_NoMemory();
|
||
|
}
|
||
|
}
|
||
|
return (PyObject *) op;
|
||
|
}
|
||
|
#else
|
||
|
PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size,
|
||
|
struct arraydescr *descr);
|
||
|
#endif /* ifndef NO_NEWARRAY_INLINE */
|
||
|
|
||
|
// fast resize (reallocation to the point)
|
||
|
// not designed for filing small increments (but for fast opaque array apps)
|
||
|
static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
|
||
|
void *items = (void*) self->data.ob_item;
|
||
|
PyMem_Resize(items, char, (size_t)(n * self->ob_descr->itemsize));
|
||
|
if (items == NULL) {
|
||
|
PyErr_NoMemory();
|
||
|
return -1;
|
||
|
}
|
||
|
self->data.ob_item = (char*) items;
|
||
|
self->ob_size = n;
|
||
|
self->allocated = n;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// suitable for small increments; over allocation 50% ;
|
||
|
static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
|
||
|
void *items = (void*) self->data.ob_item;
|
||
|
Py_ssize_t newsize;
|
||
|
if (n < self->allocated && n*4 > self->allocated) {
|
||
|
self->ob_size = n;
|
||
|
return 0;
|
||
|
}
|
||
|
newsize = n + (n / 2) + 1;
|
||
|
if (newsize <= n) { /* overflow */
|
||
|
PyErr_NoMemory();
|
||
|
return -1;
|
||
|
}
|
||
|
PyMem_Resize(items, char, (size_t)(newsize * self->ob_descr->itemsize));
|
||
|
if (items == NULL) {
|
||
|
PyErr_NoMemory();
|
||
|
return -1;
|
||
|
}
|
||
|
self->data.ob_item = (char*) items;
|
||
|
self->ob_size = n;
|
||
|
self->allocated = newsize;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
/* _ARRAYARRAY_H */
|