[Python-checkins] r68005 - sandbox/trunk/io-c/_textio.c
amaury.forgeotdarc
python-checkins at python.org
Mon Dec 29 03:33:11 CET 2008
Author: amaury.forgeotdarc
Date: Mon Dec 29 03:33:11 2008
New Revision: 68005
Log:
Intermediate check-in of the seek() function.
Not enabled for now, but found a bug in the management of the 'snapshot' point.
Modified:
sandbox/trunk/io-c/_textio.c
Modified: sandbox/trunk/io-c/_textio.c
==============================================================================
--- sandbox/trunk/io-c/_textio.c (original)
+++ sandbox/trunk/io-c/_textio.c Mon Dec 29 03:33:11 2008
@@ -534,7 +534,12 @@
self->buffer = buffer;
Py_INCREF(buffer);
- /* self._seekable = self._telling = self.buffer.seekable(); */
+ res = PyObject_CallMethod(buffer, "seekable", NULL);
+ if (res == NULL)
+ goto error;
+ self->seekable = self->telling = PyObject_IsTrue(res);
+ Py_DECREF(res);
+
return 0;
error:
@@ -718,6 +723,8 @@
Py_DECREF(state);
return -1;
}
+ Py_INCREF(dec_buffer);
+ Py_INCREF(dec_flags);
Py_DECREF(state);
}
@@ -733,7 +740,6 @@
decoded_chars = PyObject_CallMethod(self->decoder, "decode",
"Oi", input_chunk, eof);
- Py_DECREF(input_chunk);
if (decoded_chars == NULL)
goto fail;
TextIOWrapper_set_decoded_chars(self, decoded_chars);
@@ -749,12 +755,14 @@
Py_CLEAR(self->snapshot);
self->snapshot = Py_BuildValue("NN", dec_flags, next_input);
}
+ Py_DECREF(input_chunk);
return (eof == 0);
fail:
Py_XDECREF(dec_buffer);
Py_XDECREF(dec_flags);
+ Py_XDECREF(input_chunk);
return -1;
}
@@ -965,6 +973,142 @@
return NULL;
}
+/* Seek and Tell */
+
+static PyObject *
+TextIOWrapper_seek(PyTextIOWrapperObject *self, PyObject *args)
+{
+ PyObject *cookie;
+ int whence = 0;
+ static PyObject *zero = NULL;
+ PyObject *res;
+ int cmp;
+
+ if (zero == NULL) {
+ zero = PyLong_FromLong(0L);
+ if (zero == NULL)
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(args, "O|i:seek", &cookie, &whence))
+ return NULL;
+
+ if (_PyIOBase_checkClosed((PyObject *)self, NULL) == NULL)
+ return NULL;
+
+ if (!self->seekable) {
+ PyErr_SetString(PyExc_IOError,
+ "underlying stream is not seekable");
+ return NULL;
+ }
+
+ if (whence == 1) {
+ /* seek relative to current position */
+ cmp = PyObject_RichCompareBool(cookie, zero, Py_EQ);
+ if (cmp < 0)
+ return NULL;
+
+ if (cmp == 0) {
+ PyErr_SetString(PyExc_IOError,
+ "can't do nonzero cur-relative seeks");
+ return NULL;
+ }
+
+ /* Seeking to the current position should attempt to
+ * sync the underlying buffer with the current position.
+ */
+ whence = 0;
+ Py_DECREF(cookie);
+ cookie = PyObject_CallMethod((PyObject *)self, "tell", NULL);
+ }
+ else if (whence == 2) {
+ /* seek relative to end of file */
+
+ cmp = PyObject_RichCompareBool(cookie, zero, Py_EQ);
+ if (cmp < 0)
+ return NULL;
+
+ if (cmp == 0) {
+ PyErr_SetString(PyExc_IOError,
+ "can't do nonzero end-relative seeks");
+ return NULL;
+ }
+
+ res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
+ if (res == NULL)
+ return NULL;
+ Py_DECREF(res);
+
+ TextIOWrapper_set_decoded_chars(self, NULL);
+ Py_CLEAR(self->snapshot);
+ if (self->decoder) {
+ res = PyObject_CallMethod(self->decoder, "reset", NULL);
+ if (res == NULL)
+ return NULL;
+ Py_DECREF(res);
+ }
+
+ res = PyObject_CallMethod(self->buffer, "seek", "ii", 0, 2);
+ return res;
+ }
+ else if (whence != 0) {
+ PyErr_Format(PyExc_ValueError,
+ "invalid whence (%d, should be 0, 1 or 2)", whence);
+ return NULL;
+ }
+
+ cmp = PyObject_RichCompareBool(cookie, zero, Py_LT);
+ if (cmp < 0)
+ return NULL;
+
+ if (cmp == 1) {
+ PyErr_Format(PyExc_ValueError,
+ "negative seek position %R", cookie);
+ return NULL;
+ }
+
+ res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
+ if (res == NULL)
+ return NULL;
+ Py_DECREF(res);
+
+ /* The strategy of seek() is to go back to the safe start point
+ * and replay the effect of read(chars_to_skip) from there.
+ */
+/*
+ start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \
+ self._unpack_cookie(cookie)
+
+ # Seek back to the safe start point.
+ self.buffer.seek(start_pos)
+ self._set_decoded_chars('')
+ self._snapshot = None
+
+ # Restore the decoder to its state from the safe start point.
+ if self._decoder or dec_flags or chars_to_skip:
+ self._decoder = self._decoder or self._get_decoder()
+ self._decoder.setstate((b'', dec_flags))
+ self._snapshot = (dec_flags, b'')
+
+ if chars_to_skip:
+ # Just like _read_chunk, feed the decoder and save a snapshot.
+ input_chunk = self.buffer.read(bytes_to_feed)
+ self._set_decoded_chars(
+ self._decoder.decode(input_chunk, need_eof))
+ self._snapshot = (dec_flags, input_chunk)
+
+ # Skip chars_to_skip of the decoded characters.
+ if len(self._decoded_chars) < chars_to_skip:
+ raise IOError("can't restore logical file position")
+ self._decoded_chars_used = chars_to_skip
+
+ return cookie
+*/
+
+ Py_RETURN_NONE;
+}
+
+
/* Inquiries */
static PyObject *
@@ -1067,8 +1211,8 @@
{"writable", (PyCFunction)TextIOWrapper_writable, METH_NOARGS},
{"isatty", (PyCFunction)TextIOWrapper_isatty, METH_NOARGS},
-/* {"seek", (PyCFunction)TextIOWrapper_seek, METH_VARARGS},
- {"tell", (PyCFunction)TextIOWrapper_tell, METH_NOARGS},
+/* {"seek", (PyCFunction)TextIOWrapper_seek, METH_VARARGS},*/
+/* {"tell", (PyCFunction)TextIOWrapper_tell, METH_NOARGS},
{"truncate", (PyCFunction)TextIOWrapper_truncate, METH_VARARGS},
{"readinto", (PyCFunction)TextIOWrapper_readinto, METH_VARARGS},
{"peek", (PyCFunction)TextIOWrapper_peek, METH_VARARGS},
More information about the Python-checkins
mailing list