/* An implementation of Buffered I/O as defined by PEP 3116 - "New I/O" Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter, BufferedRandom. Written by Amaury Forgeot d'Arc and Antoine Pitrou */ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pyerrors.h" // _Py_FatalErrorFormat() #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "_iomodule.h" /*[clinic input] module _io class _io._BufferedIOBase "PyObject *" "clinic_state()->PyBufferedIOBase_Type" class _io._Buffered "buffered *" "clinic_state()->PyBufferedIOBase_Type" class _io.BufferedReader "buffered *" "clinic_state()->PyBufferedReader_Type" class _io.BufferedWriter "buffered *" "clinic_state()->PyBufferedWriter_Type" class _io.BufferedRWPair "rwpair *" "clinic_state()->PyBufferedRWPair_Type" class _io.BufferedRandom "buffered *" "clinic_state()->PyBufferedRandom_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3b3ef9cbbbad4590]*/ /* * BufferedIOBase class, inherits from IOBase. */ PyDoc_STRVAR(bufferediobase_doc, "Base class for buffered IO objects.\n" "\n" "The main difference with RawIOBase is that the read() method\n" "supports omitting the size argument, and does not have a default\n" "implementation that defers to readinto().\n" "\n" "In addition, read(), readinto() and write() may raise\n" "BlockingIOError if the underlying raw stream is in non-blocking\n" "mode and not ready; unlike their raw counterparts, they will never\n" "return None.\n" "\n" "A typical implementation should not inherit from a RawIOBase\n" "implementation, but wrap one.\n" ); static PyObject * _bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readinto1) { … } /*[clinic input] @critical_section _io._BufferedIOBase.readinto buffer: Py_buffer(accept={rwbuffer}) / [clinic start generated code]*/ static PyObject * _io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer) /*[clinic end generated code: output=8c8cda6684af8038 input=5273d20db7f56e1a]*/ { … } /*[clinic input] @critical_section _io._BufferedIOBase.readinto1 buffer: Py_buffer(accept={rwbuffer}) / [clinic start generated code]*/ static PyObject * _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer) /*[clinic end generated code: output=358623e4fd2b69d3 input=d6eb723dedcee654]*/ { … } static PyObject * bufferediobase_unsupported(_PyIO_State *state, const char *message) { … } /*[clinic input] _io._BufferedIOBase.detach cls: defining_class / Disconnect this buffer from its underlying raw stream and return it. After the raw stream has been detached, the buffer is in an unusable state. [clinic start generated code]*/ static PyObject * _io__BufferedIOBase_detach_impl(PyObject *self, PyTypeObject *cls) /*[clinic end generated code: output=b87b135d67cd4448 input=0b61a7b4357c1ea7]*/ { … } /*[clinic input] _io._BufferedIOBase.read cls: defining_class size: int(unused=True) = -1 / Read and return up to n bytes. If the size argument is omitted, None, or negative, read and return all data until EOF. If the size argument is positive, and the underlying raw stream is not 'interactive', multiple raw reads may be issued to satisfy the byte count (unless EOF is reached first). However, for interactive raw streams (as well as sockets and pipes), at most one raw read will be issued, and a short result does not imply that EOF is imminent. Return an empty bytes object on EOF. Return None if the underlying raw stream was open in non-blocking mode and no data is available at the moment. [clinic start generated code]*/ static PyObject * _io__BufferedIOBase_read_impl(PyObject *self, PyTypeObject *cls, int Py_UNUSED(size)) /*[clinic end generated code: output=aceb2765587b0a29 input=824f6f910465e61a]*/ { … } /*[clinic input] _io._BufferedIOBase.read1 cls: defining_class size: int(unused=True) = -1 / Read and return up to size bytes, with at most one read() call to the underlying raw stream. Return an empty bytes object on EOF. A short result does not imply that EOF is imminent. [clinic start generated code]*/ static PyObject * _io__BufferedIOBase_read1_impl(PyObject *self, PyTypeObject *cls, int Py_UNUSED(size)) /*[clinic end generated code: output=2e7fc62972487eaa input=af76380e020fd9e6]*/ { … } /*[clinic input] _io._BufferedIOBase.write cls: defining_class b: object(unused=True) / Write buffer b to the IO stream. Return the number of bytes written, which is always the length of b in bytes. Raise BlockingIOError if the buffer is full and the underlying raw stream cannot accept more data at the moment. [clinic start generated code]*/ static PyObject * _io__BufferedIOBase_write_impl(PyObject *self, PyTypeObject *cls, PyObject *Py_UNUSED(b)) /*[clinic end generated code: output=712c635246bf2306 input=9793f5c8f71029ad]*/ { … } buffered; /* Implementation notes: * BufferedReader, BufferedWriter and BufferedRandom try to share most methods (this is helped by the members `readable` and `writable`, which are initialized in the respective constructors) * They also share a single buffer for reading and writing. This enables interleaved reads and writes without flushing. It also makes the logic a bit trickier to get right. * The absolute position of the raw stream is cached, if possible, in the `abs_pos` member. It must be updated every time an operation is done on the raw stream. If not sure, it can be reinitialized by calling _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek() also does it). To read it, use RAW_TELL(). * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and _bufferedwriter_flush_unlocked do a lot of useful housekeeping. NOTE: we should try to maintain block alignment of reads and writes to the raw stream (according to the buffer size), but for now it is only done in read() and friends. */ /* These macros protect the buffered object against concurrent operations. */ static int _enter_buffered_busy(buffered *self) { … } #define ENTER_BUFFERED(self) … #define LEAVE_BUFFERED(self) … #define CHECK_INITIALIZED(self) … #define CHECK_INITIALIZED_INT(self) … #define IS_CLOSED(self) … #define CHECK_CLOSED(self, error_msg) … \ #define VALID_READ_BUFFER(self) … #define VALID_WRITE_BUFFER(self) … #define ADJUST_POSITION(self, _new_pos) … #define READAHEAD(self) … #define RAW_OFFSET(self) … #define RAW_TELL(self) … #define MINUS_LAST_BLOCK(self, size) … static int buffered_clear(buffered *self) { … } static void buffered_dealloc(buffered *self) { … } /*[clinic input] @critical_section _io._Buffered.__sizeof__ [clinic start generated code]*/ static PyObject * _io__Buffered___sizeof___impl(buffered *self) /*[clinic end generated code: output=0231ef7f5053134e input=07a32d578073ea64]*/ { … } static int buffered_traverse(buffered *self, visitproc visit, void *arg) { … } /* Because this can call arbitrary code, it shouldn't be called when the refcount is 0 (that is, not directly from tp_dealloc unless the refcount has been temporarily re-incremented). */ /*[clinic input] _io._Buffered._dealloc_warn source: object / [clinic start generated code]*/ static PyObject * _io__Buffered__dealloc_warn(buffered *self, PyObject *source) /*[clinic end generated code: output=690dcc3df8967162 input=8f845f2a4786391c]*/ { … } /* * _BufferedIOMixin methods * This is not a class, just a collection of methods that will be reused * by BufferedReader and BufferedWriter */ /* Flush and close */ /*[clinic input] @critical_section _io._Buffered.flush as _io__Buffered_simple_flush [clinic start generated code]*/ static PyObject * _io__Buffered_simple_flush_impl(buffered *self) /*[clinic end generated code: output=29ebb3820db1bdfd input=5248cb84a65f80bd]*/ { … } static int buffered_closed(buffered *self) { … } /*[clinic input] @critical_section @getter _io._Buffered.closed [clinic start generated code]*/ static PyObject * _io__Buffered_closed_get_impl(buffered *self) /*[clinic end generated code: output=f08ce57290703a1a input=18eddefdfe4a3d2f]*/ { … } /*[clinic input] @critical_section _io._Buffered.close [clinic start generated code]*/ static PyObject * _io__Buffered_close_impl(buffered *self) /*[clinic end generated code: output=7280b7b42033be0c input=56d95935b03fd326]*/ { … } /*[clinic input] @critical_section _io._Buffered.detach [clinic start generated code]*/ static PyObject * _io__Buffered_detach_impl(buffered *self) /*[clinic end generated code: output=dd0fc057b8b779f7 input=d4ef1828a678be37]*/ { … } /* Inquiries */ /*[clinic input] @critical_section _io._Buffered.seekable [clinic start generated code]*/ static PyObject * _io__Buffered_seekable_impl(buffered *self) /*[clinic end generated code: output=90172abb5ceb6e8f input=e3a4fc1d297b2fd3]*/ { … } /*[clinic input] @critical_section _io._Buffered.readable [clinic start generated code]*/ static PyObject * _io__Buffered_readable_impl(buffered *self) /*[clinic end generated code: output=92afa07661ecb698 input=abe54107d59bca9a]*/ { … } /*[clinic input] @critical_section _io._Buffered.writable [clinic start generated code]*/ static PyObject * _io__Buffered_writable_impl(buffered *self) /*[clinic end generated code: output=4e3eee8d6f9d8552 input=45eb76bf6a10e6f7]*/ { … } /*[clinic input] @critical_section @getter _io._Buffered.name [clinic start generated code]*/ static PyObject * _io__Buffered_name_get_impl(buffered *self) /*[clinic end generated code: output=d2adf384051d3d10 input=6b84a0e6126f545e]*/ { … } /*[clinic input] @critical_section @getter _io._Buffered.mode [clinic start generated code]*/ static PyObject * _io__Buffered_mode_get_impl(buffered *self) /*[clinic end generated code: output=0feb205748892fa4 input=0762d5e28542fd8c]*/ { … } /* Lower-level APIs */ /*[clinic input] @critical_section _io._Buffered.fileno [clinic start generated code]*/ static PyObject * _io__Buffered_fileno_impl(buffered *self) /*[clinic end generated code: output=b717648d58a95ee3 input=1c4fead777bae20a]*/ { … } /*[clinic input] @critical_section _io._Buffered.isatty [clinic start generated code]*/ static PyObject * _io__Buffered_isatty_impl(buffered *self) /*[clinic end generated code: output=c20e55caae67baea input=e53d182d7e490e3a]*/ { … } /* Forward decls */ static PyObject * _bufferedwriter_flush_unlocked(buffered *); static Py_ssize_t _bufferedreader_fill_buffer(buffered *self); static void _bufferedreader_reset_buf(buffered *self); static void _bufferedwriter_reset_buf(buffered *self); static PyObject * _bufferedreader_peek_unlocked(buffered *self); static PyObject * _bufferedreader_read_all(buffered *self); static PyObject * _bufferedreader_read_fast(buffered *self, Py_ssize_t); static PyObject * _bufferedreader_read_generic(buffered *self, Py_ssize_t); static Py_ssize_t _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len); /* * Helpers */ /* Sets the current error to BlockingIOError */ static void _set_BlockingIOError(const char *msg, Py_ssize_t written) { … } /* Returns the address of the `written` member if a BlockingIOError was raised, NULL otherwise. The error is always re-raised. */ static Py_ssize_t * _buffered_check_blocking_error(void) { … } static Py_off_t _buffered_raw_tell(buffered *self) { … } static Py_off_t _buffered_raw_seek(buffered *self, Py_off_t target, int whence) { … } static int _buffered_init(buffered *self) { … } /* Return 1 if an OSError with errno == EINTR is set (and then clears the error indicator), 0 otherwise. Should only be called when PyErr_Occurred() is true. */ int _PyIO_trap_eintr(void) { … } /* * Shared methods and wrappers */ static PyObject * buffered_flush_and_rewind_unlocked(buffered *self) { … } /*[clinic input] @critical_section _io._Buffered.flush [clinic start generated code]*/ static PyObject * _io__Buffered_flush_impl(buffered *self) /*[clinic end generated code: output=da2674ef1ce71f3a input=6b30de9f083419c2]*/ { … } /*[clinic input] @critical_section _io._Buffered.peek size: Py_ssize_t = 0 / [clinic start generated code]*/ static PyObject * _io__Buffered_peek_impl(buffered *self, Py_ssize_t size) /*[clinic end generated code: output=ba7a097ca230102b input=56733376f926d982]*/ { … } /*[clinic input] @critical_section _io._Buffered.read size as n: Py_ssize_t(accept={int, NoneType}) = -1 / [clinic start generated code]*/ static PyObject * _io__Buffered_read_impl(buffered *self, Py_ssize_t n) /*[clinic end generated code: output=f41c78bb15b9bbe9 input=bdb4b0425b295472]*/ { … } /*[clinic input] @critical_section _io._Buffered.read1 size as n: Py_ssize_t = -1 / [clinic start generated code]*/ static PyObject * _io__Buffered_read1_impl(buffered *self, Py_ssize_t n) /*[clinic end generated code: output=bcc4fb4e54d103a3 input=3d0ad241aa52b36c]*/ { … } static PyObject * _buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1) { … } /*[clinic input] @critical_section _io._Buffered.readinto buffer: Py_buffer(accept={rwbuffer}) / [clinic start generated code]*/ static PyObject * _io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer) /*[clinic end generated code: output=bcb376580b1d8170 input=777c33e7adaa2bcd]*/ { … } /*[clinic input] @critical_section _io._Buffered.readinto1 buffer: Py_buffer(accept={rwbuffer}) / [clinic start generated code]*/ static PyObject * _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer) /*[clinic end generated code: output=6e5c6ac5868205d6 input=ef03cc5fc92a6895]*/ { … } static PyObject * _buffered_readline(buffered *self, Py_ssize_t limit) { … } /*[clinic input] @critical_section _io._Buffered.readline size: Py_ssize_t(accept={int, NoneType}) = -1 / [clinic start generated code]*/ static PyObject * _io__Buffered_readline_impl(buffered *self, Py_ssize_t size) /*[clinic end generated code: output=24dd2aa6e33be83c input=e81ca5abd4280776]*/ { … } /*[clinic input] @critical_section _io._Buffered.tell [clinic start generated code]*/ static PyObject * _io__Buffered_tell_impl(buffered *self) /*[clinic end generated code: output=386972ae84716c1e input=ab12e67d8abcb42f]*/ { … } /*[clinic input] @critical_section _io._Buffered.seek target as targetobj: object whence: int = 0 / [clinic start generated code]*/ static PyObject * _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) /*[clinic end generated code: output=7ae0e8dc46efdefb input=b5a12be70e0ad07b]*/ { … } /*[clinic input] @critical_section _io._Buffered.truncate cls: defining_class pos: object = None / [clinic start generated code]*/ static PyObject * _io__Buffered_truncate_impl(buffered *self, PyTypeObject *cls, PyObject *pos) /*[clinic end generated code: output=fe3882fbffe79f1a input=e3cbf794575bd794]*/ { … } static PyObject * buffered_iternext(buffered *self) { … } static PyObject * buffered_repr(buffered *self) { … } /* * class BufferedReader */ static void _bufferedreader_reset_buf(buffered *self) { … } /*[clinic input] _io.BufferedReader.__init__ raw: object buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE Create a new buffered reader using the given readable raw IO object. [clinic start generated code]*/ static int _io_BufferedReader___init___impl(buffered *self, PyObject *raw, Py_ssize_t buffer_size) /*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/ { … } static Py_ssize_t _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len) { … } static Py_ssize_t _bufferedreader_fill_buffer(buffered *self) { … } static PyObject * _bufferedreader_read_all(buffered *self) { … } /* Read n bytes from the buffer if it can, otherwise return None. This function is simple enough that it can run unlocked. */ static PyObject * _bufferedreader_read_fast(buffered *self, Py_ssize_t n) { … } /* Generic read function: read from the stream until enough bytes are read, * or until an EOF occurs or until read() would block. */ static PyObject * _bufferedreader_read_generic(buffered *self, Py_ssize_t n) { … } static PyObject * _bufferedreader_peek_unlocked(buffered *self) { … } /* * class BufferedWriter */ static void _bufferedwriter_reset_buf(buffered *self) { … } /*[clinic input] _io.BufferedWriter.__init__ raw: object buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE A buffer for a writeable sequential RawIO object. The constructor creates a BufferedWriter for the given writeable raw stream. If the buffer_size is not given, it defaults to DEFAULT_BUFFER_SIZE. [clinic start generated code]*/ static int _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, Py_ssize_t buffer_size) /*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/ { … } static Py_ssize_t _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len) { … } static PyObject * _bufferedwriter_flush_unlocked(buffered *self) { … } /*[clinic input] @critical_section _io.BufferedWriter.write buffer: Py_buffer / [clinic start generated code]*/ static PyObject * _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer) /*[clinic end generated code: output=7f8d1365759bfc6b input=6a9c041de0c337be]*/ { … } /* * BufferedRWPair */ /* XXX The usefulness of this (compared to having two separate IO objects) is * questionable. */ rwpair; /*[clinic input] _io.BufferedRWPair.__init__ reader: object writer: object buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE / A buffered reader and writer object together. A buffered reader object and buffered writer object put together to form a sequential IO object that can read and write. This is typically used with a socket or two-way pipe. reader and writer are RawIOBase objects that are readable and writeable respectively. If the buffer_size is omitted it defaults to DEFAULT_BUFFER_SIZE. [clinic start generated code]*/ static int _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, PyObject *writer, Py_ssize_t buffer_size) /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/ { … } static int bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg) { … } static int bufferedrwpair_clear(rwpair *self) { … } static void bufferedrwpair_dealloc(rwpair *self) { … } static PyObject * _forward_call(buffered *self, PyObject *name, PyObject *args) { … } static PyObject * bufferedrwpair_read(rwpair *self, PyObject *args) { … } static PyObject * bufferedrwpair_peek(rwpair *self, PyObject *args) { … } static PyObject * bufferedrwpair_read1(rwpair *self, PyObject *args) { … } static PyObject * bufferedrwpair_readinto(rwpair *self, PyObject *args) { … } static PyObject * bufferedrwpair_readinto1(rwpair *self, PyObject *args) { … } static PyObject * bufferedrwpair_write(rwpair *self, PyObject *args) { … } static PyObject * bufferedrwpair_flush(rwpair *self, PyObject *Py_UNUSED(ignored)) { … } static PyObject * bufferedrwpair_readable(rwpair *self, PyObject *Py_UNUSED(ignored)) { … } static PyObject * bufferedrwpair_writable(rwpair *self, PyObject *Py_UNUSED(ignored)) { … } static PyObject * bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored)) { … } static PyObject * bufferedrwpair_isatty(rwpair *self, PyObject *Py_UNUSED(ignored)) { … } static PyObject * bufferedrwpair_closed_get(rwpair *self, void *context) { … } /* * BufferedRandom */ /*[clinic input] _io.BufferedRandom.__init__ raw: object buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE A buffered interface to random access streams. The constructor creates a reader and writer for a seekable stream, raw, given in the first argument. If the buffer_size is omitted it defaults to DEFAULT_BUFFER_SIZE. [clinic start generated code]*/ static int _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, Py_ssize_t buffer_size) /*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/ { … } #define clinic_state … #include "clinic/bufferedio.c.h" #undef clinic_state static PyMethodDef bufferediobase_methods[] = …; static PyType_Slot bufferediobase_slots[] = …; /* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */ PyType_Spec bufferediobase_spec = …; static PyMethodDef bufferedreader_methods[] = …; static PyMemberDef bufferedreader_members[] = …; static PyGetSetDef bufferedreader_getset[] = …; static PyType_Slot bufferedreader_slots[] = …; PyType_Spec bufferedreader_spec = …; static PyMethodDef bufferedwriter_methods[] = …; static PyMemberDef bufferedwriter_members[] = …; static PyGetSetDef bufferedwriter_getset[] = …; static PyType_Slot bufferedwriter_slots[] = …; PyType_Spec bufferedwriter_spec = …; static PyMethodDef bufferedrwpair_methods[] = …; static PyMemberDef bufferedrwpair_members[] = …; static PyGetSetDef bufferedrwpair_getset[] = …; static PyType_Slot bufferedrwpair_slots[] = …; PyType_Spec bufferedrwpair_spec = …; static PyMethodDef bufferedrandom_methods[] = …; static PyMemberDef bufferedrandom_members[] = …; static PyGetSetDef bufferedrandom_getset[] = …; static PyType_Slot bufferedrandom_slots[] = …; PyType_Spec bufferedrandom_spec = …;