Line data Source code
1 : /*
2 : An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
3 :
4 : Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 : BufferedRandom.
6 :
7 : Written by Amaury Forgeot d'Arc and Antoine Pitrou
8 : */
9 :
10 : #define PY_SSIZE_T_CLEAN
11 : #include "Python.h"
12 : #include "structmember.h"
13 : #include "pythread.h"
14 : #include "_iomodule.h"
15 :
16 : /*
17 : * BufferedIOBase class, inherits from IOBase.
18 : */
19 : PyDoc_STRVAR(bufferediobase_doc,
20 : "Base class for buffered IO objects.\n"
21 : "\n"
22 : "The main difference with RawIOBase is that the read() method\n"
23 : "supports omitting the size argument, and does not have a default\n"
24 : "implementation that defers to readinto().\n"
25 : "\n"
26 : "In addition, read(), readinto() and write() may raise\n"
27 : "BlockingIOError if the underlying raw stream is in non-blocking\n"
28 : "mode and not ready; unlike their raw counterparts, they will never\n"
29 : "return None.\n"
30 : "\n"
31 : "A typical implementation should not inherit from a RawIOBase\n"
32 : "implementation, but wrap one.\n"
33 : );
34 :
35 : static PyObject *
36 0 : bufferediobase_readinto(PyObject *self, PyObject *args)
37 : {
38 : Py_buffer buf;
39 : Py_ssize_t len;
40 : PyObject *data;
41 :
42 0 : if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
43 0 : return NULL;
44 : }
45 :
46 0 : data = PyObject_CallMethod(self, "read", "n", buf.len);
47 0 : if (data == NULL)
48 0 : goto error;
49 :
50 0 : if (!PyBytes_Check(data)) {
51 0 : Py_DECREF(data);
52 0 : PyErr_SetString(PyExc_TypeError, "read() should return bytes");
53 0 : goto error;
54 : }
55 :
56 0 : len = Py_SIZE(data);
57 0 : memcpy(buf.buf, PyBytes_AS_STRING(data), len);
58 :
59 0 : PyBuffer_Release(&buf);
60 0 : Py_DECREF(data);
61 :
62 0 : return PyLong_FromSsize_t(len);
63 :
64 : error:
65 0 : PyBuffer_Release(&buf);
66 0 : return NULL;
67 : }
68 :
69 : static PyObject *
70 0 : bufferediobase_unsupported(const char *message)
71 : {
72 0 : PyErr_SetString(_PyIO_unsupported_operation, message);
73 0 : return NULL;
74 : }
75 :
76 : PyDoc_STRVAR(bufferediobase_detach_doc,
77 : "Disconnect this buffer from its underlying raw stream and return it.\n"
78 : "\n"
79 : "After the raw stream has been detached, the buffer is in an unusable\n"
80 : "state.\n");
81 :
82 : static PyObject *
83 0 : bufferediobase_detach(PyObject *self)
84 : {
85 0 : return bufferediobase_unsupported("detach");
86 : }
87 :
88 : PyDoc_STRVAR(bufferediobase_read_doc,
89 : "Read and return up to n bytes.\n"
90 : "\n"
91 : "If the argument is omitted, None, or negative, reads and\n"
92 : "returns all data until EOF.\n"
93 : "\n"
94 : "If the argument is positive, and the underlying raw stream is\n"
95 : "not 'interactive', multiple raw reads may be issued to satisfy\n"
96 : "the byte count (unless EOF is reached first). But for\n"
97 : "interactive raw streams (as well as sockets and pipes), at most\n"
98 : "one raw read will be issued, and a short result does not imply\n"
99 : "that EOF is imminent.\n"
100 : "\n"
101 : "Returns an empty bytes object on EOF.\n"
102 : "\n"
103 : "Returns None if the underlying raw stream was open in non-blocking\n"
104 : "mode and no data is available at the moment.\n");
105 :
106 : static PyObject *
107 0 : bufferediobase_read(PyObject *self, PyObject *args)
108 : {
109 0 : return bufferediobase_unsupported("read");
110 : }
111 :
112 : PyDoc_STRVAR(bufferediobase_read1_doc,
113 : "Read and return up to n bytes, with at most one read() call\n"
114 : "to the underlying raw stream. A short result does not imply\n"
115 : "that EOF is imminent.\n"
116 : "\n"
117 : "Returns an empty bytes object on EOF.\n");
118 :
119 : static PyObject *
120 0 : bufferediobase_read1(PyObject *self, PyObject *args)
121 : {
122 0 : return bufferediobase_unsupported("read1");
123 : }
124 :
125 : PyDoc_STRVAR(bufferediobase_write_doc,
126 : "Write the given buffer to the IO stream.\n"
127 : "\n"
128 : "Returns the number of bytes written, which is always len(b).\n"
129 : "\n"
130 : "Raises BlockingIOError if the buffer is full and the\n"
131 : "underlying raw stream cannot accept more data at the moment.\n");
132 :
133 : static PyObject *
134 0 : bufferediobase_write(PyObject *self, PyObject *args)
135 : {
136 0 : return bufferediobase_unsupported("write");
137 : }
138 :
139 :
140 : static PyMethodDef bufferediobase_methods[] = {
141 : {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
142 : {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
143 : {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
144 : {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
145 : {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
146 : {NULL, NULL}
147 : };
148 :
149 : PyTypeObject PyBufferedIOBase_Type = {
150 : PyVarObject_HEAD_INIT(NULL, 0)
151 : "_io._BufferedIOBase", /*tp_name*/
152 : 0, /*tp_basicsize*/
153 : 0, /*tp_itemsize*/
154 : 0, /*tp_dealloc*/
155 : 0, /*tp_print*/
156 : 0, /*tp_getattr*/
157 : 0, /*tp_setattr*/
158 : 0, /*tp_compare */
159 : 0, /*tp_repr*/
160 : 0, /*tp_as_number*/
161 : 0, /*tp_as_sequence*/
162 : 0, /*tp_as_mapping*/
163 : 0, /*tp_hash */
164 : 0, /*tp_call*/
165 : 0, /*tp_str*/
166 : 0, /*tp_getattro*/
167 : 0, /*tp_setattro*/
168 : 0, /*tp_as_buffer*/
169 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
170 : bufferediobase_doc, /* tp_doc */
171 : 0, /* tp_traverse */
172 : 0, /* tp_clear */
173 : 0, /* tp_richcompare */
174 : 0, /* tp_weaklistoffset */
175 : 0, /* tp_iter */
176 : 0, /* tp_iternext */
177 : bufferediobase_methods, /* tp_methods */
178 : 0, /* tp_members */
179 : 0, /* tp_getset */
180 : &PyIOBase_Type, /* tp_base */
181 : 0, /* tp_dict */
182 : 0, /* tp_descr_get */
183 : 0, /* tp_descr_set */
184 : 0, /* tp_dictoffset */
185 : 0, /* tp_init */
186 : 0, /* tp_alloc */
187 : 0, /* tp_new */
188 : };
189 :
190 :
191 : typedef struct {
192 : PyObject_HEAD
193 :
194 : PyObject *raw;
195 : int ok; /* Initialized? */
196 : int detached;
197 : int readable;
198 : int writable;
199 :
200 : /* True if this is a vanilla Buffered object (rather than a user derived
201 : class) *and* the raw stream is a vanilla FileIO object. */
202 : int fast_closed_checks;
203 :
204 : /* Absolute position inside the raw stream (-1 if unknown). */
205 : Py_off_t abs_pos;
206 :
207 : /* A static buffer of size `buffer_size` */
208 : char *buffer;
209 : /* Current logical position in the buffer. */
210 : Py_off_t pos;
211 : /* Position of the raw stream in the buffer. */
212 : Py_off_t raw_pos;
213 :
214 : /* Just after the last buffered byte in the buffer, or -1 if the buffer
215 : isn't ready for reading. */
216 : Py_off_t read_end;
217 :
218 : /* Just after the last byte actually written */
219 : Py_off_t write_pos;
220 : /* Just after the last byte waiting to be written, or -1 if the buffer
221 : isn't ready for writing. */
222 : Py_off_t write_end;
223 :
224 : #ifdef WITH_THREAD
225 : PyThread_type_lock lock;
226 : volatile long owner;
227 : #endif
228 :
229 : Py_ssize_t buffer_size;
230 : Py_ssize_t buffer_mask;
231 :
232 : PyObject *dict;
233 : PyObject *weakreflist;
234 : } buffered;
235 :
236 : /*
237 : Implementation notes:
238 :
239 : * BufferedReader, BufferedWriter and BufferedRandom try to share most
240 : methods (this is helped by the members `readable` and `writable`, which
241 : are initialized in the respective constructors)
242 : * They also share a single buffer for reading and writing. This enables
243 : interleaved reads and writes without flushing. It also makes the logic
244 : a bit trickier to get right.
245 : * The absolute position of the raw stream is cached, if possible, in the
246 : `abs_pos` member. It must be updated every time an operation is done
247 : on the raw stream. If not sure, it can be reinitialized by calling
248 : _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
249 : also does it). To read it, use RAW_TELL().
250 : * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
251 : _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
252 :
253 : NOTE: we should try to maintain block alignment of reads and writes to the
254 : raw stream (according to the buffer size), but for now it is only done
255 : in read() and friends.
256 :
257 : */
258 :
259 : /* These macros protect the buffered object against concurrent operations. */
260 :
261 : #ifdef WITH_THREAD
262 :
263 : static int
264 : _enter_buffered_busy(buffered *self)
265 : {
266 : if (self->owner == PyThread_get_thread_ident()) {
267 : PyObject *r = PyObject_Repr((PyObject *) self);
268 : if (r != NULL) {
269 : PyErr_Format(PyExc_RuntimeError,
270 : "reentrant call inside %s",
271 : PyString_AS_STRING(r));
272 : Py_DECREF(r);
273 : }
274 : return 0;
275 : }
276 : Py_BEGIN_ALLOW_THREADS
277 : PyThread_acquire_lock(self->lock, 1);
278 : Py_END_ALLOW_THREADS
279 : return 1;
280 : }
281 :
282 : #define ENTER_BUFFERED(self) \
283 : ( (PyThread_acquire_lock(self->lock, 0) ? \
284 : 1 : _enter_buffered_busy(self)) \
285 : && (self->owner = PyThread_get_thread_ident(), 1) )
286 :
287 : #define LEAVE_BUFFERED(self) \
288 : do { \
289 : self->owner = 0; \
290 : PyThread_release_lock(self->lock); \
291 : } while(0);
292 :
293 : #else
294 : #define ENTER_BUFFERED(self) 1
295 : #define LEAVE_BUFFERED(self)
296 : #endif
297 :
298 : #define CHECK_INITIALIZED(self) \
299 : if (self->ok <= 0) { \
300 : if (self->detached) { \
301 : PyErr_SetString(PyExc_ValueError, \
302 : "raw stream has been detached"); \
303 : } else { \
304 : PyErr_SetString(PyExc_ValueError, \
305 : "I/O operation on uninitialized object"); \
306 : } \
307 : return NULL; \
308 : }
309 :
310 : #define CHECK_INITIALIZED_INT(self) \
311 : if (self->ok <= 0) { \
312 : if (self->detached) { \
313 : PyErr_SetString(PyExc_ValueError, \
314 : "raw stream has been detached"); \
315 : } else { \
316 : PyErr_SetString(PyExc_ValueError, \
317 : "I/O operation on uninitialized object"); \
318 : } \
319 : return -1; \
320 : }
321 :
322 : #define IS_CLOSED(self) \
323 : (self->fast_closed_checks \
324 : ? _PyFileIO_closed(self->raw) \
325 : : buffered_closed(self))
326 :
327 : #define CHECK_CLOSED(self, error_msg) \
328 : if (IS_CLOSED(self)) { \
329 : PyErr_SetString(PyExc_ValueError, error_msg); \
330 : return NULL; \
331 : }
332 :
333 :
334 : #define VALID_READ_BUFFER(self) \
335 : (self->readable && self->read_end != -1)
336 :
337 : #define VALID_WRITE_BUFFER(self) \
338 : (self->writable && self->write_end != -1)
339 :
340 : #define ADJUST_POSITION(self, _new_pos) \
341 : do { \
342 : self->pos = _new_pos; \
343 : if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
344 : self->read_end = self->pos; \
345 : } while(0)
346 :
347 : #define READAHEAD(self) \
348 : ((self->readable && VALID_READ_BUFFER(self)) \
349 : ? (self->read_end - self->pos) : 0)
350 :
351 : #define RAW_OFFSET(self) \
352 : (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
353 : && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
354 :
355 : #define RAW_TELL(self) \
356 : (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
357 :
358 : #define MINUS_LAST_BLOCK(self, size) \
359 : (self->buffer_mask ? \
360 : (size & ~self->buffer_mask) : \
361 : (self->buffer_size * (size / self->buffer_size)))
362 :
363 :
364 : static void
365 0 : buffered_dealloc(buffered *self)
366 : {
367 0 : if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
368 0 : return;
369 0 : _PyObject_GC_UNTRACK(self);
370 0 : self->ok = 0;
371 0 : if (self->weakreflist != NULL)
372 0 : PyObject_ClearWeakRefs((PyObject *)self);
373 0 : Py_CLEAR(self->raw);
374 0 : if (self->buffer) {
375 0 : PyMem_Free(self->buffer);
376 0 : self->buffer = NULL;
377 : }
378 : #ifdef WITH_THREAD
379 : if (self->lock) {
380 : PyThread_free_lock(self->lock);
381 : self->lock = NULL;
382 : }
383 : #endif
384 0 : Py_CLEAR(self->dict);
385 0 : Py_TYPE(self)->tp_free((PyObject *)self);
386 : }
387 :
388 : static PyObject *
389 0 : buffered_sizeof(buffered *self, void *unused)
390 : {
391 : Py_ssize_t res;
392 :
393 0 : res = _PyObject_SIZE(Py_TYPE(self));
394 0 : if (self->buffer)
395 0 : res += self->buffer_size;
396 0 : return PyLong_FromSsize_t(res);
397 : }
398 :
399 : static int
400 0 : buffered_traverse(buffered *self, visitproc visit, void *arg)
401 : {
402 0 : Py_VISIT(self->raw);
403 0 : Py_VISIT(self->dict);
404 0 : return 0;
405 : }
406 :
407 : static int
408 0 : buffered_clear(buffered *self)
409 : {
410 0 : if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
411 0 : return -1;
412 0 : self->ok = 0;
413 0 : Py_CLEAR(self->raw);
414 0 : Py_CLEAR(self->dict);
415 0 : return 0;
416 : }
417 :
418 : /*
419 : * _BufferedIOMixin methods
420 : * This is not a class, just a collection of methods that will be reused
421 : * by BufferedReader and BufferedWriter
422 : */
423 :
424 : /* Flush and close */
425 :
426 : static PyObject *
427 0 : buffered_simple_flush(buffered *self, PyObject *args)
428 : {
429 0 : CHECK_INITIALIZED(self)
430 0 : return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
431 : }
432 :
433 : static int
434 0 : buffered_closed(buffered *self)
435 : {
436 : int closed;
437 : PyObject *res;
438 0 : CHECK_INITIALIZED_INT(self)
439 0 : res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
440 0 : if (res == NULL)
441 0 : return -1;
442 0 : closed = PyObject_IsTrue(res);
443 0 : Py_DECREF(res);
444 0 : return closed;
445 : }
446 :
447 : static PyObject *
448 0 : buffered_closed_get(buffered *self, void *context)
449 : {
450 0 : CHECK_INITIALIZED(self)
451 0 : return PyObject_GetAttr(self->raw, _PyIO_str_closed);
452 : }
453 :
454 : static PyObject *
455 0 : buffered_close(buffered *self, PyObject *args)
456 : {
457 0 : PyObject *res = NULL, *exc = NULL, *val, *tb;
458 : int r;
459 :
460 0 : CHECK_INITIALIZED(self)
461 : if (!ENTER_BUFFERED(self))
462 : return NULL;
463 :
464 0 : r = buffered_closed(self);
465 0 : if (r < 0)
466 0 : goto end;
467 0 : if (r > 0) {
468 0 : res = Py_None;
469 0 : Py_INCREF(res);
470 0 : goto end;
471 : }
472 : /* flush() will most probably re-take the lock, so drop it first */
473 : LEAVE_BUFFERED(self)
474 0 : res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
475 : if (!ENTER_BUFFERED(self))
476 : return NULL;
477 0 : if (res == NULL)
478 0 : PyErr_Fetch(&exc, &val, &tb);
479 : else
480 0 : Py_DECREF(res);
481 :
482 0 : res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
483 :
484 0 : if (exc != NULL) {
485 0 : _PyErr_ReplaceException(exc, val, tb);
486 0 : Py_CLEAR(res);
487 : }
488 :
489 : end:
490 : LEAVE_BUFFERED(self)
491 0 : return res;
492 : }
493 :
494 : /* detach */
495 :
496 : static PyObject *
497 0 : buffered_detach(buffered *self, PyObject *args)
498 : {
499 : PyObject *raw, *res;
500 0 : CHECK_INITIALIZED(self)
501 0 : res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
502 0 : if (res == NULL)
503 0 : return NULL;
504 0 : Py_DECREF(res);
505 0 : raw = self->raw;
506 0 : self->raw = NULL;
507 0 : self->detached = 1;
508 0 : self->ok = 0;
509 0 : return raw;
510 : }
511 :
512 : /* Inquiries */
513 :
514 : static PyObject *
515 0 : buffered_seekable(buffered *self, PyObject *args)
516 : {
517 0 : CHECK_INITIALIZED(self)
518 0 : return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
519 : }
520 :
521 : static PyObject *
522 0 : buffered_readable(buffered *self, PyObject *args)
523 : {
524 0 : CHECK_INITIALIZED(self)
525 0 : return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
526 : }
527 :
528 : static PyObject *
529 0 : buffered_writable(buffered *self, PyObject *args)
530 : {
531 0 : CHECK_INITIALIZED(self)
532 0 : return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
533 : }
534 :
535 : static PyObject *
536 0 : buffered_name_get(buffered *self, void *context)
537 : {
538 0 : CHECK_INITIALIZED(self)
539 0 : return PyObject_GetAttrString(self->raw, "name");
540 : }
541 :
542 : static PyObject *
543 0 : buffered_mode_get(buffered *self, void *context)
544 : {
545 0 : CHECK_INITIALIZED(self)
546 0 : return PyObject_GetAttrString(self->raw, "mode");
547 : }
548 :
549 : /* Lower-level APIs */
550 :
551 : static PyObject *
552 0 : buffered_fileno(buffered *self, PyObject *args)
553 : {
554 0 : CHECK_INITIALIZED(self)
555 0 : return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
556 : }
557 :
558 : static PyObject *
559 0 : buffered_isatty(buffered *self, PyObject *args)
560 : {
561 0 : CHECK_INITIALIZED(self)
562 0 : return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
563 : }
564 :
565 :
566 : /* Forward decls */
567 : static PyObject *
568 : _bufferedwriter_flush_unlocked(buffered *);
569 : static Py_ssize_t
570 : _bufferedreader_fill_buffer(buffered *self);
571 : static void
572 : _bufferedreader_reset_buf(buffered *self);
573 : static void
574 : _bufferedwriter_reset_buf(buffered *self);
575 : static PyObject *
576 : _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
577 : static PyObject *
578 : _bufferedreader_read_all(buffered *self);
579 : static PyObject *
580 : _bufferedreader_read_fast(buffered *self, Py_ssize_t);
581 : static PyObject *
582 : _bufferedreader_read_generic(buffered *self, Py_ssize_t);
583 :
584 :
585 : /*
586 : * Helpers
587 : */
588 :
589 : /* Sets the current error to BlockingIOError */
590 : static void
591 0 : _set_BlockingIOError(char *msg, Py_ssize_t written)
592 : {
593 : PyObject *err;
594 0 : err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
595 0 : errno, msg, written);
596 0 : if (err)
597 0 : PyErr_SetObject(PyExc_BlockingIOError, err);
598 0 : Py_XDECREF(err);
599 0 : }
600 :
601 : /* Returns the address of the `written` member if a BlockingIOError was
602 : raised, NULL otherwise. The error is always re-raised. */
603 : static Py_ssize_t *
604 0 : _buffered_check_blocking_error(void)
605 : {
606 : PyObject *t, *v, *tb;
607 : PyBlockingIOErrorObject *err;
608 :
609 0 : PyErr_Fetch(&t, &v, &tb);
610 0 : if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
611 0 : PyErr_Restore(t, v, tb);
612 0 : return NULL;
613 : }
614 0 : err = (PyBlockingIOErrorObject *) v;
615 : /* TODO: sanity check (err->written >= 0) */
616 0 : PyErr_Restore(t, v, tb);
617 0 : return &err->written;
618 : }
619 :
620 : static Py_off_t
621 0 : _buffered_raw_tell(buffered *self)
622 : {
623 : Py_off_t n;
624 : PyObject *res;
625 0 : res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
626 0 : if (res == NULL)
627 0 : return -1;
628 0 : n = PyNumber_AsOff_t(res, PyExc_ValueError);
629 0 : Py_DECREF(res);
630 0 : if (n < 0) {
631 0 : if (!PyErr_Occurred())
632 0 : PyErr_Format(PyExc_IOError,
633 : "Raw stream returned invalid position %" PY_PRIdOFF,
634 : (PY_OFF_T_COMPAT)n);
635 0 : return -1;
636 : }
637 0 : self->abs_pos = n;
638 0 : return n;
639 : }
640 :
641 : static Py_off_t
642 0 : _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
643 : {
644 : PyObject *res, *posobj, *whenceobj;
645 : Py_off_t n;
646 :
647 0 : posobj = PyLong_FromOff_t(target);
648 0 : if (posobj == NULL)
649 0 : return -1;
650 0 : whenceobj = PyLong_FromLong(whence);
651 0 : if (whenceobj == NULL) {
652 0 : Py_DECREF(posobj);
653 0 : return -1;
654 : }
655 0 : res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
656 : posobj, whenceobj, NULL);
657 0 : Py_DECREF(posobj);
658 0 : Py_DECREF(whenceobj);
659 0 : if (res == NULL)
660 0 : return -1;
661 0 : n = PyNumber_AsOff_t(res, PyExc_ValueError);
662 0 : Py_DECREF(res);
663 0 : if (n < 0) {
664 0 : if (!PyErr_Occurred())
665 0 : PyErr_Format(PyExc_IOError,
666 : "Raw stream returned invalid position %" PY_PRIdOFF,
667 : (PY_OFF_T_COMPAT)n);
668 0 : return -1;
669 : }
670 0 : self->abs_pos = n;
671 0 : return n;
672 : }
673 :
674 : static int
675 0 : _buffered_init(buffered *self)
676 : {
677 : Py_ssize_t n;
678 0 : if (self->buffer_size <= 0) {
679 0 : PyErr_SetString(PyExc_ValueError,
680 : "buffer size must be strictly positive");
681 0 : return -1;
682 : }
683 0 : if (self->buffer)
684 0 : PyMem_Free(self->buffer);
685 0 : self->buffer = PyMem_Malloc(self->buffer_size);
686 0 : if (self->buffer == NULL) {
687 0 : PyErr_NoMemory();
688 0 : return -1;
689 : }
690 : #ifdef WITH_THREAD
691 : if (self->lock)
692 : PyThread_free_lock(self->lock);
693 : self->lock = PyThread_allocate_lock();
694 : if (self->lock == NULL) {
695 : PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
696 : return -1;
697 : }
698 : self->owner = 0;
699 : #endif
700 : /* Find out whether buffer_size is a power of 2 */
701 : /* XXX is this optimization useful? */
702 0 : for (n = self->buffer_size - 1; n & 1; n >>= 1)
703 : ;
704 0 : if (n == 0)
705 0 : self->buffer_mask = self->buffer_size - 1;
706 : else
707 0 : self->buffer_mask = 0;
708 0 : if (_buffered_raw_tell(self) == -1)
709 0 : PyErr_Clear();
710 0 : return 0;
711 : }
712 :
713 : /* Return 1 if an EnvironmentError with errno == EINTR is set (and then
714 : clears the error indicator), 0 otherwise.
715 : Should only be called when PyErr_Occurred() is true.
716 : */
717 : int
718 0 : _PyIO_trap_eintr(void)
719 : {
720 : static PyObject *eintr_int = NULL;
721 : PyObject *typ, *val, *tb;
722 : PyEnvironmentErrorObject *env_err;
723 :
724 0 : if (eintr_int == NULL) {
725 0 : eintr_int = PyLong_FromLong(EINTR);
726 : assert(eintr_int != NULL);
727 : }
728 0 : if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
729 0 : return 0;
730 0 : PyErr_Fetch(&typ, &val, &tb);
731 0 : PyErr_NormalizeException(&typ, &val, &tb);
732 0 : env_err = (PyEnvironmentErrorObject *) val;
733 : assert(env_err != NULL);
734 0 : if (env_err->myerrno != NULL &&
735 0 : PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
736 0 : Py_DECREF(typ);
737 0 : Py_DECREF(val);
738 0 : Py_XDECREF(tb);
739 0 : return 1;
740 : }
741 : /* This silences any error set by PyObject_RichCompareBool() */
742 0 : PyErr_Restore(typ, val, tb);
743 0 : return 0;
744 : }
745 :
746 : /*
747 : * Shared methods and wrappers
748 : */
749 :
750 : static PyObject *
751 0 : buffered_flush_and_rewind_unlocked(buffered *self)
752 : {
753 : PyObject *res;
754 :
755 0 : res = _bufferedwriter_flush_unlocked(self);
756 0 : if (res == NULL)
757 0 : return NULL;
758 0 : Py_DECREF(res);
759 :
760 0 : if (self->readable) {
761 : /* Rewind the raw stream so that its position corresponds to
762 : the current logical position. */
763 : Py_off_t n;
764 0 : n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
765 0 : _bufferedreader_reset_buf(self);
766 0 : if (n == -1)
767 0 : return NULL;
768 : }
769 0 : Py_RETURN_NONE;
770 : }
771 :
772 : static PyObject *
773 0 : buffered_flush(buffered *self, PyObject *args)
774 : {
775 : PyObject *res;
776 :
777 0 : CHECK_INITIALIZED(self)
778 0 : CHECK_CLOSED(self, "flush of closed file")
779 :
780 : if (!ENTER_BUFFERED(self))
781 : return NULL;
782 0 : res = buffered_flush_and_rewind_unlocked(self);
783 : LEAVE_BUFFERED(self)
784 :
785 0 : return res;
786 : }
787 :
788 : static PyObject *
789 0 : buffered_peek(buffered *self, PyObject *args)
790 : {
791 0 : Py_ssize_t n = 0;
792 0 : PyObject *res = NULL;
793 :
794 0 : CHECK_INITIALIZED(self)
795 0 : if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
796 0 : return NULL;
797 : }
798 :
799 : if (!ENTER_BUFFERED(self))
800 : return NULL;
801 :
802 0 : if (self->writable) {
803 0 : res = buffered_flush_and_rewind_unlocked(self);
804 0 : if (res == NULL)
805 0 : goto end;
806 0 : Py_CLEAR(res);
807 : }
808 0 : res = _bufferedreader_peek_unlocked(self, n);
809 :
810 : end:
811 : LEAVE_BUFFERED(self)
812 0 : return res;
813 : }
814 :
815 : static PyObject *
816 0 : buffered_read(buffered *self, PyObject *args)
817 : {
818 0 : Py_ssize_t n = -1;
819 : PyObject *res;
820 :
821 0 : CHECK_INITIALIZED(self)
822 0 : if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
823 0 : return NULL;
824 : }
825 0 : if (n < -1) {
826 0 : PyErr_SetString(PyExc_ValueError,
827 : "read length must be positive or -1");
828 0 : return NULL;
829 : }
830 :
831 0 : CHECK_CLOSED(self, "read of closed file")
832 :
833 0 : if (n == -1) {
834 : /* The number of bytes is unspecified, read until the end of stream */
835 : if (!ENTER_BUFFERED(self))
836 : return NULL;
837 0 : res = _bufferedreader_read_all(self);
838 : }
839 : else {
840 0 : res = _bufferedreader_read_fast(self, n);
841 0 : if (res != Py_None)
842 0 : return res;
843 0 : Py_DECREF(res);
844 : if (!ENTER_BUFFERED(self))
845 : return NULL;
846 0 : res = _bufferedreader_read_generic(self, n);
847 : }
848 :
849 : LEAVE_BUFFERED(self)
850 0 : return res;
851 : }
852 :
853 : static PyObject *
854 0 : buffered_read1(buffered *self, PyObject *args)
855 : {
856 : Py_ssize_t n, have, r;
857 0 : PyObject *res = NULL;
858 :
859 0 : CHECK_INITIALIZED(self)
860 0 : if (!PyArg_ParseTuple(args, "n:read1", &n)) {
861 0 : return NULL;
862 : }
863 :
864 0 : if (n < 0) {
865 0 : PyErr_SetString(PyExc_ValueError,
866 : "read length must be positive");
867 0 : return NULL;
868 : }
869 0 : if (n == 0)
870 0 : return PyBytes_FromStringAndSize(NULL, 0);
871 :
872 : if (!ENTER_BUFFERED(self))
873 : return NULL;
874 :
875 : /* Return up to n bytes. If at least one byte is buffered, we
876 : only return buffered bytes. Otherwise, we do one raw read. */
877 :
878 : /* XXX: this mimicks the io.py implementation but is probably wrong.
879 : If we need to read from the raw stream, then we could actually read
880 : all `n` bytes asked by the caller (and possibly more, so as to fill
881 : our buffer for the next reads). */
882 :
883 0 : have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
884 0 : if (have > 0) {
885 0 : if (n > have)
886 0 : n = have;
887 0 : res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
888 0 : if (res == NULL)
889 0 : goto end;
890 0 : self->pos += n;
891 0 : goto end;
892 : }
893 :
894 0 : if (self->writable) {
895 0 : res = buffered_flush_and_rewind_unlocked(self);
896 0 : if (res == NULL)
897 0 : goto end;
898 0 : Py_DECREF(res);
899 : }
900 :
901 : /* Fill the buffer from the raw stream, and copy it to the result. */
902 0 : _bufferedreader_reset_buf(self);
903 0 : r = _bufferedreader_fill_buffer(self);
904 0 : if (r == -1)
905 0 : goto end;
906 0 : if (r == -2)
907 0 : r = 0;
908 0 : if (n > r)
909 0 : n = r;
910 0 : res = PyBytes_FromStringAndSize(self->buffer, n);
911 0 : if (res == NULL)
912 0 : goto end;
913 0 : self->pos = n;
914 :
915 : end:
916 : LEAVE_BUFFERED(self)
917 0 : return res;
918 : }
919 :
920 : static PyObject *
921 0 : buffered_readinto(buffered *self, PyObject *args)
922 : {
923 0 : CHECK_INITIALIZED(self)
924 :
925 : /* TODO: use raw.readinto() (or a direct copy from our buffer) instead! */
926 0 : return bufferediobase_readinto((PyObject *)self, args);
927 : }
928 :
929 : static PyObject *
930 0 : _buffered_readline(buffered *self, Py_ssize_t limit)
931 : {
932 0 : PyObject *res = NULL;
933 0 : PyObject *chunks = NULL;
934 0 : Py_ssize_t n, written = 0;
935 : const char *start, *s, *end;
936 :
937 0 : CHECK_CLOSED(self, "readline of closed file")
938 :
939 : /* First, try to find a line in the buffer. This can run unlocked because
940 : the calls to the C API are simple enough that they can't trigger
941 : any thread switch. */
942 0 : n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
943 0 : if (limit >= 0 && n > limit)
944 0 : n = limit;
945 0 : start = self->buffer + self->pos;
946 0 : s = memchr(start, '\n', n);
947 0 : if (s != NULL) {
948 0 : res = PyBytes_FromStringAndSize(start, s - start + 1);
949 0 : if (res != NULL)
950 0 : self->pos += s - start + 1;
951 0 : goto end_unlocked;
952 : }
953 0 : if (n == limit) {
954 0 : res = PyBytes_FromStringAndSize(start, n);
955 0 : if (res != NULL)
956 0 : self->pos += n;
957 0 : goto end_unlocked;
958 : }
959 :
960 : if (!ENTER_BUFFERED(self))
961 : goto end_unlocked;
962 :
963 : /* Now we try to get some more from the raw stream */
964 0 : chunks = PyList_New(0);
965 0 : if (chunks == NULL)
966 0 : goto end;
967 0 : if (n > 0) {
968 0 : res = PyBytes_FromStringAndSize(start, n);
969 0 : if (res == NULL)
970 0 : goto end;
971 0 : if (PyList_Append(chunks, res) < 0) {
972 0 : Py_CLEAR(res);
973 0 : goto end;
974 : }
975 0 : Py_CLEAR(res);
976 0 : written += n;
977 0 : self->pos += n;
978 0 : if (limit >= 0)
979 0 : limit -= n;
980 : }
981 0 : if (self->writable) {
982 0 : PyObject *r = buffered_flush_and_rewind_unlocked(self);
983 0 : if (r == NULL)
984 0 : goto end;
985 0 : Py_DECREF(r);
986 : }
987 :
988 : for (;;) {
989 0 : _bufferedreader_reset_buf(self);
990 0 : n = _bufferedreader_fill_buffer(self);
991 0 : if (n == -1)
992 0 : goto end;
993 0 : if (n <= 0)
994 0 : break;
995 0 : if (limit >= 0 && n > limit)
996 0 : n = limit;
997 0 : start = self->buffer;
998 0 : end = start + n;
999 0 : s = start;
1000 0 : while (s < end) {
1001 0 : if (*s++ == '\n') {
1002 0 : res = PyBytes_FromStringAndSize(start, s - start);
1003 0 : if (res == NULL)
1004 0 : goto end;
1005 0 : self->pos = s - start;
1006 0 : goto found;
1007 : }
1008 : }
1009 0 : res = PyBytes_FromStringAndSize(start, n);
1010 0 : if (res == NULL)
1011 0 : goto end;
1012 0 : if (n == limit) {
1013 0 : self->pos = n;
1014 0 : break;
1015 : }
1016 0 : if (PyList_Append(chunks, res) < 0) {
1017 0 : Py_CLEAR(res);
1018 0 : goto end;
1019 : }
1020 0 : Py_CLEAR(res);
1021 0 : written += n;
1022 0 : if (limit >= 0)
1023 0 : limit -= n;
1024 0 : }
1025 : found:
1026 0 : if (res != NULL && PyList_Append(chunks, res) < 0) {
1027 0 : Py_CLEAR(res);
1028 0 : goto end;
1029 : }
1030 0 : Py_XSETREF(res, _PyBytes_Join(_PyIO_empty_bytes, chunks));
1031 :
1032 : end:
1033 : LEAVE_BUFFERED(self)
1034 : end_unlocked:
1035 0 : Py_XDECREF(chunks);
1036 0 : return res;
1037 : }
1038 :
1039 : static PyObject *
1040 0 : buffered_readline(buffered *self, PyObject *args)
1041 : {
1042 0 : Py_ssize_t limit = -1;
1043 :
1044 0 : CHECK_INITIALIZED(self)
1045 0 : if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
1046 0 : return NULL;
1047 0 : return _buffered_readline(self, limit);
1048 : }
1049 :
1050 :
1051 : static PyObject *
1052 0 : buffered_tell(buffered *self, PyObject *args)
1053 : {
1054 : Py_off_t pos;
1055 :
1056 0 : CHECK_INITIALIZED(self)
1057 0 : pos = _buffered_raw_tell(self);
1058 0 : if (pos == -1)
1059 0 : return NULL;
1060 0 : pos -= RAW_OFFSET(self);
1061 : /* TODO: sanity check (pos >= 0) */
1062 0 : return PyLong_FromOff_t(pos);
1063 : }
1064 :
1065 : static PyObject *
1066 0 : buffered_seek(buffered *self, PyObject *args)
1067 : {
1068 : Py_off_t target, n;
1069 0 : int whence = 0;
1070 0 : PyObject *targetobj, *res = NULL;
1071 :
1072 0 : CHECK_INITIALIZED(self)
1073 0 : if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1074 0 : return NULL;
1075 : }
1076 0 : if (whence < 0 || whence > 2) {
1077 0 : PyErr_Format(PyExc_ValueError,
1078 : "whence must be between 0 and 2, not %d", whence);
1079 0 : return NULL;
1080 : }
1081 :
1082 0 : CHECK_CLOSED(self, "seek of closed file")
1083 :
1084 0 : target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1085 0 : if (target == -1 && PyErr_Occurred())
1086 0 : return NULL;
1087 :
1088 0 : if (whence != 2 && self->readable) {
1089 : Py_off_t current, avail;
1090 : /* Check if seeking leaves us inside the current buffer,
1091 : so as to return quickly if possible. Also, we needn't take the
1092 : lock in this fast path.
1093 : Don't know how to do that when whence == 2, though. */
1094 : /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1095 : state at this point. */
1096 0 : current = RAW_TELL(self);
1097 0 : avail = READAHEAD(self);
1098 0 : if (avail > 0) {
1099 : Py_off_t offset;
1100 0 : if (whence == 0)
1101 0 : offset = target - (current - RAW_OFFSET(self));
1102 : else
1103 0 : offset = target;
1104 0 : if (offset >= -self->pos && offset <= avail) {
1105 0 : self->pos += offset;
1106 0 : return PyLong_FromOff_t(current - avail + offset);
1107 : }
1108 : }
1109 : }
1110 :
1111 : if (!ENTER_BUFFERED(self))
1112 : return NULL;
1113 :
1114 : /* Fallback: invoke raw seek() method and clear buffer */
1115 0 : if (self->writable) {
1116 0 : res = _bufferedwriter_flush_unlocked(self);
1117 0 : if (res == NULL)
1118 0 : goto end;
1119 0 : Py_CLEAR(res);
1120 0 : _bufferedwriter_reset_buf(self);
1121 : }
1122 :
1123 : /* TODO: align on block boundary and read buffer if needed? */
1124 0 : if (whence == 1)
1125 0 : target -= RAW_OFFSET(self);
1126 0 : n = _buffered_raw_seek(self, target, whence);
1127 0 : if (n == -1)
1128 0 : goto end;
1129 0 : self->raw_pos = -1;
1130 0 : res = PyLong_FromOff_t(n);
1131 0 : if (res != NULL && self->readable)
1132 0 : _bufferedreader_reset_buf(self);
1133 :
1134 : end:
1135 : LEAVE_BUFFERED(self)
1136 0 : return res;
1137 : }
1138 :
1139 : static PyObject *
1140 0 : buffered_truncate(buffered *self, PyObject *args)
1141 : {
1142 0 : PyObject *pos = Py_None;
1143 0 : PyObject *res = NULL;
1144 :
1145 0 : CHECK_INITIALIZED(self)
1146 0 : if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1147 0 : return NULL;
1148 : }
1149 :
1150 : if (!ENTER_BUFFERED(self))
1151 : return NULL;
1152 :
1153 0 : if (self->writable) {
1154 0 : res = buffered_flush_and_rewind_unlocked(self);
1155 0 : if (res == NULL)
1156 0 : goto end;
1157 0 : Py_CLEAR(res);
1158 : }
1159 0 : res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1160 0 : if (res == NULL)
1161 0 : goto end;
1162 : /* Reset cached position */
1163 0 : if (_buffered_raw_tell(self) == -1)
1164 0 : PyErr_Clear();
1165 :
1166 : end:
1167 : LEAVE_BUFFERED(self)
1168 0 : return res;
1169 : }
1170 :
1171 : static PyObject *
1172 0 : buffered_iternext(buffered *self)
1173 : {
1174 : PyObject *line;
1175 : PyTypeObject *tp;
1176 :
1177 0 : CHECK_INITIALIZED(self);
1178 :
1179 0 : tp = Py_TYPE(self);
1180 0 : if (tp == &PyBufferedReader_Type ||
1181 : tp == &PyBufferedRandom_Type) {
1182 : /* Skip method call overhead for speed */
1183 0 : line = _buffered_readline(self, -1);
1184 : }
1185 : else {
1186 0 : line = PyObject_CallMethodObjArgs((PyObject *)self,
1187 : _PyIO_str_readline, NULL);
1188 0 : if (line && !PyBytes_Check(line)) {
1189 0 : PyErr_Format(PyExc_IOError,
1190 : "readline() should have returned a bytes object, "
1191 0 : "not '%.200s'", Py_TYPE(line)->tp_name);
1192 0 : Py_DECREF(line);
1193 0 : return NULL;
1194 : }
1195 : }
1196 :
1197 0 : if (line == NULL)
1198 0 : return NULL;
1199 :
1200 0 : if (PyBytes_GET_SIZE(line) == 0) {
1201 : /* Reached EOF or would have blocked */
1202 0 : Py_DECREF(line);
1203 0 : return NULL;
1204 : }
1205 :
1206 0 : return line;
1207 : }
1208 :
1209 : static PyObject *
1210 0 : buffered_repr(buffered *self)
1211 : {
1212 : PyObject *nameobj, *res;
1213 :
1214 0 : nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1215 0 : if (nameobj == NULL) {
1216 0 : if (PyErr_ExceptionMatches(PyExc_Exception))
1217 0 : PyErr_Clear();
1218 : else
1219 0 : return NULL;
1220 0 : res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1221 : }
1222 : else {
1223 0 : PyObject *repr = PyObject_Repr(nameobj);
1224 0 : Py_DECREF(nameobj);
1225 0 : if (repr == NULL)
1226 0 : return NULL;
1227 0 : res = PyString_FromFormat("<%s name=%s>",
1228 0 : Py_TYPE(self)->tp_name,
1229 0 : PyString_AS_STRING(repr));
1230 0 : Py_DECREF(repr);
1231 : }
1232 0 : return res;
1233 : }
1234 :
1235 : /*
1236 : * class BufferedReader
1237 : */
1238 :
1239 : PyDoc_STRVAR(bufferedreader_doc,
1240 : "Create a new buffered reader using the given readable raw IO object.");
1241 :
1242 0 : static void _bufferedreader_reset_buf(buffered *self)
1243 : {
1244 0 : self->read_end = -1;
1245 0 : }
1246 :
1247 : static int
1248 0 : bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1249 : {
1250 0 : char *kwlist[] = {"raw", "buffer_size", NULL};
1251 0 : Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1252 : PyObject *raw;
1253 :
1254 0 : self->ok = 0;
1255 0 : self->detached = 0;
1256 :
1257 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1258 : &raw, &buffer_size)) {
1259 0 : return -1;
1260 : }
1261 :
1262 0 : if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1263 0 : return -1;
1264 :
1265 0 : Py_INCREF(raw);
1266 0 : Py_XSETREF(self->raw, raw);
1267 0 : self->buffer_size = buffer_size;
1268 0 : self->readable = 1;
1269 0 : self->writable = 0;
1270 :
1271 0 : if (_buffered_init(self) < 0)
1272 0 : return -1;
1273 0 : _bufferedreader_reset_buf(self);
1274 :
1275 0 : self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1276 0 : Py_TYPE(raw) == &PyFileIO_Type);
1277 :
1278 0 : self->ok = 1;
1279 0 : return 0;
1280 : }
1281 :
1282 : static Py_ssize_t
1283 0 : _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1284 : {
1285 : Py_buffer buf;
1286 : PyObject *memobj, *res;
1287 : Py_ssize_t n;
1288 : /* NOTE: the buffer needn't be released as its object is NULL. */
1289 0 : if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1290 0 : return -1;
1291 0 : memobj = PyMemoryView_FromBuffer(&buf);
1292 0 : if (memobj == NULL)
1293 0 : return -1;
1294 : /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1295 : occurs so we needn't do it ourselves.
1296 : We then retry reading, ignoring the signal if no handler has
1297 : raised (see issue #10956).
1298 : */
1299 : do {
1300 0 : res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1301 0 : } while (res == NULL && _PyIO_trap_eintr());
1302 0 : Py_DECREF(memobj);
1303 0 : if (res == NULL)
1304 0 : return -1;
1305 0 : if (res == Py_None) {
1306 : /* Non-blocking stream would have blocked. Special return code! */
1307 0 : Py_DECREF(res);
1308 0 : return -2;
1309 : }
1310 0 : n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1311 0 : Py_DECREF(res);
1312 0 : if (n < 0 || n > len) {
1313 0 : PyErr_Format(PyExc_IOError,
1314 : "raw readinto() returned invalid length %zd "
1315 : "(should have been between 0 and %zd)", n, len);
1316 0 : return -1;
1317 : }
1318 0 : if (n > 0 && self->abs_pos != -1)
1319 0 : self->abs_pos += n;
1320 0 : return n;
1321 : }
1322 :
1323 : static Py_ssize_t
1324 0 : _bufferedreader_fill_buffer(buffered *self)
1325 : {
1326 : Py_ssize_t start, len, n;
1327 0 : if (VALID_READ_BUFFER(self))
1328 0 : start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1329 : else
1330 0 : start = 0;
1331 0 : len = self->buffer_size - start;
1332 0 : n = _bufferedreader_raw_read(self, self->buffer + start, len);
1333 0 : if (n <= 0)
1334 0 : return n;
1335 0 : self->read_end = start + n;
1336 0 : self->raw_pos = start + n;
1337 0 : return n;
1338 : }
1339 :
1340 : static PyObject *
1341 0 : _bufferedreader_read_all(buffered *self)
1342 : {
1343 : Py_ssize_t current_size;
1344 0 : PyObject *res, *data = NULL;
1345 0 : PyObject *chunks = PyList_New(0);
1346 :
1347 0 : if (chunks == NULL)
1348 0 : return NULL;
1349 :
1350 : /* First copy what we have in the current buffer. */
1351 0 : current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1352 0 : if (current_size) {
1353 0 : data = PyBytes_FromStringAndSize(
1354 0 : self->buffer + self->pos, current_size);
1355 0 : if (data == NULL) {
1356 0 : Py_DECREF(chunks);
1357 0 : return NULL;
1358 : }
1359 0 : self->pos += current_size;
1360 : }
1361 : /* We're going past the buffer's bounds, flush it */
1362 0 : if (self->writable) {
1363 0 : res = buffered_flush_and_rewind_unlocked(self);
1364 0 : if (res == NULL) {
1365 0 : Py_DECREF(chunks);
1366 0 : return NULL;
1367 : }
1368 0 : Py_CLEAR(res);
1369 : }
1370 0 : _bufferedreader_reset_buf(self);
1371 : while (1) {
1372 0 : if (data) {
1373 0 : if (PyList_Append(chunks, data) < 0) {
1374 0 : Py_DECREF(data);
1375 0 : Py_DECREF(chunks);
1376 0 : return NULL;
1377 : }
1378 0 : Py_DECREF(data);
1379 : }
1380 :
1381 : /* Read until EOF or until read() would block. */
1382 0 : data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1383 0 : if (data == NULL) {
1384 0 : Py_DECREF(chunks);
1385 0 : return NULL;
1386 : }
1387 0 : if (data != Py_None && !PyBytes_Check(data)) {
1388 0 : Py_DECREF(data);
1389 0 : Py_DECREF(chunks);
1390 0 : PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1391 0 : return NULL;
1392 : }
1393 0 : if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1394 0 : if (current_size == 0) {
1395 0 : Py_DECREF(chunks);
1396 0 : return data;
1397 : }
1398 : else {
1399 0 : res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1400 0 : Py_DECREF(data);
1401 0 : Py_DECREF(chunks);
1402 0 : return res;
1403 : }
1404 : }
1405 0 : current_size += PyBytes_GET_SIZE(data);
1406 0 : if (self->abs_pos != -1)
1407 0 : self->abs_pos += PyBytes_GET_SIZE(data);
1408 0 : }
1409 : }
1410 :
1411 : /* Read n bytes from the buffer if it can, otherwise return None.
1412 : This function is simple enough that it can run unlocked. */
1413 : static PyObject *
1414 0 : _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1415 : {
1416 : Py_ssize_t current_size;
1417 :
1418 0 : current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1419 0 : if (n <= current_size) {
1420 : /* Fast path: the data to read is fully buffered. */
1421 0 : PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1422 0 : if (res != NULL)
1423 0 : self->pos += n;
1424 0 : return res;
1425 : }
1426 0 : Py_RETURN_NONE;
1427 : }
1428 :
1429 : /* Generic read function: read from the stream until enough bytes are read,
1430 : * or until an EOF occurs or until read() would block.
1431 : */
1432 : static PyObject *
1433 0 : _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1434 : {
1435 0 : PyObject *res = NULL;
1436 : Py_ssize_t current_size, remaining, written;
1437 : char *out;
1438 :
1439 0 : current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1440 0 : if (n <= current_size)
1441 0 : return _bufferedreader_read_fast(self, n);
1442 :
1443 0 : res = PyBytes_FromStringAndSize(NULL, n);
1444 0 : if (res == NULL)
1445 0 : goto error;
1446 0 : out = PyBytes_AS_STRING(res);
1447 0 : remaining = n;
1448 0 : written = 0;
1449 0 : if (current_size > 0) {
1450 0 : memcpy(out, self->buffer + self->pos, current_size);
1451 0 : remaining -= current_size;
1452 0 : written += current_size;
1453 0 : self->pos += current_size;
1454 : }
1455 : /* Flush the write buffer if necessary */
1456 0 : if (self->writable) {
1457 0 : PyObject *r = buffered_flush_and_rewind_unlocked(self);
1458 0 : if (r == NULL)
1459 0 : goto error;
1460 0 : Py_DECREF(r);
1461 : }
1462 0 : _bufferedreader_reset_buf(self);
1463 0 : while (remaining > 0) {
1464 : /* We want to read a whole block at the end into buffer.
1465 : If we had readv() we could do this in one pass. */
1466 0 : Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1467 0 : if (r == 0)
1468 0 : break;
1469 0 : r = _bufferedreader_raw_read(self, out + written, r);
1470 0 : if (r == -1)
1471 0 : goto error;
1472 0 : if (r == 0 || r == -2) {
1473 : /* EOF occurred or read() would block. */
1474 0 : if (r == 0 || written > 0) {
1475 0 : if (_PyBytes_Resize(&res, written))
1476 0 : goto error;
1477 0 : return res;
1478 : }
1479 0 : Py_DECREF(res);
1480 0 : Py_INCREF(Py_None);
1481 0 : return Py_None;
1482 : }
1483 0 : remaining -= r;
1484 0 : written += r;
1485 : }
1486 : assert(remaining <= self->buffer_size);
1487 0 : self->pos = 0;
1488 0 : self->raw_pos = 0;
1489 0 : self->read_end = 0;
1490 : /* NOTE: when the read is satisfied, we avoid issuing any additional
1491 : reads, which could block indefinitely (e.g. on a socket).
1492 : See issue #9550. */
1493 0 : while (remaining > 0 && self->read_end < self->buffer_size) {
1494 0 : Py_ssize_t r = _bufferedreader_fill_buffer(self);
1495 0 : if (r == -1)
1496 0 : goto error;
1497 0 : if (r == 0 || r == -2) {
1498 : /* EOF occurred or read() would block. */
1499 0 : if (r == 0 || written > 0) {
1500 0 : if (_PyBytes_Resize(&res, written))
1501 0 : goto error;
1502 0 : return res;
1503 : }
1504 0 : Py_DECREF(res);
1505 0 : Py_INCREF(Py_None);
1506 0 : return Py_None;
1507 : }
1508 0 : if (remaining > r) {
1509 0 : memcpy(out + written, self->buffer + self->pos, r);
1510 0 : written += r;
1511 0 : self->pos += r;
1512 0 : remaining -= r;
1513 : }
1514 0 : else if (remaining > 0) {
1515 0 : memcpy(out + written, self->buffer + self->pos, remaining);
1516 0 : written += remaining;
1517 0 : self->pos += remaining;
1518 0 : remaining = 0;
1519 : }
1520 0 : if (remaining == 0)
1521 0 : break;
1522 : }
1523 :
1524 0 : return res;
1525 :
1526 : error:
1527 0 : Py_XDECREF(res);
1528 0 : return NULL;
1529 : }
1530 :
1531 : static PyObject *
1532 0 : _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1533 : {
1534 : Py_ssize_t have, r;
1535 :
1536 0 : have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1537 : /* Constraints:
1538 : 1. we don't want to advance the file position.
1539 : 2. we don't want to lose block alignment, so we can't shift the buffer
1540 : to make some place.
1541 : Therefore, we either return `have` bytes (if > 0), or a full buffer.
1542 : */
1543 0 : if (have > 0) {
1544 0 : return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1545 : }
1546 :
1547 : /* Fill the buffer from the raw stream, and copy it to the result. */
1548 0 : _bufferedreader_reset_buf(self);
1549 0 : r = _bufferedreader_fill_buffer(self);
1550 0 : if (r == -1)
1551 0 : return NULL;
1552 0 : if (r == -2)
1553 0 : r = 0;
1554 0 : self->pos = 0;
1555 0 : return PyBytes_FromStringAndSize(self->buffer, r);
1556 : }
1557 :
1558 : static PyMethodDef bufferedreader_methods[] = {
1559 : /* BufferedIOMixin methods */
1560 : {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1561 : {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1562 : {"close", (PyCFunction)buffered_close, METH_NOARGS},
1563 : {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1564 : {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1565 : {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1566 : {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1567 : {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1568 :
1569 : {"read", (PyCFunction)buffered_read, METH_VARARGS},
1570 : {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1571 : {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1572 : {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1573 : {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1574 : {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1575 : {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1576 : {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
1577 : {NULL, NULL}
1578 : };
1579 :
1580 : static PyMemberDef bufferedreader_members[] = {
1581 : {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
1582 : {NULL}
1583 : };
1584 :
1585 : static PyGetSetDef bufferedreader_getset[] = {
1586 : {"closed", (getter)buffered_closed_get, NULL, NULL},
1587 : {"name", (getter)buffered_name_get, NULL, NULL},
1588 : {"mode", (getter)buffered_mode_get, NULL, NULL},
1589 : {NULL}
1590 : };
1591 :
1592 :
1593 : PyTypeObject PyBufferedReader_Type = {
1594 : PyVarObject_HEAD_INIT(NULL, 0)
1595 : "_io.BufferedReader", /*tp_name*/
1596 : sizeof(buffered), /*tp_basicsize*/
1597 : 0, /*tp_itemsize*/
1598 : (destructor)buffered_dealloc, /*tp_dealloc*/
1599 : 0, /*tp_print*/
1600 : 0, /*tp_getattr*/
1601 : 0, /*tp_setattr*/
1602 : 0, /*tp_compare */
1603 : (reprfunc)buffered_repr, /*tp_repr*/
1604 : 0, /*tp_as_number*/
1605 : 0, /*tp_as_sequence*/
1606 : 0, /*tp_as_mapping*/
1607 : 0, /*tp_hash */
1608 : 0, /*tp_call*/
1609 : 0, /*tp_str*/
1610 : 0, /*tp_getattro*/
1611 : 0, /*tp_setattro*/
1612 : 0, /*tp_as_buffer*/
1613 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1614 : | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1615 : bufferedreader_doc, /* tp_doc */
1616 : (traverseproc)buffered_traverse, /* tp_traverse */
1617 : (inquiry)buffered_clear, /* tp_clear */
1618 : 0, /* tp_richcompare */
1619 : offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1620 : 0, /* tp_iter */
1621 : (iternextfunc)buffered_iternext, /* tp_iternext */
1622 : bufferedreader_methods, /* tp_methods */
1623 : bufferedreader_members, /* tp_members */
1624 : bufferedreader_getset, /* tp_getset */
1625 : 0, /* tp_base */
1626 : 0, /* tp_dict */
1627 : 0, /* tp_descr_get */
1628 : 0, /* tp_descr_set */
1629 : offsetof(buffered, dict), /* tp_dictoffset */
1630 : (initproc)bufferedreader_init, /* tp_init */
1631 : 0, /* tp_alloc */
1632 : PyType_GenericNew, /* tp_new */
1633 : };
1634 :
1635 :
1636 :
1637 : static int
1638 0 : complain_about_max_buffer_size(void)
1639 : {
1640 0 : if (PyErr_WarnEx(PyExc_DeprecationWarning,
1641 : "max_buffer_size is deprecated", 1) < 0)
1642 0 : return 0;
1643 0 : return 1;
1644 : }
1645 :
1646 : /*
1647 : * class BufferedWriter
1648 : */
1649 : PyDoc_STRVAR(bufferedwriter_doc,
1650 : "A buffer for a writeable sequential RawIO object.\n"
1651 : "\n"
1652 : "The constructor creates a BufferedWriter for the given writeable raw\n"
1653 : "stream. If the buffer_size is not given, it defaults to\n"
1654 : "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1655 : );
1656 :
1657 : static void
1658 0 : _bufferedwriter_reset_buf(buffered *self)
1659 : {
1660 0 : self->write_pos = 0;
1661 0 : self->write_end = -1;
1662 0 : }
1663 :
1664 : static int
1665 0 : bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1666 : {
1667 : /* TODO: properly deprecate max_buffer_size */
1668 0 : char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1669 0 : Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1670 0 : Py_ssize_t max_buffer_size = -234;
1671 : PyObject *raw;
1672 :
1673 0 : self->ok = 0;
1674 0 : self->detached = 0;
1675 :
1676 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedWriter", kwlist,
1677 : &raw, &buffer_size, &max_buffer_size)) {
1678 0 : return -1;
1679 : }
1680 :
1681 0 : if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1682 0 : return -1;
1683 :
1684 0 : if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1685 0 : return -1;
1686 :
1687 0 : Py_INCREF(raw);
1688 0 : Py_XSETREF(self->raw, raw);
1689 0 : self->readable = 0;
1690 0 : self->writable = 1;
1691 :
1692 0 : self->buffer_size = buffer_size;
1693 0 : if (_buffered_init(self) < 0)
1694 0 : return -1;
1695 0 : _bufferedwriter_reset_buf(self);
1696 0 : self->pos = 0;
1697 :
1698 0 : self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1699 0 : Py_TYPE(raw) == &PyFileIO_Type);
1700 :
1701 0 : self->ok = 1;
1702 0 : return 0;
1703 : }
1704 :
1705 : static Py_ssize_t
1706 0 : _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1707 : {
1708 : Py_buffer buf;
1709 : PyObject *memobj, *res;
1710 : Py_ssize_t n;
1711 : int errnum;
1712 : /* NOTE: the buffer needn't be released as its object is NULL. */
1713 0 : if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1714 0 : return -1;
1715 0 : memobj = PyMemoryView_FromBuffer(&buf);
1716 0 : if (memobj == NULL)
1717 0 : return -1;
1718 : /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1719 : occurs so we needn't do it ourselves.
1720 : We then retry writing, ignoring the signal if no handler has
1721 : raised (see issue #10956).
1722 : */
1723 : do {
1724 0 : errno = 0;
1725 0 : res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1726 0 : errnum = errno;
1727 0 : } while (res == NULL && _PyIO_trap_eintr());
1728 0 : Py_DECREF(memobj);
1729 0 : if (res == NULL)
1730 0 : return -1;
1731 0 : if (res == Py_None) {
1732 : /* Non-blocking stream would have blocked. Special return code!
1733 : Being paranoid we reset errno in case it is changed by code
1734 : triggered by a decref. errno is used by _set_BlockingIOError(). */
1735 0 : Py_DECREF(res);
1736 0 : errno = errnum;
1737 0 : return -2;
1738 : }
1739 0 : n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1740 0 : Py_DECREF(res);
1741 0 : if (n < 0 || n > len) {
1742 0 : PyErr_Format(PyExc_IOError,
1743 : "raw write() returned invalid length %zd "
1744 : "(should have been between 0 and %zd)", n, len);
1745 0 : return -1;
1746 : }
1747 0 : if (n > 0 && self->abs_pos != -1)
1748 0 : self->abs_pos += n;
1749 0 : return n;
1750 : }
1751 :
1752 : /* `restore_pos` is 1 if we need to restore the raw stream position at
1753 : the end, 0 otherwise. */
1754 : static PyObject *
1755 0 : _bufferedwriter_flush_unlocked(buffered *self)
1756 : {
1757 0 : Py_ssize_t written = 0;
1758 : Py_off_t n, rewind;
1759 :
1760 0 : if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1761 : goto end;
1762 : /* First, rewind */
1763 0 : rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1764 0 : if (rewind != 0) {
1765 0 : n = _buffered_raw_seek(self, -rewind, 1);
1766 0 : if (n < 0) {
1767 0 : goto error;
1768 : }
1769 0 : self->raw_pos -= rewind;
1770 : }
1771 0 : while (self->write_pos < self->write_end) {
1772 0 : n = _bufferedwriter_raw_write(self,
1773 0 : self->buffer + self->write_pos,
1774 0 : Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1775 : Py_off_t, Py_ssize_t));
1776 0 : if (n == -1) {
1777 0 : goto error;
1778 : }
1779 0 : else if (n == -2) {
1780 0 : _set_BlockingIOError("write could not complete without blocking",
1781 : 0);
1782 0 : goto error;
1783 : }
1784 0 : self->write_pos += n;
1785 0 : self->raw_pos = self->write_pos;
1786 0 : written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1787 : /* Partial writes can return successfully when interrupted by a
1788 : signal (see write(2)). We must run signal handlers before
1789 : blocking another time, possibly indefinitely. */
1790 0 : if (PyErr_CheckSignals() < 0)
1791 0 : goto error;
1792 : }
1793 :
1794 0 : _bufferedwriter_reset_buf(self);
1795 :
1796 : end:
1797 0 : Py_RETURN_NONE;
1798 :
1799 : error:
1800 0 : return NULL;
1801 : }
1802 :
1803 : static PyObject *
1804 0 : bufferedwriter_write(buffered *self, PyObject *args)
1805 : {
1806 0 : PyObject *res = NULL;
1807 : Py_buffer buf;
1808 : Py_ssize_t written, avail, remaining;
1809 : Py_off_t offset;
1810 :
1811 0 : CHECK_INITIALIZED(self)
1812 0 : if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1813 0 : return NULL;
1814 : }
1815 :
1816 0 : if (IS_CLOSED(self)) {
1817 0 : PyErr_SetString(PyExc_ValueError, "write to closed file");
1818 0 : PyBuffer_Release(&buf);
1819 0 : return NULL;
1820 : }
1821 :
1822 : if (!ENTER_BUFFERED(self)) {
1823 : PyBuffer_Release(&buf);
1824 : return NULL;
1825 : }
1826 :
1827 : /* Fast path: the data to write can be fully buffered. */
1828 0 : if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1829 0 : self->pos = 0;
1830 0 : self->raw_pos = 0;
1831 : }
1832 0 : avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1833 0 : if (buf.len <= avail) {
1834 0 : memcpy(self->buffer + self->pos, buf.buf, buf.len);
1835 0 : if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
1836 0 : self->write_pos = self->pos;
1837 : }
1838 0 : ADJUST_POSITION(self, self->pos + buf.len);
1839 0 : if (self->pos > self->write_end)
1840 0 : self->write_end = self->pos;
1841 0 : written = buf.len;
1842 0 : goto end;
1843 : }
1844 :
1845 : /* First write the current buffer */
1846 0 : res = _bufferedwriter_flush_unlocked(self);
1847 0 : if (res == NULL) {
1848 0 : Py_ssize_t *w = _buffered_check_blocking_error();
1849 0 : if (w == NULL)
1850 0 : goto error;
1851 0 : if (self->readable)
1852 0 : _bufferedreader_reset_buf(self);
1853 : /* Make some place by shifting the buffer. */
1854 : assert(VALID_WRITE_BUFFER(self));
1855 0 : memmove(self->buffer, self->buffer + self->write_pos,
1856 0 : Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1857 : Py_off_t, Py_ssize_t));
1858 0 : self->write_end -= self->write_pos;
1859 0 : self->raw_pos -= self->write_pos;
1860 0 : self->pos -= self->write_pos;
1861 0 : self->write_pos = 0;
1862 0 : avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1863 : Py_off_t, Py_ssize_t);
1864 0 : if (buf.len <= avail) {
1865 : /* Everything can be buffered */
1866 0 : PyErr_Clear();
1867 0 : memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1868 0 : self->write_end += buf.len;
1869 0 : self->pos += buf.len;
1870 0 : written = buf.len;
1871 0 : goto end;
1872 : }
1873 : /* Buffer as much as possible. */
1874 0 : memcpy(self->buffer + self->write_end, buf.buf, avail);
1875 0 : self->write_end += avail;
1876 0 : self->pos += avail;
1877 : /* XXX Modifying the existing exception e using the pointer w
1878 : will change e.characters_written but not e.args[2].
1879 : Therefore we just replace with a new error. */
1880 0 : _set_BlockingIOError("write could not complete without blocking",
1881 : avail);
1882 0 : goto error;
1883 : }
1884 0 : Py_CLEAR(res);
1885 :
1886 : /* Adjust the raw stream position if it is away from the logical stream
1887 : position. This happens if the read buffer has been filled but not
1888 : modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1889 : the raw stream by itself).
1890 : Fixes issue #6629.
1891 : */
1892 0 : offset = RAW_OFFSET(self);
1893 0 : if (offset != 0) {
1894 0 : if (_buffered_raw_seek(self, -offset, 1) < 0)
1895 0 : goto error;
1896 0 : self->raw_pos -= offset;
1897 : }
1898 :
1899 : /* Then write buf itself. At this point the buffer has been emptied. */
1900 0 : remaining = buf.len;
1901 0 : written = 0;
1902 0 : while (remaining > self->buffer_size) {
1903 0 : Py_ssize_t n = _bufferedwriter_raw_write(
1904 0 : self, (char *) buf.buf + written, buf.len - written);
1905 0 : if (n == -1) {
1906 0 : goto error;
1907 0 : } else if (n == -2) {
1908 : /* Write failed because raw file is non-blocking */
1909 0 : if (remaining > self->buffer_size) {
1910 : /* Can't buffer everything, still buffer as much as possible */
1911 0 : memcpy(self->buffer,
1912 0 : (char *) buf.buf + written, self->buffer_size);
1913 0 : self->raw_pos = 0;
1914 0 : ADJUST_POSITION(self, self->buffer_size);
1915 0 : self->write_end = self->buffer_size;
1916 0 : written += self->buffer_size;
1917 0 : _set_BlockingIOError("write could not complete without "
1918 : "blocking", written);
1919 0 : goto error;
1920 : }
1921 0 : PyErr_Clear();
1922 0 : break;
1923 : }
1924 0 : written += n;
1925 0 : remaining -= n;
1926 : /* Partial writes can return successfully when interrupted by a
1927 : signal (see write(2)). We must run signal handlers before
1928 : blocking another time, possibly indefinitely. */
1929 0 : if (PyErr_CheckSignals() < 0)
1930 0 : goto error;
1931 : }
1932 0 : if (self->readable)
1933 0 : _bufferedreader_reset_buf(self);
1934 0 : if (remaining > 0) {
1935 0 : memcpy(self->buffer, (char *) buf.buf + written, remaining);
1936 0 : written += remaining;
1937 : }
1938 0 : self->write_pos = 0;
1939 : /* TODO: sanity check (remaining >= 0) */
1940 0 : self->write_end = remaining;
1941 0 : ADJUST_POSITION(self, remaining);
1942 0 : self->raw_pos = 0;
1943 :
1944 : end:
1945 0 : res = PyLong_FromSsize_t(written);
1946 :
1947 : error:
1948 : LEAVE_BUFFERED(self)
1949 0 : PyBuffer_Release(&buf);
1950 0 : return res;
1951 : }
1952 :
1953 : static PyMethodDef bufferedwriter_methods[] = {
1954 : /* BufferedIOMixin methods */
1955 : {"close", (PyCFunction)buffered_close, METH_NOARGS},
1956 : {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1957 : {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1958 : {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1959 : {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1960 : {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1961 : {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1962 :
1963 : {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1964 : {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1965 : {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1966 : {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1967 : {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1968 : {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
1969 : {NULL, NULL}
1970 : };
1971 :
1972 : static PyMemberDef bufferedwriter_members[] = {
1973 : {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
1974 : {NULL}
1975 : };
1976 :
1977 : static PyGetSetDef bufferedwriter_getset[] = {
1978 : {"closed", (getter)buffered_closed_get, NULL, NULL},
1979 : {"name", (getter)buffered_name_get, NULL, NULL},
1980 : {"mode", (getter)buffered_mode_get, NULL, NULL},
1981 : {NULL}
1982 : };
1983 :
1984 :
1985 : PyTypeObject PyBufferedWriter_Type = {
1986 : PyVarObject_HEAD_INIT(NULL, 0)
1987 : "_io.BufferedWriter", /*tp_name*/
1988 : sizeof(buffered), /*tp_basicsize*/
1989 : 0, /*tp_itemsize*/
1990 : (destructor)buffered_dealloc, /*tp_dealloc*/
1991 : 0, /*tp_print*/
1992 : 0, /*tp_getattr*/
1993 : 0, /*tp_setattr*/
1994 : 0, /*tp_compare */
1995 : (reprfunc)buffered_repr, /*tp_repr*/
1996 : 0, /*tp_as_number*/
1997 : 0, /*tp_as_sequence*/
1998 : 0, /*tp_as_mapping*/
1999 : 0, /*tp_hash */
2000 : 0, /*tp_call*/
2001 : 0, /*tp_str*/
2002 : 0, /*tp_getattro*/
2003 : 0, /*tp_setattro*/
2004 : 0, /*tp_as_buffer*/
2005 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2006 : | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2007 : bufferedwriter_doc, /* tp_doc */
2008 : (traverseproc)buffered_traverse, /* tp_traverse */
2009 : (inquiry)buffered_clear, /* tp_clear */
2010 : 0, /* tp_richcompare */
2011 : offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2012 : 0, /* tp_iter */
2013 : 0, /* tp_iternext */
2014 : bufferedwriter_methods, /* tp_methods */
2015 : bufferedwriter_members, /* tp_members */
2016 : bufferedwriter_getset, /* tp_getset */
2017 : 0, /* tp_base */
2018 : 0, /* tp_dict */
2019 : 0, /* tp_descr_get */
2020 : 0, /* tp_descr_set */
2021 : offsetof(buffered, dict), /* tp_dictoffset */
2022 : (initproc)bufferedwriter_init, /* tp_init */
2023 : 0, /* tp_alloc */
2024 : PyType_GenericNew, /* tp_new */
2025 : };
2026 :
2027 :
2028 :
2029 : /*
2030 : * BufferedRWPair
2031 : */
2032 :
2033 : PyDoc_STRVAR(bufferedrwpair_doc,
2034 : "A buffered reader and writer object together.\n"
2035 : "\n"
2036 : "A buffered reader object and buffered writer object put together to\n"
2037 : "form a sequential IO object that can read and write. This is typically\n"
2038 : "used with a socket or two-way pipe.\n"
2039 : "\n"
2040 : "reader and writer are RawIOBase objects that are readable and\n"
2041 : "writeable respectively. If the buffer_size is omitted it defaults to\n"
2042 : "DEFAULT_BUFFER_SIZE.\n"
2043 : );
2044 :
2045 : /* XXX The usefulness of this (compared to having two separate IO objects) is
2046 : * questionable.
2047 : */
2048 :
2049 : typedef struct {
2050 : PyObject_HEAD
2051 : buffered *reader;
2052 : buffered *writer;
2053 : PyObject *dict;
2054 : PyObject *weakreflist;
2055 : } rwpair;
2056 :
2057 : static int
2058 0 : bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
2059 : {
2060 : PyObject *reader, *writer;
2061 0 : Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2062 0 : Py_ssize_t max_buffer_size = -234;
2063 :
2064 0 : if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2065 : &buffer_size, &max_buffer_size)) {
2066 0 : return -1;
2067 : }
2068 :
2069 0 : if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2070 0 : return -1;
2071 :
2072 0 : if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2073 0 : return -1;
2074 0 : if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2075 0 : return -1;
2076 :
2077 0 : self->reader = (buffered *) PyObject_CallFunction(
2078 : (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2079 0 : if (self->reader == NULL)
2080 0 : return -1;
2081 :
2082 0 : self->writer = (buffered *) PyObject_CallFunction(
2083 : (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2084 0 : if (self->writer == NULL) {
2085 0 : Py_CLEAR(self->reader);
2086 0 : return -1;
2087 : }
2088 :
2089 0 : return 0;
2090 : }
2091 :
2092 : static int
2093 0 : bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2094 : {
2095 0 : Py_VISIT(self->dict);
2096 0 : return 0;
2097 : }
2098 :
2099 : static int
2100 0 : bufferedrwpair_clear(rwpair *self)
2101 : {
2102 0 : Py_CLEAR(self->reader);
2103 0 : Py_CLEAR(self->writer);
2104 0 : Py_CLEAR(self->dict);
2105 0 : return 0;
2106 : }
2107 :
2108 : static void
2109 0 : bufferedrwpair_dealloc(rwpair *self)
2110 : {
2111 0 : _PyObject_GC_UNTRACK(self);
2112 0 : if (self->weakreflist != NULL)
2113 0 : PyObject_ClearWeakRefs((PyObject *)self);
2114 0 : Py_CLEAR(self->reader);
2115 0 : Py_CLEAR(self->writer);
2116 0 : Py_CLEAR(self->dict);
2117 0 : Py_TYPE(self)->tp_free((PyObject *) self);
2118 0 : }
2119 :
2120 : static PyObject *
2121 0 : _forward_call(buffered *self, const char *name, PyObject *args)
2122 : {
2123 : PyObject *func, *ret;
2124 0 : if (self == NULL) {
2125 0 : PyErr_SetString(PyExc_ValueError,
2126 : "I/O operation on uninitialized object");
2127 0 : return NULL;
2128 : }
2129 :
2130 0 : func = PyObject_GetAttrString((PyObject *)self, name);
2131 0 : if (func == NULL) {
2132 0 : PyErr_SetString(PyExc_AttributeError, name);
2133 0 : return NULL;
2134 : }
2135 :
2136 0 : ret = PyObject_CallObject(func, args);
2137 0 : Py_DECREF(func);
2138 0 : return ret;
2139 : }
2140 :
2141 : static PyObject *
2142 0 : bufferedrwpair_read(rwpair *self, PyObject *args)
2143 : {
2144 0 : return _forward_call(self->reader, "read", args);
2145 : }
2146 :
2147 : static PyObject *
2148 0 : bufferedrwpair_peek(rwpair *self, PyObject *args)
2149 : {
2150 0 : return _forward_call(self->reader, "peek", args);
2151 : }
2152 :
2153 : static PyObject *
2154 0 : bufferedrwpair_read1(rwpair *self, PyObject *args)
2155 : {
2156 0 : return _forward_call(self->reader, "read1", args);
2157 : }
2158 :
2159 : static PyObject *
2160 0 : bufferedrwpair_readinto(rwpair *self, PyObject *args)
2161 : {
2162 0 : return _forward_call(self->reader, "readinto", args);
2163 : }
2164 :
2165 : static PyObject *
2166 0 : bufferedrwpair_write(rwpair *self, PyObject *args)
2167 : {
2168 0 : return _forward_call(self->writer, "write", args);
2169 : }
2170 :
2171 : static PyObject *
2172 0 : bufferedrwpair_flush(rwpair *self, PyObject *args)
2173 : {
2174 0 : return _forward_call(self->writer, "flush", args);
2175 : }
2176 :
2177 : static PyObject *
2178 0 : bufferedrwpair_readable(rwpair *self, PyObject *args)
2179 : {
2180 0 : return _forward_call(self->reader, "readable", args);
2181 : }
2182 :
2183 : static PyObject *
2184 0 : bufferedrwpair_writable(rwpair *self, PyObject *args)
2185 : {
2186 0 : return _forward_call(self->writer, "writable", args);
2187 : }
2188 :
2189 : static PyObject *
2190 0 : bufferedrwpair_close(rwpair *self, PyObject *args)
2191 : {
2192 0 : PyObject *exc = NULL, *val, *tb;
2193 0 : PyObject *ret = _forward_call(self->writer, "close", args);
2194 0 : if (ret == NULL)
2195 0 : PyErr_Fetch(&exc, &val, &tb);
2196 : else
2197 0 : Py_DECREF(ret);
2198 0 : ret = _forward_call(self->reader, "close", args);
2199 0 : if (exc != NULL) {
2200 0 : if (ret != NULL) {
2201 0 : Py_CLEAR(ret);
2202 0 : PyErr_Restore(exc, val, tb);
2203 : }
2204 : else {
2205 0 : Py_DECREF(exc);
2206 0 : Py_XDECREF(val);
2207 0 : Py_XDECREF(tb);
2208 : }
2209 : }
2210 0 : return ret;
2211 : }
2212 :
2213 : static PyObject *
2214 0 : bufferedrwpair_isatty(rwpair *self, PyObject *args)
2215 : {
2216 0 : PyObject *ret = _forward_call(self->writer, "isatty", args);
2217 :
2218 0 : if (ret != Py_False) {
2219 : /* either True or exception */
2220 0 : return ret;
2221 : }
2222 0 : Py_DECREF(ret);
2223 :
2224 0 : return _forward_call(self->reader, "isatty", args);
2225 : }
2226 :
2227 : static PyObject *
2228 0 : bufferedrwpair_closed_get(rwpair *self, void *context)
2229 : {
2230 0 : if (self->writer == NULL) {
2231 0 : PyErr_SetString(PyExc_RuntimeError,
2232 : "the BufferedRWPair object is being garbage-collected");
2233 0 : return NULL;
2234 : }
2235 0 : return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2236 : }
2237 :
2238 : static PyMethodDef bufferedrwpair_methods[] = {
2239 : {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2240 : {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2241 : {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2242 : {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2243 :
2244 : {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2245 : {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2246 :
2247 : {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2248 : {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2249 :
2250 : {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2251 : {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2252 :
2253 : {NULL, NULL}
2254 : };
2255 :
2256 : static PyGetSetDef bufferedrwpair_getset[] = {
2257 : {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2258 : {NULL}
2259 : };
2260 :
2261 : PyTypeObject PyBufferedRWPair_Type = {
2262 : PyVarObject_HEAD_INIT(NULL, 0)
2263 : "_io.BufferedRWPair", /*tp_name*/
2264 : sizeof(rwpair), /*tp_basicsize*/
2265 : 0, /*tp_itemsize*/
2266 : (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2267 : 0, /*tp_print*/
2268 : 0, /*tp_getattr*/
2269 : 0, /*tp_setattr*/
2270 : 0, /*tp_compare */
2271 : 0, /*tp_repr*/
2272 : 0, /*tp_as_number*/
2273 : 0, /*tp_as_sequence*/
2274 : 0, /*tp_as_mapping*/
2275 : 0, /*tp_hash */
2276 : 0, /*tp_call*/
2277 : 0, /*tp_str*/
2278 : 0, /*tp_getattro*/
2279 : 0, /*tp_setattro*/
2280 : 0, /*tp_as_buffer*/
2281 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2282 : | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2283 : bufferedrwpair_doc, /* tp_doc */
2284 : (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2285 : (inquiry)bufferedrwpair_clear, /* tp_clear */
2286 : 0, /* tp_richcompare */
2287 : offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2288 : 0, /* tp_iter */
2289 : 0, /* tp_iternext */
2290 : bufferedrwpair_methods, /* tp_methods */
2291 : 0, /* tp_members */
2292 : bufferedrwpair_getset, /* tp_getset */
2293 : 0, /* tp_base */
2294 : 0, /* tp_dict */
2295 : 0, /* tp_descr_get */
2296 : 0, /* tp_descr_set */
2297 : offsetof(rwpair, dict), /* tp_dictoffset */
2298 : (initproc)bufferedrwpair_init, /* tp_init */
2299 : 0, /* tp_alloc */
2300 : PyType_GenericNew, /* tp_new */
2301 : };
2302 :
2303 :
2304 :
2305 : /*
2306 : * BufferedRandom
2307 : */
2308 :
2309 : PyDoc_STRVAR(bufferedrandom_doc,
2310 : "A buffered interface to random access streams.\n"
2311 : "\n"
2312 : "The constructor creates a reader and writer for a seekable stream,\n"
2313 : "raw, given in the first argument. If the buffer_size is omitted it\n"
2314 : "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2315 : );
2316 :
2317 : static int
2318 0 : bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2319 : {
2320 0 : char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2321 0 : Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2322 0 : Py_ssize_t max_buffer_size = -234;
2323 : PyObject *raw;
2324 :
2325 0 : self->ok = 0;
2326 0 : self->detached = 0;
2327 :
2328 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedRandom", kwlist,
2329 : &raw, &buffer_size, &max_buffer_size)) {
2330 0 : return -1;
2331 : }
2332 :
2333 0 : if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2334 0 : return -1;
2335 :
2336 0 : if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2337 0 : return -1;
2338 0 : if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2339 0 : return -1;
2340 0 : if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2341 0 : return -1;
2342 :
2343 0 : Py_INCREF(raw);
2344 0 : Py_XSETREF(self->raw, raw);
2345 0 : self->buffer_size = buffer_size;
2346 0 : self->readable = 1;
2347 0 : self->writable = 1;
2348 :
2349 0 : if (_buffered_init(self) < 0)
2350 0 : return -1;
2351 0 : _bufferedreader_reset_buf(self);
2352 0 : _bufferedwriter_reset_buf(self);
2353 0 : self->pos = 0;
2354 :
2355 0 : self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2356 0 : Py_TYPE(raw) == &PyFileIO_Type);
2357 :
2358 0 : self->ok = 1;
2359 0 : return 0;
2360 : }
2361 :
2362 : static PyMethodDef bufferedrandom_methods[] = {
2363 : /* BufferedIOMixin methods */
2364 : {"close", (PyCFunction)buffered_close, METH_NOARGS},
2365 : {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2366 : {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2367 : {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2368 : {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2369 : {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2370 : {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2371 :
2372 : {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2373 :
2374 : {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2375 : {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2376 : {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2377 : {"read", (PyCFunction)buffered_read, METH_VARARGS},
2378 : {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2379 : {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2380 : {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2381 : {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2382 : {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2383 : {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2384 : {NULL, NULL}
2385 : };
2386 :
2387 : static PyMemberDef bufferedrandom_members[] = {
2388 : {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2389 : {NULL}
2390 : };
2391 :
2392 : static PyGetSetDef bufferedrandom_getset[] = {
2393 : {"closed", (getter)buffered_closed_get, NULL, NULL},
2394 : {"name", (getter)buffered_name_get, NULL, NULL},
2395 : {"mode", (getter)buffered_mode_get, NULL, NULL},
2396 : {NULL}
2397 : };
2398 :
2399 :
2400 : PyTypeObject PyBufferedRandom_Type = {
2401 : PyVarObject_HEAD_INIT(NULL, 0)
2402 : "_io.BufferedRandom", /*tp_name*/
2403 : sizeof(buffered), /*tp_basicsize*/
2404 : 0, /*tp_itemsize*/
2405 : (destructor)buffered_dealloc, /*tp_dealloc*/
2406 : 0, /*tp_print*/
2407 : 0, /*tp_getattr*/
2408 : 0, /*tp_setattr*/
2409 : 0, /*tp_compare */
2410 : (reprfunc)buffered_repr, /*tp_repr*/
2411 : 0, /*tp_as_number*/
2412 : 0, /*tp_as_sequence*/
2413 : 0, /*tp_as_mapping*/
2414 : 0, /*tp_hash */
2415 : 0, /*tp_call*/
2416 : 0, /*tp_str*/
2417 : 0, /*tp_getattro*/
2418 : 0, /*tp_setattro*/
2419 : 0, /*tp_as_buffer*/
2420 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2421 : | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2422 : bufferedrandom_doc, /* tp_doc */
2423 : (traverseproc)buffered_traverse, /* tp_traverse */
2424 : (inquiry)buffered_clear, /* tp_clear */
2425 : 0, /* tp_richcompare */
2426 : offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2427 : 0, /* tp_iter */
2428 : (iternextfunc)buffered_iternext, /* tp_iternext */
2429 : bufferedrandom_methods, /* tp_methods */
2430 : bufferedrandom_members, /* tp_members */
2431 : bufferedrandom_getset, /* tp_getset */
2432 : 0, /* tp_base */
2433 : 0, /*tp_dict*/
2434 : 0, /* tp_descr_get */
2435 : 0, /* tp_descr_set */
2436 : offsetof(buffered, dict), /*tp_dictoffset*/
2437 : (initproc)bufferedrandom_init, /* tp_init */
2438 : 0, /* tp_alloc */
2439 : PyType_GenericNew, /* tp_new */
2440 : };
2441 :
|