Commit 577acb4e authored by Fred Drake's avatar Fred Drake

improve performance of writing past the end of the file for cStringIO

(http://bugs.python.org/issue10045)
parent 5e8349e5
...@@ -755,6 +755,7 @@ Peter Stoehr ...@@ -755,6 +755,7 @@ Peter Stoehr
Casper Stoel Casper Stoel
Michael Stone Michael Stone
Ken Stox Ken Stox
Patrick Strawderman
Dan Stromberg Dan Stromberg
Daniel Stutzbach Daniel Stutzbach
Nathan Sullivan Nathan Sullivan
......
...@@ -48,6 +48,9 @@ Core and Builtins ...@@ -48,6 +48,9 @@ Core and Builtins
Library Library
------- -------
- Issue #10045: Improved performance when writing after seeking past the
end of the "file" in cStringIO.
- Issue #9948: Fixed problem of losing filename case information. - Issue #9948: Fixed problem of losing filename case information.
- Issue #9437: Fix building C extensions with non-default LDFLAGS. - Issue #9437: Fix building C extensions with non-default LDFLAGS.
......
...@@ -339,12 +339,12 @@ IO_iternext(Iobject *self) ...@@ -339,12 +339,12 @@ IO_iternext(Iobject *self)
/* Read-write object methods */ /* Read-write object methods */
PyDoc_STRVAR(O_seek__doc__, PyDoc_STRVAR(IO_seek__doc__,
"seek(position) -- set the current position\n" "seek(position) -- set the current position\n"
"seek(position, mode) -- mode 0: absolute; 1: relative; 2: relative to EOF"); "seek(position, mode) -- mode 0: absolute; 1: relative; 2: relative to EOF");
static PyObject * static PyObject *
O_seek(Oobject *self, PyObject *args) { IO_seek(Iobject *self, PyObject *args) {
Py_ssize_t position; Py_ssize_t position;
int mode = 0; int mode = 0;
...@@ -359,25 +359,10 @@ O_seek(Oobject *self, PyObject *args) { ...@@ -359,25 +359,10 @@ O_seek(Oobject *self, PyObject *args) {
position += self->pos; position += self->pos;
} }
if (position > self->buf_size) { if (position < 0) position=0;
char *newbuf;
self->buf_size*=2;
if (self->buf_size <= position) self->buf_size=position+1;
newbuf = (char*) realloc(self->buf,self->buf_size);
if (!newbuf) {
free(self->buf);
self->buf = 0;
self->buf_size=self->pos=0;
return PyErr_NoMemory();
}
self->buf = newbuf;
}
else if (position < 0) position=0;
self->pos=position; self->pos=position;
while (--position >= self->string_size) self->buf[position]=0;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -414,6 +399,19 @@ O_cwrite(PyObject *self, const char *c, Py_ssize_t l) { ...@@ -414,6 +399,19 @@ O_cwrite(PyObject *self, const char *c, Py_ssize_t l) {
oself->buf = newbuf; oself->buf = newbuf;
} }
if (oself->string_size < oself->pos) {
/* In case of overseek, pad with null bytes the buffer region between
the end of stream and the current position.
0 lo string_size hi
| |<---used--->|<----------available----------->|
| | <--to pad-->|<---to write---> |
0 buf position
*/
memset(oself->buf + oself->string_size, '\0',
(oself->pos - oself->string_size) * sizeof(char));
}
memcpy(oself->buf+oself->pos,c,l); memcpy(oself->buf+oself->pos,c,l);
assert(oself->pos + l < INT_MAX); assert(oself->pos + l < INT_MAX);
...@@ -497,12 +495,12 @@ static struct PyMethodDef O_methods[] = { ...@@ -497,12 +495,12 @@ static struct PyMethodDef O_methods[] = {
{"readline", (PyCFunction)IO_readline, METH_VARARGS, IO_readline__doc__}, {"readline", (PyCFunction)IO_readline, METH_VARARGS, IO_readline__doc__},
{"readlines", (PyCFunction)IO_readlines,METH_VARARGS, IO_readlines__doc__}, {"readlines", (PyCFunction)IO_readlines,METH_VARARGS, IO_readlines__doc__},
{"reset", (PyCFunction)IO_reset, METH_NOARGS, IO_reset__doc__}, {"reset", (PyCFunction)IO_reset, METH_NOARGS, IO_reset__doc__},
{"seek", (PyCFunction)IO_seek, METH_VARARGS, IO_seek__doc__},
{"tell", (PyCFunction)IO_tell, METH_NOARGS, IO_tell__doc__}, {"tell", (PyCFunction)IO_tell, METH_NOARGS, IO_tell__doc__},
{"truncate", (PyCFunction)IO_truncate, METH_VARARGS, IO_truncate__doc__}, {"truncate", (PyCFunction)IO_truncate, METH_VARARGS, IO_truncate__doc__},
/* Read-write StringIO specific methods: */ /* Read-write StringIO specific methods: */
{"close", (PyCFunction)O_close, METH_NOARGS, O_close__doc__}, {"close", (PyCFunction)O_close, METH_NOARGS, O_close__doc__},
{"seek", (PyCFunction)O_seek, METH_VARARGS, O_seek__doc__},
{"write", (PyCFunction)O_write, METH_VARARGS, O_write__doc__}, {"write", (PyCFunction)O_write, METH_VARARGS, O_write__doc__},
{"writelines", (PyCFunction)O_writelines, METH_O, O_writelines__doc__}, {"writelines", (PyCFunction)O_writelines, METH_O, O_writelines__doc__},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
...@@ -595,26 +593,6 @@ I_close(Iobject *self, PyObject *unused) { ...@@ -595,26 +593,6 @@ I_close(Iobject *self, PyObject *unused) {
return Py_None; return Py_None;
} }
static PyObject *
I_seek(Iobject *self, PyObject *args) {
Py_ssize_t position;
int mode = 0;
if (!IO__opencheck(IOOOBJECT(self))) return NULL;
if (!PyArg_ParseTuple(args, "n|i:seek", &position, &mode))
return NULL;
if (mode == 2) position += self->string_size;
else if (mode == 1) position += self->pos;
if (position < 0) position=0;
self->pos=position;
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef I_methods[] = { static struct PyMethodDef I_methods[] = {
/* Common methods: */ /* Common methods: */
{"flush", (PyCFunction)IO_flush, METH_NOARGS, IO_flush__doc__}, {"flush", (PyCFunction)IO_flush, METH_NOARGS, IO_flush__doc__},
...@@ -624,12 +602,12 @@ static struct PyMethodDef I_methods[] = { ...@@ -624,12 +602,12 @@ static struct PyMethodDef I_methods[] = {
{"readline", (PyCFunction)IO_readline, METH_VARARGS, IO_readline__doc__}, {"readline", (PyCFunction)IO_readline, METH_VARARGS, IO_readline__doc__},
{"readlines", (PyCFunction)IO_readlines,METH_VARARGS, IO_readlines__doc__}, {"readlines", (PyCFunction)IO_readlines,METH_VARARGS, IO_readlines__doc__},
{"reset", (PyCFunction)IO_reset, METH_NOARGS, IO_reset__doc__}, {"reset", (PyCFunction)IO_reset, METH_NOARGS, IO_reset__doc__},
{"seek", (PyCFunction)IO_seek, METH_VARARGS, IO_seek__doc__},
{"tell", (PyCFunction)IO_tell, METH_NOARGS, IO_tell__doc__}, {"tell", (PyCFunction)IO_tell, METH_NOARGS, IO_tell__doc__},
{"truncate", (PyCFunction)IO_truncate, METH_VARARGS, IO_truncate__doc__}, {"truncate", (PyCFunction)IO_truncate, METH_VARARGS, IO_truncate__doc__},
/* Read-only StringIO specific methods: */ /* Read-only StringIO specific methods: */
{"close", (PyCFunction)I_close, METH_NOARGS, O_close__doc__}, {"close", (PyCFunction)I_close, METH_NOARGS, O_close__doc__},
{"seek", (PyCFunction)I_seek, METH_VARARGS, O_seek__doc__},
{NULL, NULL} {NULL, NULL}
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment