arrayarray.h 4.0 KB

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