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