summaryrefslogtreecommitdiff
path: root/Modules/mmapmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/mmapmodule.c')
-rw-r--r--Modules/mmapmodule.c154
1 files changed, 152 insertions, 2 deletions
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 16a9dd23e4..f3727e35c5 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -660,6 +660,60 @@ mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
}
static PyObject *
+mmap_subscript(mmap_object *self, PyObject *item)
+{
+ CHECK_VALID(NULL);
+ if (PyIndex_Check(item)) {
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ if (i < 0)
+ i += self->size;
+ if (i < 0 || i > self->size) {
+ PyErr_SetString(PyExc_IndexError,
+ "mmap index out of range");
+ return NULL;
+ }
+ return PyBytes_FromStringAndSize(self->data + i, 1);
+ }
+ else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelen;
+
+ if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
+ &start, &stop, &step, &slicelen) < 0) {
+ return NULL;
+ }
+
+ if (slicelen <= 0)
+ return PyBytes_FromStringAndSize("", 0);
+ else if (step == 1)
+ return PyBytes_FromStringAndSize(self->data + start,
+ slicelen);
+ else {
+ char *result_buf = (char *)PyMem_Malloc(slicelen);
+ Py_ssize_t cur, i;
+ PyObject *result;
+
+ if (result_buf == NULL)
+ return PyErr_NoMemory();
+ for (cur = start, i = 0; i < slicelen;
+ cur += step, i++) {
+ result_buf[i] = self->data[cur];
+ }
+ result = PyBytes_FromStringAndSize(result_buf,
+ slicelen);
+ PyMem_Free(result_buf);
+ return result;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "mmap indices must be integers");
+ return NULL;
+ }
+}
+
+static PyObject *
mmap_concat(mmap_object *self, PyObject *bb)
{
CHECK_VALID(NULL);
@@ -733,7 +787,7 @@ mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
}
if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) {
PyErr_SetString(PyExc_IndexError,
- "mmap assignment must be single-character string");
+ "mmap assignment must be length-1 bytes()");
return -1;
}
if (!is_writeable(self))
@@ -743,6 +797,96 @@ mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
return 0;
}
+static int
+mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
+{
+ CHECK_VALID(-1);
+
+ if (PyIndex_Check(item)) {
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+ const char *buf;
+
+ if (i == -1 && PyErr_Occurred())
+ return -1;
+ if (i < 0)
+ i += self->size;
+ if (i < 0 || i > self->size) {
+ PyErr_SetString(PyExc_IndexError,
+ "mmap index out of range");
+ return -1;
+ }
+ if (value == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "mmap object doesn't support item deletion");
+ return -1;
+ }
+ if (!PyBytes_Check(value) || PyBytes_Size(value) != 1) {
+ PyErr_SetString(PyExc_IndexError,
+ "mmap assignment must be length-1 bytes()");
+ return -1;
+ }
+ if (!is_writeable(self))
+ return -1;
+ buf = PyBytes_AsString(value);
+ self->data[i] = buf[0];
+ return 0;
+ }
+ else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelen;
+
+ if (PySlice_GetIndicesEx((PySliceObject *)item,
+ self->size, &start, &stop,
+ &step, &slicelen) < 0) {
+ return -1;
+ }
+ if (value == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "mmap object doesn't support slice deletion");
+ return -1;
+ }
+ if (!PyBytes_Check(value)) {
+ PyErr_SetString(PyExc_IndexError,
+ "mmap slice assignment must be bytes");
+ return -1;
+ }
+ if (PyBytes_Size(value) != slicelen) {
+ PyErr_SetString(PyExc_IndexError,
+ "mmap slice assignment is wrong size");
+ return -1;
+ }
+ if (!is_writeable(self))
+ return -1;
+
+ if (slicelen == 0)
+ return 0;
+ else if (step == 1) {
+ const char *buf = PyBytes_AsString(value);
+
+ if (buf == NULL)
+ return -1;
+ memcpy(self->data + start, buf, slicelen);
+ return 0;
+ }
+ else {
+ Py_ssize_t cur, i;
+ const char *buf = PyBytes_AsString(value);
+
+ if (buf == NULL)
+ return -1;
+ for (cur = start, i = 0; i < slicelen;
+ cur += step, i++) {
+ self->data[cur] = buf[i];
+ }
+ return 0;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "mmap indices must be integer");
+ return -1;
+ }
+}
+
static PySequenceMethods mmap_as_sequence = {
(lenfunc)mmap_length, /*sq_length*/
(binaryfunc)mmap_concat, /*sq_concat*/
@@ -753,6 +897,12 @@ static PySequenceMethods mmap_as_sequence = {
(ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
};
+static PyMappingMethods mmap_as_mapping = {
+ (lenfunc)mmap_length,
+ (binaryfunc)mmap_subscript,
+ (objobjargproc)mmap_ass_subscript,
+};
+
static PyBufferProcs mmap_as_buffer = {
(getbufferproc)mmap_buffer_getbuf,
(releasebufferproc)mmap_buffer_releasebuf,
@@ -772,7 +922,7 @@ static PyTypeObject mmap_object_type = {
0, /* tp_repr */
0, /* tp_as_number */
&mmap_as_sequence, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
+ &mmap_as_mapping, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/