blob: bb52a46f1d40f1c3b74a74d490734ccf3f1ee61f [file] [log] [blame]
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001/*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
Antoine Pitrou3486a982011-05-12 01:57:53 +02003
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00004 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
Antoine Pitrou3486a982011-05-12 01:57:53 +02006
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00007 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
Martin v. Löwisbd928fe2011-10-14 10:20:37 +020016_Py_IDENTIFIER(close);
17_Py_IDENTIFIER(_dealloc_warn);
18_Py_IDENTIFIER(flush);
19_Py_IDENTIFIER(isatty);
Martin v. Löwis767046a2011-10-14 15:35:36 +020020_Py_IDENTIFIER(mode);
21_Py_IDENTIFIER(name);
Martin v. Löwisbd928fe2011-10-14 10:20:37 +020022_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);
Martin v. Löwisafe55bb2011-10-09 10:38:36 +020029
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000030/*
31 * BufferedIOBase class, inherits from IOBase.
32 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000033PyDoc_STRVAR(bufferediobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000034 "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
49static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000050bufferediobase_readinto(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000051{
52 Py_buffer buf;
53 Py_ssize_t len;
54 PyObject *data;
Martin v. Löwisbd928fe2011-10-14 10:20:37 +020055 _Py_IDENTIFIER(read);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000056
57 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
58 return NULL;
59 }
60
Martin v. Löwisafe55bb2011-10-09 10:38:36 +020061 data = _PyObject_CallMethodId(self, &PyId_read, "n", buf.len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000062 if (data == NULL)
63 goto error;
64
65 if (!PyBytes_Check(data)) {
66 Py_DECREF(data);
67 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
68 goto error;
69 }
70
71 len = Py_SIZE(data);
72 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
73
74 PyBuffer_Release(&buf);
75 Py_DECREF(data);
76
77 return PyLong_FromSsize_t(len);
78
79 error:
80 PyBuffer_Release(&buf);
81 return NULL;
82}
83
84static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000085bufferediobase_unsupported(const char *message)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000086{
87 PyErr_SetString(IO_STATE->unsupported_operation, message);
88 return NULL;
89}
90
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000091PyDoc_STRVAR(bufferediobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +000092 "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
97static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000098bufferediobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +000099{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000100 return bufferediobase_unsupported("detach");
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000101}
102
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000103PyDoc_STRVAR(bufferediobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000104 "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
121static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000122bufferediobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000123{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000124 return bufferediobase_unsupported("read");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000125}
126
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000127PyDoc_STRVAR(bufferediobase_read1_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000128 "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
134static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000135bufferediobase_read1(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000136{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000137 return bufferediobase_unsupported("read1");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000138}
139
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000140PyDoc_STRVAR(bufferediobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000141 "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
149static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000150bufferediobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000151{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000152 return bufferediobase_unsupported("write");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000153}
154
155
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000156static 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},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000162 {NULL, NULL}
163};
164
165PyTypeObject 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*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000186 bufferediobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000187 0, /* tp_traverse */
188 0, /* tp_clear */
189 0, /* tp_richcompare */
190 0, /* tp_weaklistoffset */
191 0, /* tp_iter */
192 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000193 bufferediobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000194 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};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000205
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000206
207typedef struct {
208 PyObject_HEAD
209
210 PyObject *raw;
211 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000212 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000213 int readable;
214 int writable;
Antoine Pitroue033e062010-10-29 10:38:18 +0000215 int deallocating;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200216
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000217 /* 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;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000220
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
Georg Brandldfd73442009-04-05 11:47:34 +0000241#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000242 PyThread_type_lock lock;
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000243 volatile long owner;
Georg Brandldfd73442009-04-05 11:47:34 +0000244#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000245
246 Py_ssize_t buffer_size;
247 Py_ssize_t buffer_mask;
248
249 PyObject *dict;
250 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000251} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000252
253/*
254 Implementation notes:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200255
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000256 * 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
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000265 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000266 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000267 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
268 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000269
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.
Antoine Pitrou3486a982011-05-12 01:57:53 +0200273
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000274*/
275
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000276/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000277
Georg Brandldfd73442009-04-05 11:47:34 +0000278#ifdef WITH_THREAD
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000279
280static int
281_enter_buffered_busy(buffered *self)
282{
283 if (self->owner == PyThread_get_thread_ident()) {
284 PyErr_Format(PyExc_RuntimeError,
285 "reentrant call inside %R", self);
286 return 0;
Antoine Pitrou5800b272009-11-01 12:05:48 +0000287 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000288 Py_BEGIN_ALLOW_THREADS
289 PyThread_acquire_lock(self->lock, 1);
290 Py_END_ALLOW_THREADS
291 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) )
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000298
299#define LEAVE_BUFFERED(self) \
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000300 do { \
301 self->owner = 0; \
302 PyThread_release_lock(self->lock); \
303 } while(0);
304
Georg Brandldfd73442009-04-05 11:47:34 +0000305#else
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000306#define ENTER_BUFFERED(self) 1
Georg Brandldfd73442009-04-05 11:47:34 +0000307#define LEAVE_BUFFERED(self)
308#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000309
310#define CHECK_INITIALIZED(self) \
311 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000312 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 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000319 return NULL; \
320 }
321
322#define CHECK_INITIALIZED_INT(self) \
323 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000324 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 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000331 return -1; \
332 }
333
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000334#define IS_CLOSED(self) \
335 (self->fast_closed_checks \
336 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000337 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000338
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
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000346#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) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000368 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000369
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
376static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000377buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000378{
Antoine Pitroue033e062010-10-29 10:38:18 +0000379 self->deallocating = 1;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000380 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
381 return;
382 _PyObject_GC_UNTRACK(self);
383 self->ok = 0;
384 if (self->weakreflist != NULL)
385 PyObject_ClearWeakRefs((PyObject *)self);
386 Py_CLEAR(self->raw);
387 if (self->buffer) {
388 PyMem_Free(self->buffer);
389 self->buffer = NULL;
390 }
Georg Brandldfd73442009-04-05 11:47:34 +0000391#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000392 if (self->lock) {
393 PyThread_free_lock(self->lock);
394 self->lock = NULL;
395 }
Georg Brandldfd73442009-04-05 11:47:34 +0000396#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000397 Py_CLEAR(self->dict);
398 Py_TYPE(self)->tp_free((PyObject *)self);
399}
400
401static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000402buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000403{
404 Py_VISIT(self->raw);
405 Py_VISIT(self->dict);
406 return 0;
407}
408
409static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000410buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000411{
412 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
413 return -1;
414 self->ok = 0;
415 Py_CLEAR(self->raw);
416 Py_CLEAR(self->dict);
417 return 0;
418}
419
Antoine Pitroue033e062010-10-29 10:38:18 +0000420/* Because this can call arbitrary code, it shouldn't be called when
421 the refcount is 0 (that is, not directly from tp_dealloc unless
422 the refcount has been temporarily re-incremented). */
Matthias Klosebee33162010-11-16 20:07:51 +0000423static PyObject *
Antoine Pitroue033e062010-10-29 10:38:18 +0000424buffered_dealloc_warn(buffered *self, PyObject *source)
425{
426 if (self->ok && self->raw) {
427 PyObject *r;
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200428 r = _PyObject_CallMethodId(self->raw, &PyId__dealloc_warn, "O", source);
Antoine Pitroue033e062010-10-29 10:38:18 +0000429 if (r)
430 Py_DECREF(r);
431 else
432 PyErr_Clear();
433 }
434 Py_RETURN_NONE;
435}
436
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000437/*
438 * _BufferedIOMixin methods
439 * This is not a class, just a collection of methods that will be reused
440 * by BufferedReader and BufferedWriter
441 */
442
443/* Flush and close */
444
445static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000446buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000447{
448 CHECK_INITIALIZED(self)
449 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
450}
451
452static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000453buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000454{
455 int closed;
456 PyObject *res;
457 CHECK_INITIALIZED_INT(self)
458 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
459 if (res == NULL)
460 return -1;
461 closed = PyObject_IsTrue(res);
462 Py_DECREF(res);
463 return closed;
464}
465
466static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000467buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000468{
469 CHECK_INITIALIZED(self)
470 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
471}
472
473static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000474buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000475{
476 PyObject *res = NULL;
477 int r;
478
479 CHECK_INITIALIZED(self)
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000480 if (!ENTER_BUFFERED(self))
481 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000482
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000483 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000484 if (r < 0)
485 goto end;
486 if (r > 0) {
487 res = Py_None;
488 Py_INCREF(res);
489 goto end;
490 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000491
492 if (self->deallocating) {
493 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
494 if (r)
495 Py_DECREF(r);
496 else
497 PyErr_Clear();
498 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000499 /* flush() will most probably re-take the lock, so drop it first */
500 LEAVE_BUFFERED(self)
501 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000502 if (!ENTER_BUFFERED(self))
503 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000504 if (res == NULL) {
Antoine Pitrou6be88762010-05-03 16:48:20 +0000505 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000506 }
507 Py_XDECREF(res);
508
509 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
510
511end:
512 LEAVE_BUFFERED(self)
513 return res;
514}
515
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000516/* detach */
517
518static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000519buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000520{
521 PyObject *raw, *res;
522 CHECK_INITIALIZED(self)
523 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
524 if (res == NULL)
525 return NULL;
526 Py_DECREF(res);
527 raw = self->raw;
528 self->raw = NULL;
529 self->detached = 1;
530 self->ok = 0;
531 return raw;
532}
533
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000534/* Inquiries */
535
536static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000537buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000538{
539 CHECK_INITIALIZED(self)
540 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
541}
542
543static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000544buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000545{
546 CHECK_INITIALIZED(self)
547 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
548}
549
550static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000551buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000552{
553 CHECK_INITIALIZED(self)
554 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
555}
556
557static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000558buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000559{
560 CHECK_INITIALIZED(self)
Martin v. Löwis767046a2011-10-14 15:35:36 +0200561 return _PyObject_GetAttrId(self->raw, &PyId_name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000562}
563
564static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000565buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000566{
567 CHECK_INITIALIZED(self)
Martin v. Löwis767046a2011-10-14 15:35:36 +0200568 return _PyObject_GetAttrId(self->raw, &PyId_mode);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000569}
570
571/* Lower-level APIs */
572
573static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000574buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000575{
576 CHECK_INITIALIZED(self)
577 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
578}
579
580static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000581buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000582{
583 CHECK_INITIALIZED(self)
584 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
585}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000586
Antoine Pitrou243757e2010-11-05 21:15:39 +0000587/* Serialization */
588
589static PyObject *
590buffered_getstate(buffered *self, PyObject *args)
591{
592 PyErr_Format(PyExc_TypeError,
593 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
594 return NULL;
595}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000596
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000597/* Forward decls */
598static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000599_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000600static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000601_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000602static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000603_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000604static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000605_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000606static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +0200607_bufferedreader_peek_unlocked(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000608static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000609_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000610static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000611_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000612static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000613_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200614static Py_ssize_t
615_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000616
617/*
618 * Helpers
619 */
620
621/* Returns the address of the `written` member if a BlockingIOError was
622 raised, NULL otherwise. The error is always re-raised. */
623static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000624_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000625{
626 PyObject *t, *v, *tb;
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200627 PyOSErrorObject *err;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000628
629 PyErr_Fetch(&t, &v, &tb);
630 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
631 PyErr_Restore(t, v, tb);
632 return NULL;
633 }
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200634 err = (PyOSErrorObject *) v;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000635 /* TODO: sanity check (err->written >= 0) */
636 PyErr_Restore(t, v, tb);
637 return &err->written;
638}
639
640static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000641_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000642{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000643 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000644 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000645 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
646 if (res == NULL)
647 return -1;
648 n = PyNumber_AsOff_t(res, PyExc_ValueError);
649 Py_DECREF(res);
650 if (n < 0) {
651 if (!PyErr_Occurred())
652 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000653 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200654 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000655 return -1;
656 }
657 self->abs_pos = n;
658 return n;
659}
660
661static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000662_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000663{
664 PyObject *res, *posobj, *whenceobj;
665 Py_off_t n;
666
667 posobj = PyLong_FromOff_t(target);
668 if (posobj == NULL)
669 return -1;
670 whenceobj = PyLong_FromLong(whence);
671 if (whenceobj == NULL) {
672 Py_DECREF(posobj);
673 return -1;
674 }
675 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
676 posobj, whenceobj, NULL);
677 Py_DECREF(posobj);
678 Py_DECREF(whenceobj);
679 if (res == NULL)
680 return -1;
681 n = PyNumber_AsOff_t(res, PyExc_ValueError);
682 Py_DECREF(res);
683 if (n < 0) {
684 if (!PyErr_Occurred())
685 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000686 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200687 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000688 return -1;
689 }
690 self->abs_pos = n;
691 return n;
692}
693
694static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000695_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000696{
697 Py_ssize_t n;
698 if (self->buffer_size <= 0) {
699 PyErr_SetString(PyExc_ValueError,
700 "buffer size must be strictly positive");
701 return -1;
702 }
703 if (self->buffer)
704 PyMem_Free(self->buffer);
705 self->buffer = PyMem_Malloc(self->buffer_size);
706 if (self->buffer == NULL) {
707 PyErr_NoMemory();
708 return -1;
709 }
Georg Brandldfd73442009-04-05 11:47:34 +0000710#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000711 if (self->lock)
712 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000713 self->lock = PyThread_allocate_lock();
714 if (self->lock == NULL) {
715 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
716 return -1;
717 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000718 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000719#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000720 /* Find out whether buffer_size is a power of 2 */
721 /* XXX is this optimization useful? */
722 for (n = self->buffer_size - 1; n & 1; n >>= 1)
723 ;
724 if (n == 0)
725 self->buffer_mask = self->buffer_size - 1;
726 else
727 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000728 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000729 PyErr_Clear();
730 return 0;
731}
732
Antoine Pitrou707ce822011-02-25 21:24:11 +0000733/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
734 clears the error indicator), 0 otherwise.
735 Should only be called when PyErr_Occurred() is true.
736*/
737static int
738_trap_eintr(void)
739{
740 static PyObject *eintr_int = NULL;
741 PyObject *typ, *val, *tb;
742 PyEnvironmentErrorObject *env_err;
743
744 if (eintr_int == NULL) {
745 eintr_int = PyLong_FromLong(EINTR);
746 assert(eintr_int != NULL);
747 }
748 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
749 return 0;
750 PyErr_Fetch(&typ, &val, &tb);
751 PyErr_NormalizeException(&typ, &val, &tb);
752 env_err = (PyEnvironmentErrorObject *) val;
753 assert(env_err != NULL);
754 if (env_err->myerrno != NULL &&
755 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
756 Py_DECREF(typ);
757 Py_DECREF(val);
758 Py_XDECREF(tb);
759 return 1;
760 }
761 /* This silences any error set by PyObject_RichCompareBool() */
762 PyErr_Restore(typ, val, tb);
763 return 0;
764}
765
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000766/*
767 * Shared methods and wrappers
768 */
769
770static PyObject *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200771buffered_flush_and_rewind_unlocked(buffered *self)
772{
773 PyObject *res;
774
775 res = _bufferedwriter_flush_unlocked(self, 0);
776 if (res == NULL)
777 return NULL;
778 Py_DECREF(res);
779
780 if (self->readable) {
781 /* Rewind the raw stream so that its position corresponds to
782 the current logical position. */
783 Py_off_t n;
784 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
785 _bufferedreader_reset_buf(self);
786 if (n == -1)
787 return NULL;
788 }
789 Py_RETURN_NONE;
790}
791
792static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000793buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000794{
795 PyObject *res;
796
797 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000798 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000799
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000800 if (!ENTER_BUFFERED(self))
801 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200802 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000803 LEAVE_BUFFERED(self)
804
805 return res;
806}
807
808static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000809buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000810{
811 Py_ssize_t n = 0;
812 PyObject *res = NULL;
813
814 CHECK_INITIALIZED(self)
815 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
816 return NULL;
817 }
818
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000819 if (!ENTER_BUFFERED(self))
820 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000821
822 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200823 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000824 if (res == NULL)
825 goto end;
826 Py_CLEAR(res);
827 }
Victor Stinnerbc93a112011-06-01 00:01:24 +0200828 res = _bufferedreader_peek_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000829
830end:
831 LEAVE_BUFFERED(self)
832 return res;
833}
834
835static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000836buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000837{
838 Py_ssize_t n = -1;
839 PyObject *res;
840
841 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000842 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000843 return NULL;
844 }
845 if (n < -1) {
846 PyErr_SetString(PyExc_ValueError,
847 "read length must be positive or -1");
848 return NULL;
849 }
850
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000851 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000852
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000853 if (n == -1) {
854 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000855 if (!ENTER_BUFFERED(self))
856 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000857 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000858 }
859 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000860 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200861 if (res != Py_None)
862 return res;
863 Py_DECREF(res);
864 if (!ENTER_BUFFERED(self))
865 return NULL;
866 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000867 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000868
Antoine Pitroue05565e2011-08-20 14:39:23 +0200869 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000870 return res;
871}
872
873static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000874buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000875{
876 Py_ssize_t n, have, r;
877 PyObject *res = NULL;
878
879 CHECK_INITIALIZED(self)
880 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
881 return NULL;
882 }
883
884 if (n < 0) {
885 PyErr_SetString(PyExc_ValueError,
886 "read length must be positive");
887 return NULL;
888 }
889 if (n == 0)
890 return PyBytes_FromStringAndSize(NULL, 0);
891
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000892 /* Return up to n bytes. If at least one byte is buffered, we
893 only return buffered bytes. Otherwise, we do one raw read. */
894
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000895 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
896 if (have > 0) {
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100897 n = Py_MIN(have, n);
898 res = _bufferedreader_read_fast(self, n);
899 assert(res != Py_None);
900 return res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000901 }
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100902 res = PyBytes_FromStringAndSize(NULL, n);
903 if (res == NULL)
904 return NULL;
905 if (!ENTER_BUFFERED(self)) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200906 Py_DECREF(res);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100907 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200908 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000909 _bufferedreader_reset_buf(self);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100910 r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
911 LEAVE_BUFFERED(self)
912 if (r == -1) {
913 Py_DECREF(res);
914 return NULL;
915 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000916 if (r == -2)
917 r = 0;
918 if (n > r)
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100919 _PyBytes_Resize(&res, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000920 return res;
921}
922
923static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000924buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000925{
Antoine Pitrou3486a982011-05-12 01:57:53 +0200926 Py_buffer buf;
927 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000928 PyObject *res = NULL;
929
930 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +0200931
932 if (!PyArg_ParseTuple(args, "w*:readinto", &buf))
933 return NULL;
934
935 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
936 if (n > 0) {
937 if (n >= buf.len) {
938 memcpy(buf.buf, self->buffer + self->pos, buf.len);
939 self->pos += buf.len;
940 res = PyLong_FromSsize_t(buf.len);
941 goto end_unlocked;
942 }
943 memcpy(buf.buf, self->buffer + self->pos, n);
944 self->pos += n;
945 written = n;
946 }
947
948 if (!ENTER_BUFFERED(self))
949 goto end_unlocked;
950
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000951 if (self->writable) {
Antoine Pitroue8bb1a02011-08-20 14:52:04 +0200952 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000953 if (res == NULL)
954 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200955 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000956 }
Antoine Pitrou3486a982011-05-12 01:57:53 +0200957
958 _bufferedreader_reset_buf(self);
959 self->pos = 0;
960
961 for (remaining = buf.len - written;
962 remaining > 0;
963 written += n, remaining -= n) {
964 /* If remaining bytes is larger than internal buffer size, copy
965 * directly into caller's buffer. */
966 if (remaining > self->buffer_size) {
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200967 n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
968 remaining);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200969 }
970 else {
971 n = _bufferedreader_fill_buffer(self);
972 if (n > 0) {
973 if (n > remaining)
974 n = remaining;
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200975 memcpy((char *) buf.buf + written,
976 self->buffer + self->pos, n);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200977 self->pos += n;
978 continue; /* short circuit */
979 }
980 }
981 if (n == 0 || (n == -2 && written > 0))
982 break;
983 if (n < 0) {
984 if (n == -2) {
985 Py_INCREF(Py_None);
986 res = Py_None;
987 }
988 goto end;
989 }
990 }
991 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000992
993end:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200994 LEAVE_BUFFERED(self);
995end_unlocked:
996 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000997 return res;
998}
999
1000static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001001_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001002{
1003 PyObject *res = NULL;
1004 PyObject *chunks = NULL;
1005 Py_ssize_t n, written = 0;
1006 const char *start, *s, *end;
1007
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001008 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001009
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001010 /* First, try to find a line in the buffer. This can run unlocked because
1011 the calls to the C API are simple enough that they can't trigger
1012 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001013 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1014 if (limit >= 0 && n > limit)
1015 n = limit;
1016 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001017 s = memchr(start, '\n', n);
1018 if (s != NULL) {
1019 res = PyBytes_FromStringAndSize(start, s - start + 1);
1020 if (res != NULL)
1021 self->pos += s - start + 1;
1022 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001023 }
1024 if (n == limit) {
1025 res = PyBytes_FromStringAndSize(start, n);
1026 if (res != NULL)
1027 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001028 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001029 }
1030
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001031 if (!ENTER_BUFFERED(self))
1032 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001033
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001034 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001035 chunks = PyList_New(0);
1036 if (chunks == NULL)
1037 goto end;
1038 if (n > 0) {
1039 res = PyBytes_FromStringAndSize(start, n);
1040 if (res == NULL)
1041 goto end;
1042 if (PyList_Append(chunks, res) < 0) {
1043 Py_CLEAR(res);
1044 goto end;
1045 }
1046 Py_CLEAR(res);
1047 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001048 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001049 if (limit >= 0)
1050 limit -= n;
1051 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001052 if (self->writable) {
1053 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1054 if (r == NULL)
1055 goto end;
1056 Py_DECREF(r);
1057 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001058
1059 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001060 _bufferedreader_reset_buf(self);
1061 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001062 if (n == -1)
1063 goto end;
1064 if (n <= 0)
1065 break;
1066 if (limit >= 0 && n > limit)
1067 n = limit;
1068 start = self->buffer;
1069 end = start + n;
1070 s = start;
1071 while (s < end) {
1072 if (*s++ == '\n') {
1073 res = PyBytes_FromStringAndSize(start, s - start);
1074 if (res == NULL)
1075 goto end;
1076 self->pos = s - start;
1077 goto found;
1078 }
1079 }
1080 res = PyBytes_FromStringAndSize(start, n);
1081 if (res == NULL)
1082 goto end;
1083 if (n == limit) {
1084 self->pos = n;
1085 break;
1086 }
1087 if (PyList_Append(chunks, res) < 0) {
1088 Py_CLEAR(res);
1089 goto end;
1090 }
1091 Py_CLEAR(res);
1092 written += n;
1093 if (limit >= 0)
1094 limit -= n;
1095 }
1096found:
1097 if (res != NULL && PyList_Append(chunks, res) < 0) {
1098 Py_CLEAR(res);
1099 goto end;
1100 }
1101 Py_CLEAR(res);
1102 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1103
1104end:
1105 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001106end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001107 Py_XDECREF(chunks);
1108 return res;
1109}
1110
1111static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001112buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001113{
1114 Py_ssize_t limit = -1;
1115
1116 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001117 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001118 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001119 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001120}
1121
1122
1123static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001124buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001125{
1126 Py_off_t pos;
1127
1128 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001129 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001130 if (pos == -1)
1131 return NULL;
1132 pos -= RAW_OFFSET(self);
1133 /* TODO: sanity check (pos >= 0) */
1134 return PyLong_FromOff_t(pos);
1135}
1136
1137static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001138buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001139{
1140 Py_off_t target, n;
1141 int whence = 0;
1142 PyObject *targetobj, *res = NULL;
1143
1144 CHECK_INITIALIZED(self)
1145 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1146 return NULL;
1147 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001148 if (whence < 0 || whence > 2) {
1149 PyErr_Format(PyExc_ValueError,
1150 "whence must be between 0 and 2, not %d", whence);
1151 return NULL;
1152 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001153
1154 CHECK_CLOSED(self, "seek of closed file")
1155
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001156 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1157 return NULL;
1158
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001159 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1160 if (target == -1 && PyErr_Occurred())
1161 return NULL;
1162
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001163 if (whence != 2 && self->readable) {
1164 Py_off_t current, avail;
1165 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001166 so as to return quickly if possible. Also, we needn't take the
1167 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001168 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001169 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1170 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001171 current = RAW_TELL(self);
1172 avail = READAHEAD(self);
1173 if (avail > 0) {
1174 Py_off_t offset;
1175 if (whence == 0)
1176 offset = target - (current - RAW_OFFSET(self));
1177 else
1178 offset = target;
1179 if (offset >= -self->pos && offset <= avail) {
1180 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001181 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001182 }
1183 }
1184 }
1185
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001186 if (!ENTER_BUFFERED(self))
1187 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001188
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001189 /* Fallback: invoke raw seek() method and clear buffer */
1190 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001191 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001192 if (res == NULL)
1193 goto end;
1194 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001195 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001196 }
1197
1198 /* TODO: align on block boundary and read buffer if needed? */
1199 if (whence == 1)
1200 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001201 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001202 if (n == -1)
1203 goto end;
1204 self->raw_pos = -1;
1205 res = PyLong_FromOff_t(n);
1206 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001207 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001208
1209end:
1210 LEAVE_BUFFERED(self)
1211 return res;
1212}
1213
1214static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001215buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001216{
1217 PyObject *pos = Py_None;
1218 PyObject *res = NULL;
1219
1220 CHECK_INITIALIZED(self)
1221 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1222 return NULL;
1223 }
1224
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001225 if (!ENTER_BUFFERED(self))
1226 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001227
1228 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001229 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001230 if (res == NULL)
1231 goto end;
1232 Py_CLEAR(res);
1233 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001234 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1235 if (res == NULL)
1236 goto end;
1237 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001238 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001239 PyErr_Clear();
1240
1241end:
1242 LEAVE_BUFFERED(self)
1243 return res;
1244}
1245
1246static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001247buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001248{
1249 PyObject *line;
1250 PyTypeObject *tp;
1251
1252 CHECK_INITIALIZED(self);
1253
1254 tp = Py_TYPE(self);
1255 if (tp == &PyBufferedReader_Type ||
1256 tp == &PyBufferedRandom_Type) {
1257 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001258 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001259 }
1260 else {
1261 line = PyObject_CallMethodObjArgs((PyObject *)self,
1262 _PyIO_str_readline, NULL);
1263 if (line && !PyBytes_Check(line)) {
1264 PyErr_Format(PyExc_IOError,
1265 "readline() should have returned a bytes object, "
1266 "not '%.200s'", Py_TYPE(line)->tp_name);
1267 Py_DECREF(line);
1268 return NULL;
1269 }
1270 }
1271
1272 if (line == NULL)
1273 return NULL;
1274
1275 if (PyBytes_GET_SIZE(line) == 0) {
1276 /* Reached EOF or would have blocked */
1277 Py_DECREF(line);
1278 return NULL;
1279 }
1280
1281 return line;
1282}
1283
Antoine Pitrou716c4442009-05-23 19:04:03 +00001284static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001285buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001286{
1287 PyObject *nameobj, *res;
1288
Martin v. Löwis767046a2011-10-14 15:35:36 +02001289 nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
Antoine Pitrou716c4442009-05-23 19:04:03 +00001290 if (nameobj == NULL) {
1291 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1292 PyErr_Clear();
1293 else
1294 return NULL;
1295 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1296 }
1297 else {
1298 res = PyUnicode_FromFormat("<%s name=%R>",
1299 Py_TYPE(self)->tp_name, nameobj);
1300 Py_DECREF(nameobj);
1301 }
1302 return res;
1303}
1304
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001305/*
1306 * class BufferedReader
1307 */
1308
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001309PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001310 "Create a new buffered reader using the given readable raw IO object.");
1311
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001312static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001313{
1314 self->read_end = -1;
1315}
1316
1317static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001318bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001319{
1320 char *kwlist[] = {"raw", "buffer_size", NULL};
1321 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1322 PyObject *raw;
1323
1324 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001325 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001326
1327 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1328 &raw, &buffer_size)) {
1329 return -1;
1330 }
1331
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001332 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001333 return -1;
1334
1335 Py_CLEAR(self->raw);
1336 Py_INCREF(raw);
1337 self->raw = raw;
1338 self->buffer_size = buffer_size;
1339 self->readable = 1;
1340 self->writable = 0;
1341
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001342 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001343 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001344 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001345
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001346 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1347 Py_TYPE(raw) == &PyFileIO_Type);
1348
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001349 self->ok = 1;
1350 return 0;
1351}
1352
1353static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001354_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001355{
1356 Py_buffer buf;
1357 PyObject *memobj, *res;
1358 Py_ssize_t n;
1359 /* NOTE: the buffer needn't be released as its object is NULL. */
1360 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1361 return -1;
1362 memobj = PyMemoryView_FromBuffer(&buf);
1363 if (memobj == NULL)
1364 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001365 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1366 occurs so we needn't do it ourselves.
1367 We then retry reading, ignoring the signal if no handler has
1368 raised (see issue #10956).
1369 */
1370 do {
1371 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1372 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001373 Py_DECREF(memobj);
1374 if (res == NULL)
1375 return -1;
1376 if (res == Py_None) {
1377 /* Non-blocking stream would have blocked. Special return code! */
1378 Py_DECREF(res);
1379 return -2;
1380 }
1381 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1382 Py_DECREF(res);
1383 if (n < 0 || n > len) {
1384 PyErr_Format(PyExc_IOError,
1385 "raw readinto() returned invalid length %zd "
1386 "(should have been between 0 and %zd)", n, len);
1387 return -1;
1388 }
1389 if (n > 0 && self->abs_pos != -1)
1390 self->abs_pos += n;
1391 return n;
1392}
1393
1394static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001395_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001396{
1397 Py_ssize_t start, len, n;
1398 if (VALID_READ_BUFFER(self))
1399 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1400 else
1401 start = 0;
1402 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001403 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001404 if (n <= 0)
1405 return n;
1406 self->read_end = start + n;
1407 self->raw_pos = start + n;
1408 return n;
1409}
1410
1411static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001412_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001413{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001414 Py_ssize_t current_size;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001415 PyObject *res, *data = NULL, *chunk, *chunks;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001416
1417 /* First copy what we have in the current buffer. */
1418 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1419 if (current_size) {
1420 data = PyBytes_FromStringAndSize(
1421 self->buffer + self->pos, current_size);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001422 if (data == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001423 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001424 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001425 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001426 /* We're going past the buffer's bounds, flush it */
1427 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001428 res = buffered_flush_and_rewind_unlocked(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001429 if (res == NULL)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001430 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001431 Py_CLEAR(res);
1432 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001433 _bufferedreader_reset_buf(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001434
1435 if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
1436 chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
1437 if (chunk == NULL)
1438 return NULL;
1439 if (chunk != Py_None && !PyBytes_Check(chunk)) {
1440 Py_XDECREF(data);
1441 Py_DECREF(chunk);
1442 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1443 return NULL;
1444 }
1445 if (chunk == Py_None) {
1446 if (current_size == 0)
1447 return chunk;
1448 else {
1449 Py_DECREF(chunk);
1450 return data;
1451 }
1452 }
1453 else if (current_size) {
1454 PyBytes_Concat(&data, chunk);
1455 Py_DECREF(chunk);
1456 if (data == NULL)
1457 return NULL;
1458 return data;
1459 } else
1460 return chunk;
1461 }
1462
1463 chunks = PyList_New(0);
1464 if (chunks == NULL)
1465 return NULL;
1466
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001467 while (1) {
1468 if (data) {
1469 if (PyList_Append(chunks, data) < 0) {
1470 Py_DECREF(data);
1471 Py_DECREF(chunks);
1472 return NULL;
1473 }
1474 Py_DECREF(data);
1475 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001476
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001477 /* Read until EOF or until read() would block. */
1478 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1479 if (data == NULL) {
1480 Py_DECREF(chunks);
1481 return NULL;
1482 }
1483 if (data != Py_None && !PyBytes_Check(data)) {
1484 Py_DECREF(data);
1485 Py_DECREF(chunks);
1486 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1487 return NULL;
1488 }
1489 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1490 if (current_size == 0) {
1491 Py_DECREF(chunks);
1492 return data;
1493 }
1494 else {
1495 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1496 Py_DECREF(data);
1497 Py_DECREF(chunks);
1498 return res;
1499 }
1500 }
1501 current_size += PyBytes_GET_SIZE(data);
1502 if (self->abs_pos != -1)
1503 self->abs_pos += PyBytes_GET_SIZE(data);
1504 }
1505}
1506
1507/* Read n bytes from the buffer if it can, otherwise return None.
1508 This function is simple enough that it can run unlocked. */
1509static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001510_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001511{
1512 Py_ssize_t current_size;
1513
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001514 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1515 if (n <= current_size) {
1516 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001517 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1518 if (res != NULL)
1519 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001520 return res;
1521 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001522 Py_RETURN_NONE;
1523}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001524
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001525/* Generic read function: read from the stream until enough bytes are read,
1526 * or until an EOF occurs or until read() would block.
1527 */
1528static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001529_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001530{
1531 PyObject *res = NULL;
1532 Py_ssize_t current_size, remaining, written;
1533 char *out;
1534
1535 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1536 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001537 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001538
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001539 res = PyBytes_FromStringAndSize(NULL, n);
1540 if (res == NULL)
1541 goto error;
1542 out = PyBytes_AS_STRING(res);
1543 remaining = n;
1544 written = 0;
1545 if (current_size > 0) {
1546 memcpy(out, self->buffer + self->pos, current_size);
1547 remaining -= current_size;
1548 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001549 self->pos += current_size;
1550 }
1551 /* Flush the write buffer if necessary */
1552 if (self->writable) {
1553 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1554 if (r == NULL)
1555 goto error;
1556 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001557 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001558 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001559 while (remaining > 0) {
1560 /* We want to read a whole block at the end into buffer.
1561 If we had readv() we could do this in one pass. */
1562 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1563 if (r == 0)
1564 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001565 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001566 if (r == -1)
1567 goto error;
1568 if (r == 0 || r == -2) {
1569 /* EOF occurred or read() would block. */
1570 if (r == 0 || written > 0) {
1571 if (_PyBytes_Resize(&res, written))
1572 goto error;
1573 return res;
1574 }
1575 Py_DECREF(res);
1576 Py_INCREF(Py_None);
1577 return Py_None;
1578 }
1579 remaining -= r;
1580 written += r;
1581 }
1582 assert(remaining <= self->buffer_size);
1583 self->pos = 0;
1584 self->raw_pos = 0;
1585 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001586 /* NOTE: when the read is satisfied, we avoid issuing any additional
1587 reads, which could block indefinitely (e.g. on a socket).
1588 See issue #9550. */
1589 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001590 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001591 if (r == -1)
1592 goto error;
1593 if (r == 0 || r == -2) {
1594 /* EOF occurred or read() would block. */
1595 if (r == 0 || written > 0) {
1596 if (_PyBytes_Resize(&res, written))
1597 goto error;
1598 return res;
1599 }
1600 Py_DECREF(res);
1601 Py_INCREF(Py_None);
1602 return Py_None;
1603 }
1604 if (remaining > r) {
1605 memcpy(out + written, self->buffer + self->pos, r);
1606 written += r;
1607 self->pos += r;
1608 remaining -= r;
1609 }
1610 else if (remaining > 0) {
1611 memcpy(out + written, self->buffer + self->pos, remaining);
1612 written += remaining;
1613 self->pos += remaining;
1614 remaining = 0;
1615 }
1616 if (remaining == 0)
1617 break;
1618 }
1619
1620 return res;
1621
1622error:
1623 Py_XDECREF(res);
1624 return NULL;
1625}
1626
1627static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +02001628_bufferedreader_peek_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001629{
1630 Py_ssize_t have, r;
1631
1632 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1633 /* Constraints:
1634 1. we don't want to advance the file position.
1635 2. we don't want to lose block alignment, so we can't shift the buffer
1636 to make some place.
1637 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1638 */
1639 if (have > 0) {
1640 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1641 }
1642
1643 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001644 _bufferedreader_reset_buf(self);
1645 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001646 if (r == -1)
1647 return NULL;
1648 if (r == -2)
1649 r = 0;
1650 self->pos = 0;
1651 return PyBytes_FromStringAndSize(self->buffer, r);
1652}
1653
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001654static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001655 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001656 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1657 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1658 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1659 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1660 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1661 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1662 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1663 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001664 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001665 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001666
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001667 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1668 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1669 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001670 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001671 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1672 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1673 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1674 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001675 {NULL, NULL}
1676};
1677
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001678static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001679 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001680 {NULL}
1681};
1682
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001683static PyGetSetDef bufferedreader_getset[] = {
1684 {"closed", (getter)buffered_closed_get, NULL, NULL},
1685 {"name", (getter)buffered_name_get, NULL, NULL},
1686 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001687 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001688};
1689
1690
1691PyTypeObject PyBufferedReader_Type = {
1692 PyVarObject_HEAD_INIT(NULL, 0)
1693 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001694 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001695 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001696 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001697 0, /*tp_print*/
1698 0, /*tp_getattr*/
1699 0, /*tp_setattr*/
1700 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001701 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001702 0, /*tp_as_number*/
1703 0, /*tp_as_sequence*/
1704 0, /*tp_as_mapping*/
1705 0, /*tp_hash */
1706 0, /*tp_call*/
1707 0, /*tp_str*/
1708 0, /*tp_getattro*/
1709 0, /*tp_setattro*/
1710 0, /*tp_as_buffer*/
1711 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1712 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001713 bufferedreader_doc, /* tp_doc */
1714 (traverseproc)buffered_traverse, /* tp_traverse */
1715 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001716 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001717 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001718 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001719 (iternextfunc)buffered_iternext, /* tp_iternext */
1720 bufferedreader_methods, /* tp_methods */
1721 bufferedreader_members, /* tp_members */
1722 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001723 0, /* tp_base */
1724 0, /* tp_dict */
1725 0, /* tp_descr_get */
1726 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001727 offsetof(buffered, dict), /* tp_dictoffset */
1728 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001729 0, /* tp_alloc */
1730 PyType_GenericNew, /* tp_new */
1731};
1732
1733
Benjamin Peterson59406a92009-03-26 17:10:29 +00001734
1735static int
1736complain_about_max_buffer_size(void)
1737{
1738 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1739 "max_buffer_size is deprecated", 1) < 0)
1740 return 0;
1741 return 1;
1742}
1743
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001744/*
1745 * class BufferedWriter
1746 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001747PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001748 "A buffer for a writeable sequential RawIO object.\n"
1749 "\n"
1750 "The constructor creates a BufferedWriter for the given writeable raw\n"
1751 "stream. If the buffer_size is not given, it defaults to\n"
1752 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1753 );
1754
1755static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001756_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001757{
1758 self->write_pos = 0;
1759 self->write_end = -1;
1760}
1761
1762static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001763bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001764{
1765 /* TODO: properly deprecate max_buffer_size */
1766 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1767 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001768 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001769 PyObject *raw;
1770
1771 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001772 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001773
1774 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1775 &raw, &buffer_size, &max_buffer_size)) {
1776 return -1;
1777 }
1778
Benjamin Peterson59406a92009-03-26 17:10:29 +00001779 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1780 return -1;
1781
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001782 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001783 return -1;
1784
1785 Py_CLEAR(self->raw);
1786 Py_INCREF(raw);
1787 self->raw = raw;
1788 self->readable = 0;
1789 self->writable = 1;
1790
1791 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001792 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001793 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001794 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001795 self->pos = 0;
1796
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001797 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1798 Py_TYPE(raw) == &PyFileIO_Type);
1799
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001800 self->ok = 1;
1801 return 0;
1802}
1803
1804static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001805_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001806{
1807 Py_buffer buf;
1808 PyObject *memobj, *res;
1809 Py_ssize_t n;
1810 /* NOTE: the buffer needn't be released as its object is NULL. */
1811 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1812 return -1;
1813 memobj = PyMemoryView_FromBuffer(&buf);
1814 if (memobj == NULL)
1815 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001816 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1817 occurs so we needn't do it ourselves.
1818 We then retry writing, ignoring the signal if no handler has
1819 raised (see issue #10956).
1820 */
1821 do {
1822 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1823 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001824 Py_DECREF(memobj);
1825 if (res == NULL)
1826 return -1;
1827 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1828 Py_DECREF(res);
1829 if (n < 0 || n > len) {
1830 PyErr_Format(PyExc_IOError,
1831 "raw write() returned invalid length %zd "
1832 "(should have been between 0 and %zd)", n, len);
1833 return -1;
1834 }
1835 if (n > 0 && self->abs_pos != -1)
1836 self->abs_pos += n;
1837 return n;
1838}
1839
1840/* `restore_pos` is 1 if we need to restore the raw stream position at
1841 the end, 0 otherwise. */
1842static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001843_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001844{
1845 Py_ssize_t written = 0;
1846 Py_off_t n, rewind;
1847
1848 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1849 goto end;
1850 /* First, rewind */
1851 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1852 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001853 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001854 if (n < 0) {
1855 goto error;
1856 }
1857 self->raw_pos -= rewind;
1858 }
1859 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001860 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001861 self->buffer + self->write_pos,
1862 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1863 Py_off_t, Py_ssize_t));
1864 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001865 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001866 if (w == NULL)
1867 goto error;
1868 self->write_pos += *w;
1869 self->raw_pos = self->write_pos;
1870 written += *w;
1871 *w = written;
1872 /* Already re-raised */
1873 goto error;
1874 }
1875 self->write_pos += n;
1876 self->raw_pos = self->write_pos;
1877 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001878 /* Partial writes can return successfully when interrupted by a
1879 signal (see write(2)). We must run signal handlers before
1880 blocking another time, possibly indefinitely. */
1881 if (PyErr_CheckSignals() < 0)
1882 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001883 }
1884
1885 if (restore_pos) {
1886 Py_off_t forward = rewind - written;
1887 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001888 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001889 if (n < 0) {
1890 goto error;
1891 }
1892 self->raw_pos += forward;
1893 }
1894 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001895 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001896
1897end:
1898 Py_RETURN_NONE;
1899
1900error:
1901 return NULL;
1902}
1903
1904static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001905bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001906{
1907 PyObject *res = NULL;
1908 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001909 Py_ssize_t written, avail, remaining;
1910 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001911
1912 CHECK_INITIALIZED(self)
1913 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1914 return NULL;
1915 }
1916
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001917 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001918 PyErr_SetString(PyExc_ValueError, "write to closed file");
1919 PyBuffer_Release(&buf);
1920 return NULL;
1921 }
1922
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001923 if (!ENTER_BUFFERED(self)) {
1924 PyBuffer_Release(&buf);
1925 return NULL;
1926 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001927
1928 /* Fast path: the data to write can be fully buffered. */
1929 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1930 self->pos = 0;
1931 self->raw_pos = 0;
1932 }
1933 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1934 if (buf.len <= avail) {
1935 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02001936 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001937 self->write_pos = self->pos;
1938 }
1939 ADJUST_POSITION(self, self->pos + buf.len);
1940 if (self->pos > self->write_end)
1941 self->write_end = self->pos;
1942 written = buf.len;
1943 goto end;
1944 }
1945
1946 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001947 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001948 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001949 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001950 if (w == NULL)
1951 goto error;
1952 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001953 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001954 /* Make some place by shifting the buffer. */
1955 assert(VALID_WRITE_BUFFER(self));
1956 memmove(self->buffer, self->buffer + self->write_pos,
1957 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1958 Py_off_t, Py_ssize_t));
1959 self->write_end -= self->write_pos;
1960 self->raw_pos -= self->write_pos;
1961 self->pos -= self->write_pos;
1962 self->write_pos = 0;
1963 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1964 Py_off_t, Py_ssize_t);
1965 if (buf.len <= avail) {
1966 /* Everything can be buffered */
1967 PyErr_Clear();
1968 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1969 self->write_end += buf.len;
1970 written = buf.len;
1971 goto end;
1972 }
1973 /* Buffer as much as possible. */
1974 memcpy(self->buffer + self->write_end, buf.buf, avail);
1975 self->write_end += avail;
1976 /* Already re-raised */
1977 *w = avail;
1978 goto error;
1979 }
1980 Py_CLEAR(res);
1981
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001982 /* Adjust the raw stream position if it is away from the logical stream
1983 position. This happens if the read buffer has been filled but not
1984 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1985 the raw stream by itself).
1986 Fixes issue #6629.
1987 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001988 offset = RAW_OFFSET(self);
1989 if (offset != 0) {
1990 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001991 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001992 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001993 }
1994
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001995 /* Then write buf itself. At this point the buffer has been emptied. */
1996 remaining = buf.len;
1997 written = 0;
1998 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001999 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002000 self, (char *) buf.buf + written, buf.len - written);
2001 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002002 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002003 if (w == NULL)
2004 goto error;
2005 written += *w;
2006 remaining -= *w;
2007 if (remaining > self->buffer_size) {
2008 /* Can't buffer everything, still buffer as much as possible */
2009 memcpy(self->buffer,
2010 (char *) buf.buf + written, self->buffer_size);
2011 self->raw_pos = 0;
2012 ADJUST_POSITION(self, self->buffer_size);
2013 self->write_end = self->buffer_size;
2014 *w = written + self->buffer_size;
2015 /* Already re-raised */
2016 goto error;
2017 }
2018 PyErr_Clear();
2019 break;
2020 }
2021 written += n;
2022 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002023 /* Partial writes can return successfully when interrupted by a
2024 signal (see write(2)). We must run signal handlers before
2025 blocking another time, possibly indefinitely. */
2026 if (PyErr_CheckSignals() < 0)
2027 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002028 }
2029 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002030 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002031 if (remaining > 0) {
2032 memcpy(self->buffer, (char *) buf.buf + written, remaining);
2033 written += remaining;
2034 }
2035 self->write_pos = 0;
2036 /* TODO: sanity check (remaining >= 0) */
2037 self->write_end = remaining;
2038 ADJUST_POSITION(self, remaining);
2039 self->raw_pos = 0;
2040
2041end:
2042 res = PyLong_FromSsize_t(written);
2043
2044error:
2045 LEAVE_BUFFERED(self)
2046 PyBuffer_Release(&buf);
2047 return res;
2048}
2049
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002050static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002051 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002052 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2053 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2054 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2055 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2056 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2057 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2058 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002059 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002060 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002061
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002062 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2063 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2064 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2065 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2066 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002067 {NULL, NULL}
2068};
2069
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002070static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002071 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002072 {NULL}
2073};
2074
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002075static PyGetSetDef bufferedwriter_getset[] = {
2076 {"closed", (getter)buffered_closed_get, NULL, NULL},
2077 {"name", (getter)buffered_name_get, NULL, NULL},
2078 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002079 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002080};
2081
2082
2083PyTypeObject PyBufferedWriter_Type = {
2084 PyVarObject_HEAD_INIT(NULL, 0)
2085 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002086 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002087 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002088 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002089 0, /*tp_print*/
2090 0, /*tp_getattr*/
2091 0, /*tp_setattr*/
2092 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002093 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002094 0, /*tp_as_number*/
2095 0, /*tp_as_sequence*/
2096 0, /*tp_as_mapping*/
2097 0, /*tp_hash */
2098 0, /*tp_call*/
2099 0, /*tp_str*/
2100 0, /*tp_getattro*/
2101 0, /*tp_setattro*/
2102 0, /*tp_as_buffer*/
2103 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2104 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002105 bufferedwriter_doc, /* tp_doc */
2106 (traverseproc)buffered_traverse, /* tp_traverse */
2107 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002108 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002109 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002110 0, /* tp_iter */
2111 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002112 bufferedwriter_methods, /* tp_methods */
2113 bufferedwriter_members, /* tp_members */
2114 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002115 0, /* tp_base */
2116 0, /* tp_dict */
2117 0, /* tp_descr_get */
2118 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002119 offsetof(buffered, dict), /* tp_dictoffset */
2120 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002121 0, /* tp_alloc */
2122 PyType_GenericNew, /* tp_new */
2123};
2124
2125
2126
2127/*
2128 * BufferedRWPair
2129 */
2130
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002131PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002132 "A buffered reader and writer object together.\n"
2133 "\n"
2134 "A buffered reader object and buffered writer object put together to\n"
2135 "form a sequential IO object that can read and write. This is typically\n"
2136 "used with a socket or two-way pipe.\n"
2137 "\n"
2138 "reader and writer are RawIOBase objects that are readable and\n"
2139 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002140 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002141 );
2142
2143/* XXX The usefulness of this (compared to having two separate IO objects) is
2144 * questionable.
2145 */
2146
2147typedef struct {
2148 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002149 buffered *reader;
2150 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002151 PyObject *dict;
2152 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002153} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002154
2155static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002156bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002157{
2158 PyObject *reader, *writer;
2159 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002160 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002161
2162 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2163 &buffer_size, &max_buffer_size)) {
2164 return -1;
2165 }
2166
Benjamin Peterson59406a92009-03-26 17:10:29 +00002167 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2168 return -1;
2169
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002170 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002171 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002172 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002173 return -1;
2174
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002175 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002176 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002177 if (self->reader == NULL)
2178 return -1;
2179
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002180 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002181 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002182 if (self->writer == NULL) {
2183 Py_CLEAR(self->reader);
2184 return -1;
2185 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002186
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002187 return 0;
2188}
2189
2190static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002191bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002192{
2193 Py_VISIT(self->dict);
2194 return 0;
2195}
2196
2197static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002198bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002199{
2200 Py_CLEAR(self->reader);
2201 Py_CLEAR(self->writer);
2202 Py_CLEAR(self->dict);
2203 return 0;
2204}
2205
2206static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002207bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002208{
2209 _PyObject_GC_UNTRACK(self);
2210 Py_CLEAR(self->reader);
2211 Py_CLEAR(self->writer);
2212 Py_CLEAR(self->dict);
2213 Py_TYPE(self)->tp_free((PyObject *) self);
2214}
2215
2216static PyObject *
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002217_forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002218{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002219 PyObject *func = _PyObject_GetAttrId((PyObject *)self, name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002220 PyObject *ret;
2221
2222 if (func == NULL) {
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002223 PyErr_SetString(PyExc_AttributeError, name->string);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002224 return NULL;
2225 }
2226
2227 ret = PyObject_CallObject(func, args);
2228 Py_DECREF(func);
2229 return ret;
2230}
2231
2232static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002233bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002234{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002235 return _forward_call(self->reader, &PyId_read, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002236}
2237
2238static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002239bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002240{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002241 return _forward_call(self->reader, &PyId_peek, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002242}
2243
2244static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002245bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002246{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002247 return _forward_call(self->reader, &PyId_read1, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002248}
2249
2250static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002251bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002252{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002253 return _forward_call(self->reader, &PyId_readinto, args);
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002254}
2255
2256static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002257bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002258{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002259 return _forward_call(self->writer, &PyId_write, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002260}
2261
2262static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002263bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002264{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002265 return _forward_call(self->writer, &PyId_flush, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002266}
2267
2268static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002269bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002270{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002271 return _forward_call(self->reader, &PyId_readable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002272}
2273
2274static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002275bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002276{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002277 return _forward_call(self->writer, &PyId_writable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002278}
2279
2280static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002281bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002282{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002283 PyObject *ret = _forward_call(self->writer, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002284 if (ret == NULL)
2285 return NULL;
2286 Py_DECREF(ret);
2287
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002288 return _forward_call(self->reader, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002289}
2290
2291static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002292bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002293{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002294 PyObject *ret = _forward_call(self->writer, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002295
2296 if (ret != Py_False) {
2297 /* either True or exception */
2298 return ret;
2299 }
2300 Py_DECREF(ret);
2301
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002302 return _forward_call(self->reader, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002303}
2304
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002305static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002306bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002307{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002308 if (self->writer == NULL) {
2309 PyErr_SetString(PyExc_RuntimeError,
2310 "the BufferedRWPair object is being garbage-collected");
2311 return NULL;
2312 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002313 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2314}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002315
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002316static PyMethodDef bufferedrwpair_methods[] = {
2317 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2318 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2319 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2320 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002321
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002322 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2323 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002324
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002325 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2326 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002327
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002328 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2329 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002330
Antoine Pitrou243757e2010-11-05 21:15:39 +00002331 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2332
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002333 {NULL, NULL}
2334};
2335
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002336static PyGetSetDef bufferedrwpair_getset[] = {
2337 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002338 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002339};
2340
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002341PyTypeObject PyBufferedRWPair_Type = {
2342 PyVarObject_HEAD_INIT(NULL, 0)
2343 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002344 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002345 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002346 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002347 0, /*tp_print*/
2348 0, /*tp_getattr*/
2349 0, /*tp_setattr*/
2350 0, /*tp_compare */
2351 0, /*tp_repr*/
2352 0, /*tp_as_number*/
2353 0, /*tp_as_sequence*/
2354 0, /*tp_as_mapping*/
2355 0, /*tp_hash */
2356 0, /*tp_call*/
2357 0, /*tp_str*/
2358 0, /*tp_getattro*/
2359 0, /*tp_setattro*/
2360 0, /*tp_as_buffer*/
2361 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2362 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002363 bufferedrwpair_doc, /* tp_doc */
2364 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2365 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002366 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002367 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002368 0, /* tp_iter */
2369 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002370 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002371 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002372 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002373 0, /* tp_base */
2374 0, /* tp_dict */
2375 0, /* tp_descr_get */
2376 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002377 offsetof(rwpair, dict), /* tp_dictoffset */
2378 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002379 0, /* tp_alloc */
2380 PyType_GenericNew, /* tp_new */
2381};
2382
2383
2384
2385/*
2386 * BufferedRandom
2387 */
2388
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002389PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002390 "A buffered interface to random access streams.\n"
2391 "\n"
2392 "The constructor creates a reader and writer for a seekable stream,\n"
2393 "raw, given in the first argument. If the buffer_size is omitted it\n"
2394 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2395 );
2396
2397static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002398bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002399{
2400 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2401 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002402 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002403 PyObject *raw;
2404
2405 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002406 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002407
2408 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2409 &raw, &buffer_size, &max_buffer_size)) {
2410 return -1;
2411 }
2412
Benjamin Peterson59406a92009-03-26 17:10:29 +00002413 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2414 return -1;
2415
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002416 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002417 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002418 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002419 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002420 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002421 return -1;
2422
2423 Py_CLEAR(self->raw);
2424 Py_INCREF(raw);
2425 self->raw = raw;
2426 self->buffer_size = buffer_size;
2427 self->readable = 1;
2428 self->writable = 1;
2429
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002430 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002431 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002432 _bufferedreader_reset_buf(self);
2433 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002434 self->pos = 0;
2435
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002436 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2437 Py_TYPE(raw) == &PyFileIO_Type);
2438
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002439 self->ok = 1;
2440 return 0;
2441}
2442
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002443static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002444 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002445 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2446 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2447 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2448 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2449 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2450 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2451 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002452 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002453 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002454
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002455 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002456
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002457 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2458 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2459 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2460 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2461 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2462 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2463 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2464 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2465 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002466 {NULL, NULL}
2467};
2468
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002469static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002470 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002471 {NULL}
2472};
2473
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002474static PyGetSetDef bufferedrandom_getset[] = {
2475 {"closed", (getter)buffered_closed_get, NULL, NULL},
2476 {"name", (getter)buffered_name_get, NULL, NULL},
2477 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002478 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002479};
2480
2481
2482PyTypeObject PyBufferedRandom_Type = {
2483 PyVarObject_HEAD_INIT(NULL, 0)
2484 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002485 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002486 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002487 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002488 0, /*tp_print*/
2489 0, /*tp_getattr*/
2490 0, /*tp_setattr*/
2491 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002492 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002493 0, /*tp_as_number*/
2494 0, /*tp_as_sequence*/
2495 0, /*tp_as_mapping*/
2496 0, /*tp_hash */
2497 0, /*tp_call*/
2498 0, /*tp_str*/
2499 0, /*tp_getattro*/
2500 0, /*tp_setattro*/
2501 0, /*tp_as_buffer*/
2502 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2503 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002504 bufferedrandom_doc, /* tp_doc */
2505 (traverseproc)buffered_traverse, /* tp_traverse */
2506 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002507 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002508 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002509 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002510 (iternextfunc)buffered_iternext, /* tp_iternext */
2511 bufferedrandom_methods, /* tp_methods */
2512 bufferedrandom_members, /* tp_members */
2513 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002514 0, /* tp_base */
2515 0, /*tp_dict*/
2516 0, /* tp_descr_get */
2517 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002518 offsetof(buffered, dict), /*tp_dictoffset*/
2519 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002520 0, /* tp_alloc */
2521 PyType_GenericNew, /* tp_new */
2522};