[Python-checkins] r68028 - sandbox/trunk/io-c/_textio.c

amaury.forgeotdarc python-checkins at python.org
Mon Dec 29 22:15:04 CET 2008


Author: amaury.forgeotdarc
Date: Mon Dec 29 22:15:03 2008
New Revision: 68028

Log:
implement TextIOWrapper.seek.
This one was almost fun to translate.


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 22:15:03 2008
@@ -1050,7 +1050,7 @@
     return 0;
 }
 
-static int
+static PyObject *
 TextIOWrapper_buildCookie(CookieStruct *cookie, PyObject *cookieObj)
 {
     char buffer[sizeof(CookieStruct)];
@@ -1088,7 +1088,7 @@
 static PyObject *
 TextIOWrapper_seek(PyTextIOWrapperObject *self, PyObject *args)
 {
-    PyObject *cookie;
+    PyObject *cookieObj;
     int whence = 0;
     static PyObject *zero = NULL;
     PyObject *res;
@@ -1100,53 +1100,55 @@
             return NULL;
     }
 
-    if (!PyArg_ParseTuple(args, "O|i:seek", &cookie, &whence))
+    if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence))
         return NULL;
+    Py_INCREF(cookieObj);
 
     if (_PyIOBase_checkClosed((PyObject *)self, NULL) == NULL)
-        return NULL;
+        goto fail;
 
     if (!self->seekable) {
-        PyErr_SetString(PyExc_IOError, 
+        PyErr_SetString(PyExc_IOError,
                         "underlying stream is not seekable");
-        return NULL;
+        goto fail;
     }
 
     if (whence == 1) {
         /* seek relative to current position */
-        cmp = PyObject_RichCompareBool(cookie, zero, Py_EQ);
+        cmp = PyObject_RichCompareBool(cookieObj, zero, Py_EQ);
         if (cmp < 0)
-            return NULL;
+	    goto fail;
 
         if (cmp == 0) {
-            PyErr_SetString(PyExc_IOError, 
+            PyErr_SetString(PyExc_IOError,
                             "can't do nonzero cur-relative seeks");
-            return NULL;
+	    goto fail;
         }
 
         /* 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);
+	Py_DECREF(cookieObj);
+        cookieObj = PyObject_CallMethod((PyObject *)self, "tell", NULL);
+	if (cookieObj == NULL)
+	    goto fail;
     }
     else if (whence == 2) {
         /* seek relative to end of file */
 
-        cmp = PyObject_RichCompareBool(cookie, zero, Py_EQ);
+        cmp = PyObject_RichCompareBool(cookieObj, zero, Py_EQ);
         if (cmp < 0)
-            return NULL;
+	    goto fail;
 
         if (cmp == 0) {
-            PyErr_SetString(PyExc_IOError, 
+            PyErr_SetString(PyExc_IOError,
                             "can't do nonzero end-relative seeks");
-            return NULL;
+	    goto fail;
         }
 
         res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
         if (res == NULL)
-            return NULL;
+	    goto fail;
         Py_DECREF(res);
 
         TextIOWrapper_set_decoded_chars(self, NULL);
@@ -1154,7 +1156,7 @@
         if (self->decoder) {
             res = PyObject_CallMethod(self->decoder, "reset", NULL);
             if (res == NULL)
-                return NULL;
+		goto fail;
             Py_DECREF(res);
         }
 
@@ -1164,58 +1166,93 @@
     else if (whence != 0) {
         PyErr_Format(PyExc_ValueError,
                      "invalid whence (%d, should be 0, 1 or 2)", whence);
-        return NULL;
+	goto fail;
     }
 
-    cmp = PyObject_RichCompareBool(cookie, zero, Py_LT);
+    cmp = PyObject_RichCompareBool(cookieObj, zero, Py_LT);
     if (cmp < 0)
-        return NULL;
-    
+        goto fail;
+
     if (cmp == 1) {
         PyErr_Format(PyExc_ValueError,
-                     "negative seek position %R", cookie);
-        return NULL;
+                     "negative seek position %R", cookieObj);
+        goto fail;
     }
 
     res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
     if (res == NULL)
-        return NULL;
+        goto fail;
     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
+    {
+	CookieStruct cookie;
+
+	if (TextIOWrapper_parseCookie(&cookie, cookieObj) < 0)
+	    goto fail;
+
+        /* Seek back to the safe start point. */
+	res = PyObject_CallMethod(self->buffer, "seek",
+				  "L", (PY_LONG_LONG)cookie.start_pos);
+	if (res == NULL)
+	    goto fail;
+	Py_DECREF(res);
+
+	TextIOWrapper_set_decoded_chars(self, NULL);
+	Py_CLEAR(self->snapshot);
+
+        /* Restore the decoder to its state from the safe start point. */
+	if (self->decoder || cookie.dec_flags || cookie.chars_to_skip) {
+	    res = PyObject_CallMethod(self->decoder, "setstate",
+				      "((yi))", "", cookie.dec_flags);
+	    if (res == NULL)
+		goto fail;
+	    Py_DECREF(res);
+
+	    self->snapshot = Py_BuildValue("((iy))", cookie.dec_flags, "");
+	    if (self->snapshot == NULL)
+		goto fail;
+	}
+
+	if (cookie.chars_to_skip) {
+	    /* Just like _read_chunk, feed the decoder and save a snapshot. */
+	    PyObject *input_chunk = PyObject_CallMethod(
+		self->buffer, "read", "i", cookie.bytes_to_feed);
+	    PyObject *decoded;
+
+	    if (input_chunk == NULL)
+		goto fail;
+
+	    self->snapshot = Py_BuildValue("((iO))", cookie.dec_flags, input_chunk);
+	    if (self->snapshot == NULL) {
+		Py_DECREF(input_chunk);
+		goto fail;
+	    }
+
+	    decoded = PyObject_CallMethod(self->decoder, "decode",
+					  "Ni", input_chunk, (int)cookie.need_eof);
+
+	    if (decoded == NULL)
+		goto fail;
+
+	    TextIOWrapper_set_decoded_chars(self, decoded);
+
+	    /* Skip chars_to_skip of the decoded characters. */
+	    if (PyUnicode_GetSize(self->decoded_chars) < cookie.chars_to_skip) {
+		PyErr_SetString(PyExc_IOError, "can't restore logical file position");
+		goto fail;
+	    }
+            self->decoded_chars_used = cookie.chars_to_skip;
+	}
+    }
+
+    return cookieObj;
+  fail:
+    Py_XDECREF(cookieObj);
+    return NULL;
 
-        return cookie
-*/
-    
-    Py_RETURN_NONE;
 }
 
 
@@ -1321,7 +1358,7 @@
     {"writable", (PyCFunction)TextIOWrapper_writable, METH_NOARGS},
     {"isatty", (PyCFunction)TextIOWrapper_isatty, METH_NOARGS},
 
-/*    {"seek", (PyCFunction)TextIOWrapper_seek, METH_VARARGS},*/
+    {"seek", (PyCFunction)TextIOWrapper_seek, METH_VARARGS},
 /*    {"tell", (PyCFunction)TextIOWrapper_tell, METH_NOARGS},
     {"truncate", (PyCFunction)TextIOWrapper_truncate, METH_VARARGS},
     {"readinto", (PyCFunction)TextIOWrapper_readinto, METH_VARARGS},


More information about the Python-checkins mailing list