Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions Modules/_io/_iomodule.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "pythread.h"

/*
* Declarations shared between the different parts of the io module
*/
Expand Down Expand Up @@ -183,3 +185,47 @@ extern PyObject *_PyIO_empty_str;
extern PyObject *_PyIO_empty_bytes;

extern PyTypeObject _PyBytesIOBuffer_Type;

typedef struct {
PyObject_HEAD

PyObject *raw;
int ok; /* Initialized? */
int detached;
int readable;
int writable;
char finalizing;

/* True if this is a vanilla Buffered object (rather than a user derived
class) *and* the raw stream is a vanilla FileIO object. */
int fast_closed_checks;

/* Absolute position inside the raw stream (-1 if unknown). */
Py_off_t abs_pos;

/* A static buffer of size `buffer_size` */
char *buffer;
/* Current logical position in the buffer. */
Py_off_t pos;
/* Position of the raw stream in the buffer. */
Py_off_t raw_pos;

/* Just after the last buffered byte in the buffer, or -1 if the buffer
isn't ready for reading. */
Py_off_t read_end;

/* Just after the last byte actually written */
Py_off_t write_pos;
/* Just after the last byte waiting to be written, or -1 if the buffer
isn't ready for writing. */
Py_off_t write_end;

PyThread_type_lock lock;
volatile unsigned long owner;

Py_ssize_t buffer_size;
Py_ssize_t buffer_mask;

PyObject *dict;
PyObject *weakreflist;
} _PyIO_buffered;
45 changes: 1 addition & 44 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "Python.h"
#include "internal/pystate.h"
#include "structmember.h"
#include "pythread.h"
#include "_iomodule.h"

/*[clinic input]
Expand Down Expand Up @@ -197,49 +196,7 @@ bufferediobase_write(PyObject *self, PyObject *args)
}


typedef struct {
PyObject_HEAD

PyObject *raw;
int ok; /* Initialized? */
int detached;
int readable;
int writable;
char finalizing;

/* True if this is a vanilla Buffered object (rather than a user derived
class) *and* the raw stream is a vanilla FileIO object. */
int fast_closed_checks;

/* Absolute position inside the raw stream (-1 if unknown). */
Py_off_t abs_pos;

/* A static buffer of size `buffer_size` */
char *buffer;
/* Current logical position in the buffer. */
Py_off_t pos;
/* Position of the raw stream in the buffer. */
Py_off_t raw_pos;

/* Just after the last buffered byte in the buffer, or -1 if the buffer
isn't ready for reading. */
Py_off_t read_end;

/* Just after the last byte actually written */
Py_off_t write_pos;
/* Just after the last byte waiting to be written, or -1 if the buffer
isn't ready for writing. */
Py_off_t write_end;

PyThread_type_lock lock;
volatile unsigned long owner;

Py_ssize_t buffer_size;
Py_ssize_t buffer_mask;

PyObject *dict;
PyObject *weakreflist;
} buffered;
typedef _PyIO_buffered buffered;

/*
Implementation notes:
Expand Down
29 changes: 21 additions & 8 deletions Modules/_io/textio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1075,21 +1075,31 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,

self->has_read1 = _PyObject_HasAttrId(buffer, &PyId_read1);

self->encoding_start_of_stream = 0;
if (self->seekable && self->encoder) {
PyObject *cookieObj;
int cmp;

self->encoding_start_of_stream = 1;

cookieObj = PyObject_CallMethodObjArgs(buffer, _PyIO_str_tell, NULL);
if (cookieObj == NULL)
goto error;
if (Py_TYPE(buffer) == &PyBufferedWriter_Type
|| Py_TYPE(buffer) == &PyBufferedRandom_Type) {
/* Fast-path for _io.BufferedWriter and _io.BufferedRandom:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about BufferedReader?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we only go into this path if self->encoder is set. self->encoder is only set if the buffer is writable.

read directly the private abs_pos attribute */
_PyIO_buffered *bw = (_PyIO_buffered *)buffer;
/* _buffered_init() sets abs_pos (if the file is seekable) */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if it's not seekable?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we only go into this path if self->seekable is set.

assert(bw->abs_pos >= 0);
cmp = (bw->abs_pos == 0);
}
else {
cookieObj = PyObject_CallMethodObjArgs(buffer, _PyIO_str_tell, NULL);
if (cookieObj == NULL)
goto error;

cmp = PyObject_RichCompareBool(cookieObj, _PyLong_Zero, Py_EQ);
Py_DECREF(cookieObj);
if (cmp < 0) {
goto error;
cmp = PyObject_RichCompareBool(cookieObj, _PyLong_Zero, Py_EQ);
Py_DECREF(cookieObj);
if (cmp < 0) {
goto error;
}
}

if (cmp == 0) {
Expand All @@ -1101,6 +1111,9 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
Py_DECREF(res);
}
}
else {
self->encoding_start_of_stream = 0;
}

self->ok = 1;
return 0;
Expand Down