| /* | 
 |     An implementation of the I/O abstract base classes hierarchy | 
 |     as defined by PEP 3116 - "New I/O" | 
 |  | 
 |     Classes defined here: IOBase, RawIOBase. | 
 |  | 
 |     Written by Amaury Forgeot d'Arc and Antoine Pitrou | 
 | */ | 
 |  | 
 |  | 
 | #define PY_SSIZE_T_CLEAN | 
 | #include "Python.h" | 
 | #include "pycore_long.h"          // _PyLong_GetOne() | 
 | #include "pycore_object.h" | 
 | #include <stddef.h>               // offsetof() | 
 | #include "_iomodule.h" | 
 |  | 
 | /*[clinic input] | 
 | module _io | 
 | class _io._IOBase "PyObject *" "&PyIOBase_Type" | 
 | class _io._RawIOBase "PyObject *" "&PyRawIOBase_Type" | 
 | [clinic start generated code]*/ | 
 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=d29a4d076c2b211c]*/ | 
 |  | 
 | /* | 
 |  * IOBase class, an abstract class | 
 |  */ | 
 |  | 
 | typedef struct { | 
 |     PyObject_HEAD | 
 |  | 
 |     PyObject *dict; | 
 |     PyObject *weakreflist; | 
 | } iobase; | 
 |  | 
 | PyDoc_STRVAR(iobase_doc, | 
 |     "The abstract base class for all I/O classes.\n" | 
 |     "\n" | 
 |     "This class provides dummy implementations for many methods that\n" | 
 |     "derived classes can override selectively; the default implementations\n" | 
 |     "represent a file that cannot be read, written or seeked.\n" | 
 |     "\n" | 
 |     "Even though IOBase does not declare read, readinto, or write because\n" | 
 |     "their signatures will vary, implementations and clients should\n" | 
 |     "consider those methods part of the interface. Also, implementations\n" | 
 |     "may raise UnsupportedOperation when operations they do not support are\n" | 
 |     "called.\n" | 
 |     "\n" | 
 |     "The basic type used for binary data read from or written to a file is\n" | 
 |     "bytes. Other bytes-like objects are accepted as method arguments too.\n" | 
 |     "In some cases (such as readinto), a writable object is required. Text\n" | 
 |     "I/O classes work with str data.\n" | 
 |     "\n" | 
 |     "Note that calling any method (except additional calls to close(),\n" | 
 |     "which are ignored) on a closed stream should raise a ValueError.\n" | 
 |     "\n" | 
 |     "IOBase (and its subclasses) support the iterator protocol, meaning\n" | 
 |     "that an IOBase object can be iterated over yielding the lines in a\n" | 
 |     "stream.\n" | 
 |     "\n" | 
 |     "IOBase also supports the :keyword:`with` statement. In this example,\n" | 
 |     "fp is closed after the suite of the with statement is complete:\n" | 
 |     "\n" | 
 |     "with open('spam.txt', 'r') as fp:\n" | 
 |     "    fp.write('Spam and eggs!')\n"); | 
 |  | 
 | /* Use this macro whenever you want to check the internal `closed` status | 
 |    of the IOBase object rather than the virtual `closed` attribute as returned | 
 |    by whatever subclass. */ | 
 |  | 
 |  | 
 | /* Internal methods */ | 
 | static PyObject * | 
 | iobase_unsupported(const char *message) | 
 | { | 
 |     _PyIO_State *state = IO_STATE(); | 
 |     if (state != NULL) | 
 |         PyErr_SetString(state->unsupported_operation, message); | 
 |     return NULL; | 
 | } | 
 |  | 
 | /* Positioning */ | 
 |  | 
 | PyDoc_STRVAR(iobase_seek_doc, | 
 |     "Change stream position.\n" | 
 |     "\n" | 
 |     "Change the stream position to the given byte offset. The offset is\n" | 
 |     "interpreted relative to the position indicated by whence.  Values\n" | 
 |     "for whence are:\n" | 
 |     "\n" | 
 |     "* 0 -- start of stream (the default); offset should be zero or positive\n" | 
 |     "* 1 -- current stream position; offset may be negative\n" | 
 |     "* 2 -- end of stream; offset is usually negative\n" | 
 |     "\n" | 
 |     "Return the new absolute position."); | 
 |  | 
 | static PyObject * | 
 | iobase_seek(PyObject *self, PyObject *args) | 
 | { | 
 |     return iobase_unsupported("seek"); | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.tell | 
 |  | 
 | Return current stream position. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_tell_impl(PyObject *self) | 
 | /*[clinic end generated code: output=89a1c0807935abe2 input=04e615fec128801f]*/ | 
 | { | 
 |     return _PyObject_CallMethod(self, &_Py_ID(seek), "ii", 0, 1); | 
 | } | 
 |  | 
 | PyDoc_STRVAR(iobase_truncate_doc, | 
 |     "Truncate file to size bytes.\n" | 
 |     "\n" | 
 |     "File pointer is left unchanged.  Size defaults to the current IO\n" | 
 |     "position as reported by tell().  Returns the new size."); | 
 |  | 
 | static PyObject * | 
 | iobase_truncate(PyObject *self, PyObject *args) | 
 | { | 
 |     return iobase_unsupported("truncate"); | 
 | } | 
 |  | 
 | static int | 
 | iobase_is_closed(PyObject *self) | 
 | { | 
 |     PyObject *res; | 
 |     int ret; | 
 |     /* This gets the derived attribute, which is *not* __IOBase_closed | 
 |        in most cases! */ | 
 |     ret = _PyObject_LookupAttr(self, &_Py_ID(__IOBase_closed), &res); | 
 |     Py_XDECREF(res); | 
 |     return ret; | 
 | } | 
 |  | 
 | /* Flush and close methods */ | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.flush | 
 |  | 
 | Flush write buffers, if applicable. | 
 |  | 
 | This is not implemented for read-only and non-blocking streams. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_flush_impl(PyObject *self) | 
 | /*[clinic end generated code: output=7cef4b4d54656a3b input=773be121abe270aa]*/ | 
 | { | 
 |     /* XXX Should this return the number of bytes written??? */ | 
 |     int closed = iobase_is_closed(self); | 
 |  | 
 |     if (!closed) { | 
 |         Py_RETURN_NONE; | 
 |     } | 
 |     if (closed > 0) { | 
 |         PyErr_SetString(PyExc_ValueError, "I/O operation on closed file."); | 
 |     } | 
 |     return NULL; | 
 | } | 
 |  | 
 | static PyObject * | 
 | iobase_closed_get(PyObject *self, void *context) | 
 | { | 
 |     int closed = iobase_is_closed(self); | 
 |     if (closed < 0) { | 
 |         return NULL; | 
 |     } | 
 |     return PyBool_FromLong(closed); | 
 | } | 
 |  | 
 | static int | 
 | iobase_check_closed(PyObject *self) | 
 | { | 
 |     PyObject *res; | 
 |     int closed; | 
 |     /* This gets the derived attribute, which is *not* __IOBase_closed | 
 |        in most cases! */ | 
 |     closed = _PyObject_LookupAttr(self, &_Py_ID(closed), &res); | 
 |     if (closed > 0) { | 
 |         closed = PyObject_IsTrue(res); | 
 |         Py_DECREF(res); | 
 |         if (closed > 0) { | 
 |             PyErr_SetString(PyExc_ValueError, "I/O operation on closed file."); | 
 |             return -1; | 
 |         } | 
 |     } | 
 |     return closed; | 
 | } | 
 |  | 
 | PyObject * | 
 | _PyIOBase_check_closed(PyObject *self, PyObject *args) | 
 | { | 
 |     if (iobase_check_closed(self)) { | 
 |         return NULL; | 
 |     } | 
 |     if (args == Py_True) { | 
 |         return Py_None; | 
 |     } | 
 |     Py_RETURN_NONE; | 
 | } | 
 |  | 
 | /* XXX: IOBase thinks it has to maintain its own internal state in | 
 |    `__IOBase_closed` and call flush() by itself, but it is redundant with | 
 |    whatever behaviour a non-trivial derived class will implement. */ | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.close | 
 |  | 
 | Flush and close the IO object. | 
 |  | 
 | This method has no effect if the file is already closed. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_close_impl(PyObject *self) | 
 | /*[clinic end generated code: output=63c6a6f57d783d6d input=f4494d5c31dbc6b7]*/ | 
 | { | 
 |     PyObject *res, *exc, *val, *tb; | 
 |     int rc, closed = iobase_is_closed(self); | 
 |  | 
 |     if (closed < 0) { | 
 |         return NULL; | 
 |     } | 
 |     if (closed) { | 
 |         Py_RETURN_NONE; | 
 |     } | 
 |  | 
 |     res = PyObject_CallMethodNoArgs(self, &_Py_ID(flush)); | 
 |  | 
 |     PyErr_Fetch(&exc, &val, &tb); | 
 |     rc = PyObject_SetAttr(self, &_Py_ID(__IOBase_closed), Py_True); | 
 |     _PyErr_ChainExceptions(exc, val, tb); | 
 |     if (rc < 0) { | 
 |         Py_CLEAR(res); | 
 |     } | 
 |  | 
 |     if (res == NULL) | 
 |         return NULL; | 
 |  | 
 |     Py_DECREF(res); | 
 |     Py_RETURN_NONE; | 
 | } | 
 |  | 
 | /* Finalization and garbage collection support */ | 
 |  | 
 | static void | 
 | iobase_finalize(PyObject *self) | 
 | { | 
 |     PyObject *res; | 
 |     PyObject *error_type, *error_value, *error_traceback; | 
 |     int closed; | 
 |  | 
 |     /* Save the current exception, if any. */ | 
 |     PyErr_Fetch(&error_type, &error_value, &error_traceback); | 
 |  | 
 |     /* If `closed` doesn't exist or can't be evaluated as bool, then the | 
 |        object is probably in an unusable state, so ignore. */ | 
 |     if (_PyObject_LookupAttr(self, &_Py_ID(closed), &res) <= 0) { | 
 |         PyErr_Clear(); | 
 |         closed = -1; | 
 |     } | 
 |     else { | 
 |         closed = PyObject_IsTrue(res); | 
 |         Py_DECREF(res); | 
 |         if (closed == -1) | 
 |             PyErr_Clear(); | 
 |     } | 
 |     if (closed == 0) { | 
 |         /* Signal close() that it was called as part of the object | 
 |            finalization process. */ | 
 |         if (PyObject_SetAttr(self, &_Py_ID(_finalizing), Py_True)) | 
 |             PyErr_Clear(); | 
 |         res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(close)); | 
 |         /* Silencing I/O errors is bad, but printing spurious tracebacks is | 
 |            equally as bad, and potentially more frequent (because of | 
 |            shutdown issues). */ | 
 |         if (res == NULL) { | 
 | #ifndef Py_DEBUG | 
 |             if (_Py_GetConfig()->dev_mode) { | 
 |                 PyErr_WriteUnraisable(self); | 
 |             } | 
 |             else { | 
 |                 PyErr_Clear(); | 
 |             } | 
 | #else | 
 |             PyErr_WriteUnraisable(self); | 
 | #endif | 
 |         } | 
 |         else { | 
 |             Py_DECREF(res); | 
 |         } | 
 |     } | 
 |  | 
 |     /* Restore the saved exception. */ | 
 |     PyErr_Restore(error_type, error_value, error_traceback); | 
 | } | 
 |  | 
 | int | 
 | _PyIOBase_finalize(PyObject *self) | 
 | { | 
 |     int is_zombie; | 
 |  | 
 |     /* If _PyIOBase_finalize() is called from a destructor, we need to | 
 |        resurrect the object as calling close() can invoke arbitrary code. */ | 
 |     is_zombie = (Py_REFCNT(self) == 0); | 
 |     if (is_zombie) | 
 |         return PyObject_CallFinalizerFromDealloc(self); | 
 |     else { | 
 |         PyObject_CallFinalizer(self); | 
 |         return 0; | 
 |     } | 
 | } | 
 |  | 
 | static int | 
 | iobase_traverse(iobase *self, visitproc visit, void *arg) | 
 | { | 
 |     Py_VISIT(self->dict); | 
 |     return 0; | 
 | } | 
 |  | 
 | static int | 
 | iobase_clear(iobase *self) | 
 | { | 
 |     Py_CLEAR(self->dict); | 
 |     return 0; | 
 | } | 
 |  | 
 | /* Destructor */ | 
 |  | 
 | static void | 
 | iobase_dealloc(iobase *self) | 
 | { | 
 |     /* NOTE: since IOBaseObject has its own dict, Python-defined attributes | 
 |        are still available here for close() to use. | 
 |        However, if the derived class declares a __slots__, those slots are | 
 |        already gone. | 
 |     */ | 
 |     if (_PyIOBase_finalize((PyObject *) self) < 0) { | 
 |         /* When called from a heap type's dealloc, the type will be | 
 |            decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ | 
 |         if (_PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) { | 
 |             Py_INCREF(Py_TYPE(self)); | 
 |         } | 
 |         return; | 
 |     } | 
 |     _PyObject_GC_UNTRACK(self); | 
 |     if (self->weakreflist != NULL) | 
 |         PyObject_ClearWeakRefs((PyObject *) self); | 
 |     Py_CLEAR(self->dict); | 
 |     Py_TYPE(self)->tp_free((PyObject *) self); | 
 | } | 
 |  | 
 | /* Inquiry methods */ | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.seekable | 
 |  | 
 | Return whether object supports random access. | 
 |  | 
 | If False, seek(), tell() and truncate() will raise OSError. | 
 | This method may need to do a test seek(). | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_seekable_impl(PyObject *self) | 
 | /*[clinic end generated code: output=4c24c67f5f32a43d input=b976622f7fdf3063]*/ | 
 | { | 
 |     Py_RETURN_FALSE; | 
 | } | 
 |  | 
 | PyObject * | 
 | _PyIOBase_check_seekable(PyObject *self, PyObject *args) | 
 | { | 
 |     PyObject *res  = PyObject_CallMethodNoArgs(self, &_Py_ID(seekable)); | 
 |     if (res == NULL) | 
 |         return NULL; | 
 |     if (res != Py_True) { | 
 |         Py_CLEAR(res); | 
 |         iobase_unsupported("File or stream is not seekable."); | 
 |         return NULL; | 
 |     } | 
 |     if (args == Py_True) { | 
 |         Py_DECREF(res); | 
 |     } | 
 |     return res; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.readable | 
 |  | 
 | Return whether object was opened for reading. | 
 |  | 
 | If False, read() will raise OSError. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_readable_impl(PyObject *self) | 
 | /*[clinic end generated code: output=e48089250686388b input=285b3b866a0ec35f]*/ | 
 | { | 
 |     Py_RETURN_FALSE; | 
 | } | 
 |  | 
 | /* May be called with any object */ | 
 | PyObject * | 
 | _PyIOBase_check_readable(PyObject *self, PyObject *args) | 
 | { | 
 |     PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(readable)); | 
 |     if (res == NULL) | 
 |         return NULL; | 
 |     if (res != Py_True) { | 
 |         Py_CLEAR(res); | 
 |         iobase_unsupported("File or stream is not readable."); | 
 |         return NULL; | 
 |     } | 
 |     if (args == Py_True) { | 
 |         Py_DECREF(res); | 
 |     } | 
 |     return res; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.writable | 
 |  | 
 | Return whether object was opened for writing. | 
 |  | 
 | If False, write() will raise OSError. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_writable_impl(PyObject *self) | 
 | /*[clinic end generated code: output=406001d0985be14f input=9dcac18a013a05b5]*/ | 
 | { | 
 |     Py_RETURN_FALSE; | 
 | } | 
 |  | 
 | /* May be called with any object */ | 
 | PyObject * | 
 | _PyIOBase_check_writable(PyObject *self, PyObject *args) | 
 | { | 
 |     PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(writable)); | 
 |     if (res == NULL) | 
 |         return NULL; | 
 |     if (res != Py_True) { | 
 |         Py_CLEAR(res); | 
 |         iobase_unsupported("File or stream is not writable."); | 
 |         return NULL; | 
 |     } | 
 |     if (args == Py_True) { | 
 |         Py_DECREF(res); | 
 |     } | 
 |     return res; | 
 | } | 
 |  | 
 | /* Context manager */ | 
 |  | 
 | static PyObject * | 
 | iobase_enter(PyObject *self, PyObject *args) | 
 | { | 
 |     if (iobase_check_closed(self)) | 
 |         return NULL; | 
 |  | 
 |     Py_INCREF(self); | 
 |     return self; | 
 | } | 
 |  | 
 | static PyObject * | 
 | iobase_exit(PyObject *self, PyObject *args) | 
 | { | 
 |     return PyObject_CallMethodNoArgs(self, &_Py_ID(close)); | 
 | } | 
 |  | 
 | /* Lower-level APIs */ | 
 |  | 
 | /* XXX Should these be present even if unimplemented? */ | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.fileno | 
 |  | 
 | Returns underlying file descriptor if one exists. | 
 |  | 
 | OSError is raised if the IO object does not use a file descriptor. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_fileno_impl(PyObject *self) | 
 | /*[clinic end generated code: output=7cc0973f0f5f3b73 input=4e37028947dc1cc8]*/ | 
 | { | 
 |     return iobase_unsupported("fileno"); | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.isatty | 
 |  | 
 | Return whether this is an 'interactive' stream. | 
 |  | 
 | Return False if it can't be determined. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_isatty_impl(PyObject *self) | 
 | /*[clinic end generated code: output=60cab77cede41cdd input=9ef76530d368458b]*/ | 
 | { | 
 |     if (iobase_check_closed(self)) | 
 |         return NULL; | 
 |     Py_RETURN_FALSE; | 
 | } | 
 |  | 
 | /* Readline(s) and writelines */ | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.readline | 
 |     size as limit: Py_ssize_t(accept={int, NoneType}) = -1 | 
 |     / | 
 |  | 
 | Read and return a line from the stream. | 
 |  | 
 | If size is specified, at most size bytes will be read. | 
 |  | 
 | The line terminator is always b'\n' for binary files; for text | 
 | files, the newlines argument to open can be used to select the line | 
 | terminator(s) recognized. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit) | 
 | /*[clinic end generated code: output=4479f79b58187840 input=d0c596794e877bff]*/ | 
 | { | 
 |     /* For backwards compatibility, a (slowish) readline(). */ | 
 |  | 
 |     PyObject *peek, *buffer, *result; | 
 |     Py_ssize_t old_size = -1; | 
 |  | 
 |     if (_PyObject_LookupAttr(self, &_Py_ID(peek), &peek) < 0) { | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     buffer = PyByteArray_FromStringAndSize(NULL, 0); | 
 |     if (buffer == NULL) { | 
 |         Py_XDECREF(peek); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     while (limit < 0 || PyByteArray_GET_SIZE(buffer) < limit) { | 
 |         Py_ssize_t nreadahead = 1; | 
 |         PyObject *b; | 
 |  | 
 |         if (peek != NULL) { | 
 |             PyObject *readahead = PyObject_CallOneArg(peek, _PyLong_GetOne()); | 
 |             if (readahead == NULL) { | 
 |                 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() | 
 |                    when EINTR occurs so we needn't do it ourselves. */ | 
 |                 if (_PyIO_trap_eintr()) { | 
 |                     continue; | 
 |                 } | 
 |                 goto fail; | 
 |             } | 
 |             if (!PyBytes_Check(readahead)) { | 
 |                 PyErr_Format(PyExc_OSError, | 
 |                              "peek() should have returned a bytes object, " | 
 |                              "not '%.200s'", Py_TYPE(readahead)->tp_name); | 
 |                 Py_DECREF(readahead); | 
 |                 goto fail; | 
 |             } | 
 |             if (PyBytes_GET_SIZE(readahead) > 0) { | 
 |                 Py_ssize_t n = 0; | 
 |                 const char *buf = PyBytes_AS_STRING(readahead); | 
 |                 if (limit >= 0) { | 
 |                     do { | 
 |                         if (n >= PyBytes_GET_SIZE(readahead) || n >= limit) | 
 |                             break; | 
 |                         if (buf[n++] == '\n') | 
 |                             break; | 
 |                     } while (1); | 
 |                 } | 
 |                 else { | 
 |                     do { | 
 |                         if (n >= PyBytes_GET_SIZE(readahead)) | 
 |                             break; | 
 |                         if (buf[n++] == '\n') | 
 |                             break; | 
 |                     } while (1); | 
 |                 } | 
 |                 nreadahead = n; | 
 |             } | 
 |             Py_DECREF(readahead); | 
 |         } | 
 |  | 
 |         b = _PyObject_CallMethod(self, &_Py_ID(read), "n", nreadahead); | 
 |         if (b == NULL) { | 
 |             /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() | 
 |                when EINTR occurs so we needn't do it ourselves. */ | 
 |             if (_PyIO_trap_eintr()) { | 
 |                 continue; | 
 |             } | 
 |             goto fail; | 
 |         } | 
 |         if (!PyBytes_Check(b)) { | 
 |             PyErr_Format(PyExc_OSError, | 
 |                          "read() should have returned a bytes object, " | 
 |                          "not '%.200s'", Py_TYPE(b)->tp_name); | 
 |             Py_DECREF(b); | 
 |             goto fail; | 
 |         } | 
 |         if (PyBytes_GET_SIZE(b) == 0) { | 
 |             Py_DECREF(b); | 
 |             break; | 
 |         } | 
 |  | 
 |         old_size = PyByteArray_GET_SIZE(buffer); | 
 |         if (PyByteArray_Resize(buffer, old_size + PyBytes_GET_SIZE(b)) < 0) { | 
 |             Py_DECREF(b); | 
 |             goto fail; | 
 |         } | 
 |         memcpy(PyByteArray_AS_STRING(buffer) + old_size, | 
 |                PyBytes_AS_STRING(b), PyBytes_GET_SIZE(b)); | 
 |  | 
 |         Py_DECREF(b); | 
 |  | 
 |         if (PyByteArray_AS_STRING(buffer)[PyByteArray_GET_SIZE(buffer) - 1] == '\n') | 
 |             break; | 
 |     } | 
 |  | 
 |     result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(buffer), | 
 |                                        PyByteArray_GET_SIZE(buffer)); | 
 |     Py_XDECREF(peek); | 
 |     Py_DECREF(buffer); | 
 |     return result; | 
 |   fail: | 
 |     Py_XDECREF(peek); | 
 |     Py_DECREF(buffer); | 
 |     return NULL; | 
 | } | 
 |  | 
 | static PyObject * | 
 | iobase_iter(PyObject *self) | 
 | { | 
 |     if (iobase_check_closed(self)) | 
 |         return NULL; | 
 |  | 
 |     Py_INCREF(self); | 
 |     return self; | 
 | } | 
 |  | 
 | static PyObject * | 
 | iobase_iternext(PyObject *self) | 
 | { | 
 |     PyObject *line = PyObject_CallMethodNoArgs(self, &_Py_ID(readline)); | 
 |  | 
 |     if (line == NULL) | 
 |         return NULL; | 
 |  | 
 |     if (PyObject_Size(line) <= 0) { | 
 |         /* Error or empty */ | 
 |         Py_DECREF(line); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     return line; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.readlines | 
 |     hint: Py_ssize_t(accept={int, NoneType}) = -1 | 
 |     / | 
 |  | 
 | Return a list of lines from the stream. | 
 |  | 
 | hint can be specified to control the number of lines read: no more | 
 | lines will be read if the total size (in bytes/characters) of all | 
 | lines so far exceeds hint. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint) | 
 | /*[clinic end generated code: output=2f50421677fa3dea input=9400c786ea9dc416]*/ | 
 | { | 
 |     Py_ssize_t length = 0; | 
 |     PyObject *result, *it = NULL; | 
 |  | 
 |     result = PyList_New(0); | 
 |     if (result == NULL) | 
 |         return NULL; | 
 |  | 
 |     if (hint <= 0) { | 
 |         /* XXX special-casing this made sense in the Python version in order | 
 |            to remove the bytecode interpretation overhead, but it could | 
 |            probably be removed here. */ | 
 |         PyObject *ret = PyObject_CallMethodObjArgs(result, &_Py_ID(extend), | 
 |                                                    self, NULL); | 
 |         if (ret == NULL) { | 
 |             goto error; | 
 |         } | 
 |         Py_DECREF(ret); | 
 |         return result; | 
 |     } | 
 |  | 
 |     it = PyObject_GetIter(self); | 
 |     if (it == NULL) { | 
 |         goto error; | 
 |     } | 
 |  | 
 |     while (1) { | 
 |         Py_ssize_t line_length; | 
 |         PyObject *line = PyIter_Next(it); | 
 |         if (line == NULL) { | 
 |             if (PyErr_Occurred()) { | 
 |                 goto error; | 
 |             } | 
 |             else | 
 |                 break; /* StopIteration raised */ | 
 |         } | 
 |  | 
 |         if (PyList_Append(result, line) < 0) { | 
 |             Py_DECREF(line); | 
 |             goto error; | 
 |         } | 
 |         line_length = PyObject_Size(line); | 
 |         Py_DECREF(line); | 
 |         if (line_length < 0) { | 
 |             goto error; | 
 |         } | 
 |         if (line_length > hint - length) | 
 |             break; | 
 |         length += line_length; | 
 |     } | 
 |  | 
 |     Py_DECREF(it); | 
 |     return result; | 
 |  | 
 |  error: | 
 |     Py_XDECREF(it); | 
 |     Py_DECREF(result); | 
 |     return NULL; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | _io._IOBase.writelines | 
 |     lines: object | 
 |     / | 
 |  | 
 | Write a list of lines to stream. | 
 |  | 
 | Line separators are not added, so it is usual for each of the | 
 | lines provided to have a line separator at the end. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__IOBase_writelines(PyObject *self, PyObject *lines) | 
 | /*[clinic end generated code: output=976eb0a9b60a6628 input=cac3fc8864183359]*/ | 
 | { | 
 |     PyObject *iter, *res; | 
 |  | 
 |     if (iobase_check_closed(self)) | 
 |         return NULL; | 
 |  | 
 |     iter = PyObject_GetIter(lines); | 
 |     if (iter == NULL) | 
 |         return NULL; | 
 |  | 
 |     while (1) { | 
 |         PyObject *line = PyIter_Next(iter); | 
 |         if (line == NULL) { | 
 |             if (PyErr_Occurred()) { | 
 |                 Py_DECREF(iter); | 
 |                 return NULL; | 
 |             } | 
 |             else | 
 |                 break; /* Stop Iteration */ | 
 |         } | 
 |  | 
 |         res = NULL; | 
 |         do { | 
 |             res = PyObject_CallMethodObjArgs(self, &_Py_ID(write), line, NULL); | 
 |         } while (res == NULL && _PyIO_trap_eintr()); | 
 |         Py_DECREF(line); | 
 |         if (res == NULL) { | 
 |             Py_DECREF(iter); | 
 |             return NULL; | 
 |         } | 
 |         Py_DECREF(res); | 
 |     } | 
 |     Py_DECREF(iter); | 
 |     Py_RETURN_NONE; | 
 | } | 
 |  | 
 | #include "clinic/iobase.c.h" | 
 |  | 
 | static PyMethodDef iobase_methods[] = { | 
 |     {"seek", iobase_seek, METH_VARARGS, iobase_seek_doc}, | 
 |     _IO__IOBASE_TELL_METHODDEF | 
 |     {"truncate", iobase_truncate, METH_VARARGS, iobase_truncate_doc}, | 
 |     _IO__IOBASE_FLUSH_METHODDEF | 
 |     _IO__IOBASE_CLOSE_METHODDEF | 
 |  | 
 |     _IO__IOBASE_SEEKABLE_METHODDEF | 
 |     _IO__IOBASE_READABLE_METHODDEF | 
 |     _IO__IOBASE_WRITABLE_METHODDEF | 
 |  | 
 |     {"_checkClosed",   _PyIOBase_check_closed, METH_NOARGS}, | 
 |     {"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS}, | 
 |     {"_checkReadable", _PyIOBase_check_readable, METH_NOARGS}, | 
 |     {"_checkWritable", _PyIOBase_check_writable, METH_NOARGS}, | 
 |  | 
 |     _IO__IOBASE_FILENO_METHODDEF | 
 |     _IO__IOBASE_ISATTY_METHODDEF | 
 |  | 
 |     {"__enter__", iobase_enter, METH_NOARGS}, | 
 |     {"__exit__", iobase_exit, METH_VARARGS}, | 
 |  | 
 |     _IO__IOBASE_READLINE_METHODDEF | 
 |     _IO__IOBASE_READLINES_METHODDEF | 
 |     _IO__IOBASE_WRITELINES_METHODDEF | 
 |  | 
 |     {NULL, NULL} | 
 | }; | 
 |  | 
 | static PyGetSetDef iobase_getset[] = { | 
 |     {"__dict__", PyObject_GenericGetDict, NULL, NULL}, | 
 |     {"closed", (getter)iobase_closed_get, NULL, NULL}, | 
 |     {NULL} | 
 | }; | 
 |  | 
 |  | 
 | PyTypeObject PyIOBase_Type = { | 
 |     PyVarObject_HEAD_INIT(NULL, 0) | 
 |     "_io._IOBase",              /*tp_name*/ | 
 |     sizeof(iobase),             /*tp_basicsize*/ | 
 |     0,                          /*tp_itemsize*/ | 
 |     (destructor)iobase_dealloc, /*tp_dealloc*/ | 
 |     0,                          /*tp_vectorcall_offset*/ | 
 |     0,                          /*tp_getattr*/ | 
 |     0,                          /*tp_setattr*/ | 
 |     0,                          /*tp_as_async*/ | 
 |     0,                          /*tp_repr*/ | 
 |     0,                          /*tp_as_number*/ | 
 |     0,                          /*tp_as_sequence*/ | 
 |     0,                          /*tp_as_mapping*/ | 
 |     0,                          /*tp_hash */ | 
 |     0,                          /*tp_call*/ | 
 |     0,                          /*tp_str*/ | 
 |     0,                          /*tp_getattro*/ | 
 |     0,                          /*tp_setattro*/ | 
 |     0,                          /*tp_as_buffer*/ | 
 |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
 |         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/ | 
 |     iobase_doc,                 /* tp_doc */ | 
 |     (traverseproc)iobase_traverse, /* tp_traverse */ | 
 |     (inquiry)iobase_clear,      /* tp_clear */ | 
 |     0,                          /* tp_richcompare */ | 
 |     offsetof(iobase, weakreflist), /* tp_weaklistoffset */ | 
 |     iobase_iter,                /* tp_iter */ | 
 |     iobase_iternext,            /* tp_iternext */ | 
 |     iobase_methods,             /* tp_methods */ | 
 |     0,                          /* tp_members */ | 
 |     iobase_getset,              /* tp_getset */ | 
 |     0,                          /* tp_base */ | 
 |     0,                          /* tp_dict */ | 
 |     0,                          /* tp_descr_get */ | 
 |     0,                          /* tp_descr_set */ | 
 |     offsetof(iobase, dict),     /* tp_dictoffset */ | 
 |     0,                          /* tp_init */ | 
 |     0,                          /* tp_alloc */ | 
 |     PyType_GenericNew,          /* tp_new */ | 
 |     0,                          /* tp_free */ | 
 |     0,                          /* tp_is_gc */ | 
 |     0,                          /* tp_bases */ | 
 |     0,                          /* tp_mro */ | 
 |     0,                          /* tp_cache */ | 
 |     0,                          /* tp_subclasses */ | 
 |     0,                          /* tp_weaklist */ | 
 |     0,                          /* tp_del */ | 
 |     0,                          /* tp_version_tag */ | 
 |     iobase_finalize,            /* tp_finalize */ | 
 | }; | 
 |  | 
 |  | 
 | /* | 
 |  * RawIOBase class, Inherits from IOBase. | 
 |  */ | 
 | PyDoc_STRVAR(rawiobase_doc, | 
 |              "Base class for raw binary I/O."); | 
 |  | 
 | /* | 
 |  * The read() method is implemented by calling readinto(); derived classes | 
 |  * that want to support read() only need to implement readinto() as a | 
 |  * primitive operation.  In general, readinto() can be more efficient than | 
 |  * read(). | 
 |  * | 
 |  * (It would be tempting to also provide an implementation of readinto() in | 
 |  * terms of read(), in case the latter is a more suitable primitive operation, | 
 |  * but that would lead to nasty recursion in case a subclass doesn't implement | 
 |  * either.) | 
 | */ | 
 |  | 
 | /*[clinic input] | 
 | _io._RawIOBase.read | 
 |     size as n: Py_ssize_t = -1 | 
 |     / | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n) | 
 | /*[clinic end generated code: output=6cdeb731e3c9f13c input=b6d0dcf6417d1374]*/ | 
 | { | 
 |     PyObject *b, *res; | 
 |  | 
 |     if (n < 0) { | 
 |         return PyObject_CallMethodNoArgs(self, &_Py_ID(readall)); | 
 |     } | 
 |  | 
 |     /* TODO: allocate a bytes object directly instead and manually construct | 
 |        a writable memoryview pointing to it. */ | 
 |     b = PyByteArray_FromStringAndSize(NULL, n); | 
 |     if (b == NULL) | 
 |         return NULL; | 
 |  | 
 |     res = PyObject_CallMethodObjArgs(self, &_Py_ID(readinto), b, NULL); | 
 |     if (res == NULL || res == Py_None) { | 
 |         Py_DECREF(b); | 
 |         return res; | 
 |     } | 
 |  | 
 |     n = PyNumber_AsSsize_t(res, PyExc_ValueError); | 
 |     Py_DECREF(res); | 
 |     if (n == -1 && PyErr_Occurred()) { | 
 |         Py_DECREF(b); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     res = PyBytes_FromStringAndSize(PyByteArray_AsString(b), n); | 
 |     Py_DECREF(b); | 
 |     return res; | 
 | } | 
 |  | 
 |  | 
 | /*[clinic input] | 
 | _io._RawIOBase.readall | 
 |  | 
 | Read until EOF, using multiple read() call. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | _io__RawIOBase_readall_impl(PyObject *self) | 
 | /*[clinic end generated code: output=1987b9ce929425a0 input=688874141213622a]*/ | 
 | { | 
 |     int r; | 
 |     PyObject *chunks = PyList_New(0); | 
 |     PyObject *result; | 
 |  | 
 |     if (chunks == NULL) | 
 |         return NULL; | 
 |  | 
 |     while (1) { | 
 |         PyObject *data = _PyObject_CallMethod(self, &_Py_ID(read), | 
 |                                               "i", DEFAULT_BUFFER_SIZE); | 
 |         if (!data) { | 
 |             /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() | 
 |                when EINTR occurs so we needn't do it ourselves. */ | 
 |             if (_PyIO_trap_eintr()) { | 
 |                 continue; | 
 |             } | 
 |             Py_DECREF(chunks); | 
 |             return NULL; | 
 |         } | 
 |         if (data == Py_None) { | 
 |             if (PyList_GET_SIZE(chunks) == 0) { | 
 |                 Py_DECREF(chunks); | 
 |                 return data; | 
 |             } | 
 |             Py_DECREF(data); | 
 |             break; | 
 |         } | 
 |         if (!PyBytes_Check(data)) { | 
 |             Py_DECREF(chunks); | 
 |             Py_DECREF(data); | 
 |             PyErr_SetString(PyExc_TypeError, "read() should return bytes"); | 
 |             return NULL; | 
 |         } | 
 |         if (PyBytes_GET_SIZE(data) == 0) { | 
 |             /* EOF */ | 
 |             Py_DECREF(data); | 
 |             break; | 
 |         } | 
 |         r = PyList_Append(chunks, data); | 
 |         Py_DECREF(data); | 
 |         if (r < 0) { | 
 |             Py_DECREF(chunks); | 
 |             return NULL; | 
 |         } | 
 |     } | 
 |     result = _PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks); | 
 |     Py_DECREF(chunks); | 
 |     return result; | 
 | } | 
 |  | 
 | static PyObject * | 
 | rawiobase_readinto(PyObject *self, PyObject *args) | 
 | { | 
 |     PyErr_SetNone(PyExc_NotImplementedError); | 
 |     return NULL; | 
 | } | 
 |  | 
 | static PyObject * | 
 | rawiobase_write(PyObject *self, PyObject *args) | 
 | { | 
 |     PyErr_SetNone(PyExc_NotImplementedError); | 
 |     return NULL; | 
 | } | 
 |  | 
 | static PyMethodDef rawiobase_methods[] = { | 
 |     _IO__RAWIOBASE_READ_METHODDEF | 
 |     _IO__RAWIOBASE_READALL_METHODDEF | 
 |     {"readinto", rawiobase_readinto, METH_VARARGS}, | 
 |     {"write", rawiobase_write, METH_VARARGS}, | 
 |     {NULL, NULL} | 
 | }; | 
 |  | 
 | PyTypeObject PyRawIOBase_Type = { | 
 |     PyVarObject_HEAD_INIT(NULL, 0) | 
 |     "_io._RawIOBase",                /*tp_name*/ | 
 |     0,                          /*tp_basicsize*/ | 
 |     0,                          /*tp_itemsize*/ | 
 |     0,                          /*tp_dealloc*/ | 
 |     0,                          /*tp_vectorcall_offset*/ | 
 |     0,                          /*tp_getattr*/ | 
 |     0,                          /*tp_setattr*/ | 
 |     0,                          /*tp_as_async*/ | 
 |     0,                          /*tp_repr*/ | 
 |     0,                          /*tp_as_number*/ | 
 |     0,                          /*tp_as_sequence*/ | 
 |     0,                          /*tp_as_mapping*/ | 
 |     0,                          /*tp_hash */ | 
 |     0,                          /*tp_call*/ | 
 |     0,                          /*tp_str*/ | 
 |     0,                          /*tp_getattro*/ | 
 |     0,                          /*tp_setattro*/ | 
 |     0,                          /*tp_as_buffer*/ | 
 |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/ | 
 |     rawiobase_doc,              /* tp_doc */ | 
 |     0,                          /* tp_traverse */ | 
 |     0,                          /* tp_clear */ | 
 |     0,                          /* tp_richcompare */ | 
 |     0,                          /* tp_weaklistoffset */ | 
 |     0,                          /* tp_iter */ | 
 |     0,                          /* tp_iternext */ | 
 |     rawiobase_methods,          /* tp_methods */ | 
 |     0,                          /* tp_members */ | 
 |     0,                          /* tp_getset */ | 
 |     &PyIOBase_Type,             /* tp_base */ | 
 |     0,                          /* tp_dict */ | 
 |     0,                          /* tp_descr_get */ | 
 |     0,                          /* tp_descr_set */ | 
 |     0,                          /* tp_dictoffset */ | 
 |     0,                          /* tp_init */ | 
 |     0,                          /* tp_alloc */ | 
 |     0,                          /* tp_new */ | 
 |     0,                          /* tp_free */ | 
 |     0,                          /* tp_is_gc */ | 
 |     0,                          /* tp_bases */ | 
 |     0,                          /* tp_mro */ | 
 |     0,                          /* tp_cache */ | 
 |     0,                          /* tp_subclasses */ | 
 |     0,                          /* tp_weaklist */ | 
 |     0,                          /* tp_del */ | 
 |     0,                          /* tp_version_tag */ | 
 |     0,                          /* tp_finalize */ | 
 | }; |