from weakref import proxy
import array, io, math
from pickle import loads, dumps
+import operator
class ArraySubclass(array.array):
pass
def test_buffer(self):
a = array.array(self.typecode, self.example)
- b = bytes(memoryview(a))
+ m = memoryview(a)
+ b = bytes(m)
+ self.assertEqual(b, a.tostring())
self.assertEqual(b[0], a.tostring()[0])
+ # Resizing is forbidden when there are buffer exports
+ self.assertRaises(BufferError, a.append, a[0])
+ self.assertRaises(BufferError, a.extend, a[0:1])
+ self.assertRaises(BufferError, a.remove, a[0])
+ self.assertRaises(BufferError, a.fromlist, a.tolist())
+ self.assertRaises(BufferError, a.fromstring, a.tostring())
+ if self.typecode == 'u':
+ self.assertRaises(BufferError, a.fromunicode, a.tounicode())
+ self.assertRaises(BufferError, operator.setitem, a, slice(0, 0), a)
+ self.assertRaises(BufferError, operator.delitem, a, 0)
+ self.assertRaises(BufferError, operator.delitem, a, slice(0, 1))
+ self.assertRaises(BufferError, operator.irepeat, a, 2)
+ self.assertRaises(BufferError, operator.irepeat, a, 0)
def test_weakref(self):
s = array.array(self.typecode, self.example)
char *items;
size_t _new_size;
+ if (self->ob_exports > 0 && newsize != Py_SIZE(self)) {
+ PyErr_SetString(PyExc_BufferError,
+ "cannot resize an array that is exporting buffers");
+ return -1;
+ }
+
/* Bypass realloc() when a previous overallocation is large enough
to accommodate the newsize. If the newsize is 16 smaller than the
- current size, then proceed with the realloc() to shrink the list.
+ current size, then proceed with the realloc() to shrink the array.
*/
if (self->allocated >= newsize &&
return 0;
}
- if (self->ob_exports > 0) {
- PyErr_SetString(PyExc_BufferError,
- "cannot resize an array that is exporting data");
- return -1;
- }
+ if (newsize == 0) {
+ PyMem_FREE(self->ob_item);
+ self->ob_item = NULL;
+ Py_SIZE(self) = 0;
+ self->allocated = 0;
+ return 0;
+ }
/* This over-allocates proportional to the array size, making room
* for additional growth. The over-allocation is mild, but is
memmove(item + (ihigh+d)*a->ob_descr->itemsize,
item + ihigh*a->ob_descr->itemsize,
(Py_SIZE(a)-ihigh)*a->ob_descr->itemsize);
- Py_SIZE(a) += d;
- PyMem_RESIZE(item, char, Py_SIZE(a)*a->ob_descr->itemsize);
- /* Can't fail */
- a->ob_item = item;
- a->allocated = Py_SIZE(a);
+ if (array_resize(a, Py_SIZE(a) + d) == -1)
+ return -1;
}
else if (d > 0) { /* Insert d items */
- PyMem_RESIZE(item, char,
- (Py_SIZE(a) + d)*a->ob_descr->itemsize);
- if (item == NULL) {
- PyErr_NoMemory();
+ if (array_resize(a, Py_SIZE(a) + d))
return -1;
- }
memmove(item + (ihigh+d)*a->ob_descr->itemsize,
item + ihigh*a->ob_descr->itemsize,
(Py_SIZE(a)-ihigh)*a->ob_descr->itemsize);
- a->ob_item = item;
- Py_SIZE(a) += d;
- a->allocated = Py_SIZE(a);
}
if (n > 0)
memcpy(item + ilow*a->ob_descr->itemsize, b->ob_item,
static int
array_do_extend(arrayobject *self, PyObject *bb)
{
- Py_ssize_t size;
- char *old_item;
+ Py_ssize_t size, oldsize;
if (!array_Check(bb))
return array_iter_extend(self, bb);
PyErr_NoMemory();
return -1;
}
- size = Py_SIZE(self) + Py_SIZE(b);
- old_item = self->ob_item;
- PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize);
- if (self->ob_item == NULL) {
- self->ob_item = old_item;
- PyErr_NoMemory();
+ oldsize = Py_SIZE(self);
+ size = oldsize + Py_SIZE(b);
+ if (array_resize(self, size) == -1)
return -1;
- }
- memcpy(self->ob_item + Py_SIZE(self)*self->ob_descr->itemsize,
- b->ob_item, Py_SIZE(b)*b->ob_descr->itemsize);
- Py_SIZE(self) = size;
- self->allocated = size;
+ memcpy(self->ob_item + oldsize * self->ob_descr->itemsize,
+ b->ob_item, Py_SIZE(b) * b->ob_descr->itemsize);
return 0;
#undef b
return PyErr_NoMemory();
}
size = Py_SIZE(self) * self->ob_descr->itemsize;
- if (n == 0) {
- PyMem_FREE(items);
- self->ob_item = NULL;
- Py_SIZE(self) = 0;
- self->allocated = 0;
+ if (n > 0 && size > PY_SSIZE_T_MAX / n) {
+ return PyErr_NoMemory();
}
- else {
- if (size > PY_SSIZE_T_MAX / n) {
- return PyErr_NoMemory();
- }
- PyMem_RESIZE(items, char, n * size);
- if (items == NULL)
- return PyErr_NoMemory();
- p = items;
- for (i = 1; i < n; i++) {
- p += size;
- memcpy(p, items, size);
- }
- self->ob_item = items;
- Py_SIZE(self) *= n;
- self->allocated = Py_SIZE(self);
+ if (array_resize(self, n * Py_SIZE(self)) == -1)
+ return NULL;
+ items = p = self->ob_item;
+ for (i = 1; i < n; i++) {
+ p += size;
+ memcpy(p, items, size);
}
}
Py_INCREF(self);
array_fromlist(arrayobject *self, PyObject *list)
{
Py_ssize_t n;
- Py_ssize_t itemsize = self->ob_descr->itemsize;
if (!PyList_Check(list)) {
PyErr_SetString(PyExc_TypeError, "arg must be list");
}
n = PyList_Size(list);
if (n > 0) {
- char *item = self->ob_item;
- Py_ssize_t i;
- PyMem_RESIZE(item, char, (Py_SIZE(self) + n) * itemsize);
- if (item == NULL) {
- PyErr_NoMemory();
+ Py_ssize_t i, old_size;
+ old_size = Py_SIZE(self);
+ if (array_resize(self, old_size + n) == -1)
return NULL;
- }
- self->ob_item = item;
- Py_SIZE(self) += n;
- self->allocated = Py_SIZE(self);
for (i = 0; i < n; i++) {
PyObject *v = PyList_GetItem(list, i);
if ((*self->ob_descr->setitem)(self,
Py_SIZE(self) - n + i, v) != 0) {
- Py_SIZE(self) -= n;
- if (itemsize && (Py_SIZE(self) > PY_SSIZE_T_MAX / itemsize)) {
- return PyErr_NoMemory();
- }
- PyMem_RESIZE(item, char,
- Py_SIZE(self) * itemsize);
- self->ob_item = item;
- self->allocated = Py_SIZE(self);
+ array_resize(self, old_size);
return NULL;
}
}
}
n = n / itemsize;
if (n > 0) {
- char *item = self->ob_item;
- if ((n > PY_SSIZE_T_MAX - Py_SIZE(self)) ||
- ((Py_SIZE(self) + n) > PY_SSIZE_T_MAX / itemsize)) {
+ Py_ssize_t old_size = Py_SIZE(self);
+ if ((n > PY_SSIZE_T_MAX - old_size) ||
+ ((old_size + n) > PY_SSIZE_T_MAX / itemsize)) {
return PyErr_NoMemory();
}
- PyMem_RESIZE(item, char, (Py_SIZE(self) + n) * itemsize);
- if (item == NULL) {
- PyErr_NoMemory();
+ if (array_resize(self, old_size + n) == -1)
return NULL;
- }
- self->ob_item = item;
- Py_SIZE(self) += n;
- self->allocated = Py_SIZE(self);
- memcpy(item + (Py_SIZE(self) - n) * itemsize,
- str, itemsize*n);
+ memcpy(self->ob_item + old_size * itemsize,
+ str, n * itemsize);
}
Py_INCREF(Py_None);
return Py_None;
return NULL;
}
if (n > 0) {
- Py_UNICODE *item = (Py_UNICODE *) self->ob_item;
- if (Py_SIZE(self) > PY_SSIZE_T_MAX - n) {
- return PyErr_NoMemory();
- }
- PyMem_RESIZE(item, Py_UNICODE, Py_SIZE(self) + n);
- if (item == NULL) {
- PyErr_NoMemory();
+ Py_ssize_t old_size = Py_SIZE(self);
+ if (array_resize(self, old_size + n) == -1)
return NULL;
- }
- self->ob_item = (char *) item;
- Py_SIZE(self) += n;
- self->allocated = Py_SIZE(self);
- memcpy(item + Py_SIZE(self) - n,
+ memcpy(self->ob_item + old_size * sizeof(Py_UNICODE),
ustr, n * sizeof(Py_UNICODE));
}
self->ob_item + stop * itemsize,
(Py_SIZE(self) - stop) * itemsize);
if (array_resize(self, Py_SIZE(self) +
- needed - slicelength) < 0)
+ needed - slicelength) < 0)
return -1;
}
else if (slicelength < needed) {
if (array_resize(self, Py_SIZE(self) +
- needed - slicelength) < 0)
+ needed - slicelength) < 0)
return -1;
memmove(self->ob_item + (start + needed) * itemsize,
self->ob_item + stop * itemsize,