[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