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