blob: dc723b1793673998df4cf6fcc4bd74c4d965339c [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 *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100599_bufferedwriter_flush_unlocked(buffered *);
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
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100621/* Sets the current error to BlockingIOError */
622static void
623_set_BlockingIOError(char *msg, Py_ssize_t written)
624{
625 PyObject *err;
626 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
627 errno, msg, written);
628 if (err)
629 PyErr_SetObject(PyExc_BlockingIOError, err);
630 Py_XDECREF(err);
631}
632
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000633/* Returns the address of the `written` member if a BlockingIOError was
634 raised, NULL otherwise. The error is always re-raised. */
635static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000636_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000637{
638 PyObject *t, *v, *tb;
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200639 PyOSErrorObject *err;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000640
641 PyErr_Fetch(&t, &v, &tb);
642 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
643 PyErr_Restore(t, v, tb);
644 return NULL;
645 }
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200646 err = (PyOSErrorObject *) v;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000647 /* TODO: sanity check (err->written >= 0) */
648 PyErr_Restore(t, v, tb);
649 return &err->written;
650}
651
652static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000653_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000654{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000655 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000656 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000657 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
658 if (res == NULL)
659 return -1;
660 n = PyNumber_AsOff_t(res, PyExc_ValueError);
661 Py_DECREF(res);
662 if (n < 0) {
663 if (!PyErr_Occurred())
664 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000665 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200666 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000667 return -1;
668 }
669 self->abs_pos = n;
670 return n;
671}
672
673static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000674_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000675{
676 PyObject *res, *posobj, *whenceobj;
677 Py_off_t n;
678
679 posobj = PyLong_FromOff_t(target);
680 if (posobj == NULL)
681 return -1;
682 whenceobj = PyLong_FromLong(whence);
683 if (whenceobj == NULL) {
684 Py_DECREF(posobj);
685 return -1;
686 }
687 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
688 posobj, whenceobj, NULL);
689 Py_DECREF(posobj);
690 Py_DECREF(whenceobj);
691 if (res == NULL)
692 return -1;
693 n = PyNumber_AsOff_t(res, PyExc_ValueError);
694 Py_DECREF(res);
695 if (n < 0) {
696 if (!PyErr_Occurred())
697 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000698 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200699 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000700 return -1;
701 }
702 self->abs_pos = n;
703 return n;
704}
705
706static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000707_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000708{
709 Py_ssize_t n;
710 if (self->buffer_size <= 0) {
711 PyErr_SetString(PyExc_ValueError,
712 "buffer size must be strictly positive");
713 return -1;
714 }
715 if (self->buffer)
716 PyMem_Free(self->buffer);
717 self->buffer = PyMem_Malloc(self->buffer_size);
718 if (self->buffer == NULL) {
719 PyErr_NoMemory();
720 return -1;
721 }
Georg Brandldfd73442009-04-05 11:47:34 +0000722#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000723 if (self->lock)
724 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000725 self->lock = PyThread_allocate_lock();
726 if (self->lock == NULL) {
727 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
728 return -1;
729 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000730 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000731#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000732 /* Find out whether buffer_size is a power of 2 */
733 /* XXX is this optimization useful? */
734 for (n = self->buffer_size - 1; n & 1; n >>= 1)
735 ;
736 if (n == 0)
737 self->buffer_mask = self->buffer_size - 1;
738 else
739 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000740 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000741 PyErr_Clear();
742 return 0;
743}
744
Antoine Pitrou707ce822011-02-25 21:24:11 +0000745/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
746 clears the error indicator), 0 otherwise.
747 Should only be called when PyErr_Occurred() is true.
748*/
749static int
750_trap_eintr(void)
751{
752 static PyObject *eintr_int = NULL;
753 PyObject *typ, *val, *tb;
754 PyEnvironmentErrorObject *env_err;
755
756 if (eintr_int == NULL) {
757 eintr_int = PyLong_FromLong(EINTR);
758 assert(eintr_int != NULL);
759 }
760 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
761 return 0;
762 PyErr_Fetch(&typ, &val, &tb);
763 PyErr_NormalizeException(&typ, &val, &tb);
764 env_err = (PyEnvironmentErrorObject *) val;
765 assert(env_err != NULL);
766 if (env_err->myerrno != NULL &&
767 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
768 Py_DECREF(typ);
769 Py_DECREF(val);
770 Py_XDECREF(tb);
771 return 1;
772 }
773 /* This silences any error set by PyObject_RichCompareBool() */
774 PyErr_Restore(typ, val, tb);
775 return 0;
776}
777
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000778/*
779 * Shared methods and wrappers
780 */
781
782static PyObject *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200783buffered_flush_and_rewind_unlocked(buffered *self)
784{
785 PyObject *res;
786
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100787 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200788 if (res == NULL)
789 return NULL;
790 Py_DECREF(res);
791
792 if (self->readable) {
793 /* Rewind the raw stream so that its position corresponds to
794 the current logical position. */
795 Py_off_t n;
796 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
797 _bufferedreader_reset_buf(self);
798 if (n == -1)
799 return NULL;
800 }
801 Py_RETURN_NONE;
802}
803
804static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000805buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000806{
807 PyObject *res;
808
809 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000810 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000811
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000812 if (!ENTER_BUFFERED(self))
813 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200814 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000815 LEAVE_BUFFERED(self)
816
817 return res;
818}
819
820static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000821buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000822{
823 Py_ssize_t n = 0;
824 PyObject *res = NULL;
825
826 CHECK_INITIALIZED(self)
827 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
828 return NULL;
829 }
830
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000831 if (!ENTER_BUFFERED(self))
832 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000833
834 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200835 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000836 if (res == NULL)
837 goto end;
838 Py_CLEAR(res);
839 }
Victor Stinnerbc93a112011-06-01 00:01:24 +0200840 res = _bufferedreader_peek_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000841
842end:
843 LEAVE_BUFFERED(self)
844 return res;
845}
846
847static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000848buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000849{
850 Py_ssize_t n = -1;
851 PyObject *res;
852
853 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000854 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000855 return NULL;
856 }
857 if (n < -1) {
858 PyErr_SetString(PyExc_ValueError,
859 "read length must be positive or -1");
860 return NULL;
861 }
862
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000863 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000864
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000865 if (n == -1) {
866 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000867 if (!ENTER_BUFFERED(self))
868 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000869 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000870 }
871 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000872 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200873 if (res != Py_None)
874 return res;
875 Py_DECREF(res);
876 if (!ENTER_BUFFERED(self))
877 return NULL;
878 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000879 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000880
Antoine Pitroue05565e2011-08-20 14:39:23 +0200881 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000882 return res;
883}
884
885static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000886buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000887{
888 Py_ssize_t n, have, r;
889 PyObject *res = NULL;
890
891 CHECK_INITIALIZED(self)
892 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
893 return NULL;
894 }
895
896 if (n < 0) {
897 PyErr_SetString(PyExc_ValueError,
898 "read length must be positive");
899 return NULL;
900 }
901 if (n == 0)
902 return PyBytes_FromStringAndSize(NULL, 0);
903
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000904 /* Return up to n bytes. If at least one byte is buffered, we
905 only return buffered bytes. Otherwise, we do one raw read. */
906
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000907 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
908 if (have > 0) {
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100909 n = Py_MIN(have, n);
910 res = _bufferedreader_read_fast(self, n);
911 assert(res != Py_None);
912 return res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000913 }
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100914 res = PyBytes_FromStringAndSize(NULL, n);
915 if (res == NULL)
916 return NULL;
917 if (!ENTER_BUFFERED(self)) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200918 Py_DECREF(res);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100919 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200920 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000921 _bufferedreader_reset_buf(self);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100922 r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
923 LEAVE_BUFFERED(self)
924 if (r == -1) {
925 Py_DECREF(res);
926 return NULL;
927 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000928 if (r == -2)
929 r = 0;
930 if (n > r)
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100931 _PyBytes_Resize(&res, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000932 return res;
933}
934
935static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000936buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000937{
Antoine Pitrou3486a982011-05-12 01:57:53 +0200938 Py_buffer buf;
939 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000940 PyObject *res = NULL;
941
942 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +0200943
944 if (!PyArg_ParseTuple(args, "w*:readinto", &buf))
945 return NULL;
946
947 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
948 if (n > 0) {
949 if (n >= buf.len) {
950 memcpy(buf.buf, self->buffer + self->pos, buf.len);
951 self->pos += buf.len;
952 res = PyLong_FromSsize_t(buf.len);
953 goto end_unlocked;
954 }
955 memcpy(buf.buf, self->buffer + self->pos, n);
956 self->pos += n;
957 written = n;
958 }
959
960 if (!ENTER_BUFFERED(self))
961 goto end_unlocked;
962
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000963 if (self->writable) {
Antoine Pitroue8bb1a02011-08-20 14:52:04 +0200964 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000965 if (res == NULL)
966 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200967 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000968 }
Antoine Pitrou3486a982011-05-12 01:57:53 +0200969
970 _bufferedreader_reset_buf(self);
971 self->pos = 0;
972
973 for (remaining = buf.len - written;
974 remaining > 0;
975 written += n, remaining -= n) {
976 /* If remaining bytes is larger than internal buffer size, copy
977 * directly into caller's buffer. */
978 if (remaining > self->buffer_size) {
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200979 n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
980 remaining);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200981 }
982 else {
983 n = _bufferedreader_fill_buffer(self);
984 if (n > 0) {
985 if (n > remaining)
986 n = remaining;
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200987 memcpy((char *) buf.buf + written,
988 self->buffer + self->pos, n);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200989 self->pos += n;
990 continue; /* short circuit */
991 }
992 }
993 if (n == 0 || (n == -2 && written > 0))
994 break;
995 if (n < 0) {
996 if (n == -2) {
997 Py_INCREF(Py_None);
998 res = Py_None;
999 }
1000 goto end;
1001 }
1002 }
1003 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001004
1005end:
Antoine Pitrou3486a982011-05-12 01:57:53 +02001006 LEAVE_BUFFERED(self);
1007end_unlocked:
1008 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001009 return res;
1010}
1011
1012static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001013_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001014{
1015 PyObject *res = NULL;
1016 PyObject *chunks = NULL;
1017 Py_ssize_t n, written = 0;
1018 const char *start, *s, *end;
1019
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001020 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001021
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001022 /* First, try to find a line in the buffer. This can run unlocked because
1023 the calls to the C API are simple enough that they can't trigger
1024 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001025 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1026 if (limit >= 0 && n > limit)
1027 n = limit;
1028 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001029 s = memchr(start, '\n', n);
1030 if (s != NULL) {
1031 res = PyBytes_FromStringAndSize(start, s - start + 1);
1032 if (res != NULL)
1033 self->pos += s - start + 1;
1034 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001035 }
1036 if (n == limit) {
1037 res = PyBytes_FromStringAndSize(start, n);
1038 if (res != NULL)
1039 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001040 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001041 }
1042
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001043 if (!ENTER_BUFFERED(self))
1044 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001045
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001046 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001047 chunks = PyList_New(0);
1048 if (chunks == NULL)
1049 goto end;
1050 if (n > 0) {
1051 res = PyBytes_FromStringAndSize(start, n);
1052 if (res == NULL)
1053 goto end;
1054 if (PyList_Append(chunks, res) < 0) {
1055 Py_CLEAR(res);
1056 goto end;
1057 }
1058 Py_CLEAR(res);
1059 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001060 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001061 if (limit >= 0)
1062 limit -= n;
1063 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001064 if (self->writable) {
1065 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1066 if (r == NULL)
1067 goto end;
1068 Py_DECREF(r);
1069 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001070
1071 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001072 _bufferedreader_reset_buf(self);
1073 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001074 if (n == -1)
1075 goto end;
1076 if (n <= 0)
1077 break;
1078 if (limit >= 0 && n > limit)
1079 n = limit;
1080 start = self->buffer;
1081 end = start + n;
1082 s = start;
1083 while (s < end) {
1084 if (*s++ == '\n') {
1085 res = PyBytes_FromStringAndSize(start, s - start);
1086 if (res == NULL)
1087 goto end;
1088 self->pos = s - start;
1089 goto found;
1090 }
1091 }
1092 res = PyBytes_FromStringAndSize(start, n);
1093 if (res == NULL)
1094 goto end;
1095 if (n == limit) {
1096 self->pos = n;
1097 break;
1098 }
1099 if (PyList_Append(chunks, res) < 0) {
1100 Py_CLEAR(res);
1101 goto end;
1102 }
1103 Py_CLEAR(res);
1104 written += n;
1105 if (limit >= 0)
1106 limit -= n;
1107 }
1108found:
1109 if (res != NULL && PyList_Append(chunks, res) < 0) {
1110 Py_CLEAR(res);
1111 goto end;
1112 }
1113 Py_CLEAR(res);
1114 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1115
1116end:
1117 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001118end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001119 Py_XDECREF(chunks);
1120 return res;
1121}
1122
1123static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001124buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001125{
1126 Py_ssize_t limit = -1;
1127
1128 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001129 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001130 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001131 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001132}
1133
1134
1135static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001136buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001137{
1138 Py_off_t pos;
1139
1140 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001141 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001142 if (pos == -1)
1143 return NULL;
1144 pos -= RAW_OFFSET(self);
1145 /* TODO: sanity check (pos >= 0) */
1146 return PyLong_FromOff_t(pos);
1147}
1148
1149static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001150buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001151{
1152 Py_off_t target, n;
1153 int whence = 0;
1154 PyObject *targetobj, *res = NULL;
1155
1156 CHECK_INITIALIZED(self)
1157 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1158 return NULL;
1159 }
Jesus Cea94363612012-06-22 18:32:07 +02001160
1161 /* Do some error checking instead of trusting OS 'seek()'
1162 ** error detection, just in case.
1163 */
1164 if ((whence < 0 || whence >2)
1165#ifdef SEEK_HOLE
1166 && (whence != SEEK_HOLE)
1167#endif
1168#ifdef SEEK_DATA
1169 && (whence != SEEK_DATA)
1170#endif
1171 ) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001172 PyErr_Format(PyExc_ValueError,
Jesus Cea94363612012-06-22 18:32:07 +02001173 "whence value %d unsupported", whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001174 return NULL;
1175 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001176
1177 CHECK_CLOSED(self, "seek of closed file")
1178
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001179 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1180 return NULL;
1181
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001182 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1183 if (target == -1 && PyErr_Occurred())
1184 return NULL;
1185
Jesus Cea94363612012-06-22 18:32:07 +02001186 /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1187 buffer. Other whence values must be managed without this optimization.
1188 Some Operating Systems can provide additional values, like
1189 SEEK_HOLE/SEEK_DATA. */
1190 if (((whence == 0) || (whence == 1)) && self->readable) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001191 Py_off_t current, avail;
1192 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001193 so as to return quickly if possible. Also, we needn't take the
1194 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001195 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001196 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1197 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001198 current = RAW_TELL(self);
1199 avail = READAHEAD(self);
1200 if (avail > 0) {
1201 Py_off_t offset;
1202 if (whence == 0)
1203 offset = target - (current - RAW_OFFSET(self));
1204 else
1205 offset = target;
1206 if (offset >= -self->pos && offset <= avail) {
1207 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001208 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001209 }
1210 }
1211 }
1212
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001213 if (!ENTER_BUFFERED(self))
1214 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001215
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001216 /* Fallback: invoke raw seek() method and clear buffer */
1217 if (self->writable) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001218 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001219 if (res == NULL)
1220 goto end;
1221 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001222 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001223 }
1224
1225 /* TODO: align on block boundary and read buffer if needed? */
1226 if (whence == 1)
1227 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001228 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001229 if (n == -1)
1230 goto end;
1231 self->raw_pos = -1;
1232 res = PyLong_FromOff_t(n);
1233 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001234 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001235
1236end:
1237 LEAVE_BUFFERED(self)
1238 return res;
1239}
1240
1241static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001242buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001243{
1244 PyObject *pos = Py_None;
1245 PyObject *res = NULL;
1246
1247 CHECK_INITIALIZED(self)
1248 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1249 return NULL;
1250 }
1251
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001252 if (!ENTER_BUFFERED(self))
1253 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001254
1255 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001256 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001257 if (res == NULL)
1258 goto end;
1259 Py_CLEAR(res);
1260 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001261 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1262 if (res == NULL)
1263 goto end;
1264 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001265 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001266 PyErr_Clear();
1267
1268end:
1269 LEAVE_BUFFERED(self)
1270 return res;
1271}
1272
1273static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001274buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001275{
1276 PyObject *line;
1277 PyTypeObject *tp;
1278
1279 CHECK_INITIALIZED(self);
1280
1281 tp = Py_TYPE(self);
1282 if (tp == &PyBufferedReader_Type ||
1283 tp == &PyBufferedRandom_Type) {
1284 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001285 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001286 }
1287 else {
1288 line = PyObject_CallMethodObjArgs((PyObject *)self,
1289 _PyIO_str_readline, NULL);
1290 if (line && !PyBytes_Check(line)) {
1291 PyErr_Format(PyExc_IOError,
1292 "readline() should have returned a bytes object, "
1293 "not '%.200s'", Py_TYPE(line)->tp_name);
1294 Py_DECREF(line);
1295 return NULL;
1296 }
1297 }
1298
1299 if (line == NULL)
1300 return NULL;
1301
1302 if (PyBytes_GET_SIZE(line) == 0) {
1303 /* Reached EOF or would have blocked */
1304 Py_DECREF(line);
1305 return NULL;
1306 }
1307
1308 return line;
1309}
1310
Antoine Pitrou716c4442009-05-23 19:04:03 +00001311static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001312buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001313{
1314 PyObject *nameobj, *res;
1315
Martin v. Löwis767046a2011-10-14 15:35:36 +02001316 nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
Antoine Pitrou716c4442009-05-23 19:04:03 +00001317 if (nameobj == NULL) {
1318 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1319 PyErr_Clear();
1320 else
1321 return NULL;
1322 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1323 }
1324 else {
1325 res = PyUnicode_FromFormat("<%s name=%R>",
1326 Py_TYPE(self)->tp_name, nameobj);
1327 Py_DECREF(nameobj);
1328 }
1329 return res;
1330}
1331
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001332/*
1333 * class BufferedReader
1334 */
1335
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001336PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001337 "Create a new buffered reader using the given readable raw IO object.");
1338
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001339static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001340{
1341 self->read_end = -1;
1342}
1343
1344static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001345bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001346{
1347 char *kwlist[] = {"raw", "buffer_size", NULL};
1348 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1349 PyObject *raw;
1350
1351 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001352 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001353
1354 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1355 &raw, &buffer_size)) {
1356 return -1;
1357 }
1358
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001359 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001360 return -1;
1361
1362 Py_CLEAR(self->raw);
1363 Py_INCREF(raw);
1364 self->raw = raw;
1365 self->buffer_size = buffer_size;
1366 self->readable = 1;
1367 self->writable = 0;
1368
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001369 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001370 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001371 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001372
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001373 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1374 Py_TYPE(raw) == &PyFileIO_Type);
1375
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001376 self->ok = 1;
1377 return 0;
1378}
1379
1380static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001381_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001382{
1383 Py_buffer buf;
1384 PyObject *memobj, *res;
1385 Py_ssize_t n;
1386 /* NOTE: the buffer needn't be released as its object is NULL. */
1387 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1388 return -1;
1389 memobj = PyMemoryView_FromBuffer(&buf);
1390 if (memobj == NULL)
1391 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001392 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1393 occurs so we needn't do it ourselves.
1394 We then retry reading, ignoring the signal if no handler has
1395 raised (see issue #10956).
1396 */
1397 do {
1398 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1399 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001400 Py_DECREF(memobj);
1401 if (res == NULL)
1402 return -1;
1403 if (res == Py_None) {
1404 /* Non-blocking stream would have blocked. Special return code! */
1405 Py_DECREF(res);
1406 return -2;
1407 }
1408 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1409 Py_DECREF(res);
1410 if (n < 0 || n > len) {
1411 PyErr_Format(PyExc_IOError,
1412 "raw readinto() returned invalid length %zd "
1413 "(should have been between 0 and %zd)", n, len);
1414 return -1;
1415 }
1416 if (n > 0 && self->abs_pos != -1)
1417 self->abs_pos += n;
1418 return n;
1419}
1420
1421static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001422_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001423{
1424 Py_ssize_t start, len, n;
1425 if (VALID_READ_BUFFER(self))
1426 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1427 else
1428 start = 0;
1429 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001430 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001431 if (n <= 0)
1432 return n;
1433 self->read_end = start + n;
1434 self->raw_pos = start + n;
1435 return n;
1436}
1437
1438static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001439_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001440{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001441 Py_ssize_t current_size;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001442 PyObject *res, *data = NULL, *chunk, *chunks;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001443
1444 /* First copy what we have in the current buffer. */
1445 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1446 if (current_size) {
1447 data = PyBytes_FromStringAndSize(
1448 self->buffer + self->pos, current_size);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001449 if (data == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001450 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001451 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001452 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001453 /* We're going past the buffer's bounds, flush it */
1454 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001455 res = buffered_flush_and_rewind_unlocked(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001456 if (res == NULL)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001457 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001458 Py_CLEAR(res);
1459 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001460 _bufferedreader_reset_buf(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001461
1462 if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
1463 chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
1464 if (chunk == NULL)
1465 return NULL;
1466 if (chunk != Py_None && !PyBytes_Check(chunk)) {
1467 Py_XDECREF(data);
1468 Py_DECREF(chunk);
1469 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1470 return NULL;
1471 }
1472 if (chunk == Py_None) {
1473 if (current_size == 0)
1474 return chunk;
1475 else {
1476 Py_DECREF(chunk);
1477 return data;
1478 }
1479 }
1480 else if (current_size) {
1481 PyBytes_Concat(&data, chunk);
1482 Py_DECREF(chunk);
1483 if (data == NULL)
1484 return NULL;
1485 return data;
1486 } else
1487 return chunk;
1488 }
1489
1490 chunks = PyList_New(0);
1491 if (chunks == NULL)
1492 return NULL;
1493
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001494 while (1) {
1495 if (data) {
1496 if (PyList_Append(chunks, data) < 0) {
1497 Py_DECREF(data);
1498 Py_DECREF(chunks);
1499 return NULL;
1500 }
1501 Py_DECREF(data);
1502 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001503
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001504 /* Read until EOF or until read() would block. */
1505 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1506 if (data == NULL) {
1507 Py_DECREF(chunks);
1508 return NULL;
1509 }
1510 if (data != Py_None && !PyBytes_Check(data)) {
1511 Py_DECREF(data);
1512 Py_DECREF(chunks);
1513 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1514 return NULL;
1515 }
1516 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1517 if (current_size == 0) {
1518 Py_DECREF(chunks);
1519 return data;
1520 }
1521 else {
1522 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1523 Py_DECREF(data);
1524 Py_DECREF(chunks);
1525 return res;
1526 }
1527 }
1528 current_size += PyBytes_GET_SIZE(data);
1529 if (self->abs_pos != -1)
1530 self->abs_pos += PyBytes_GET_SIZE(data);
1531 }
1532}
1533
1534/* Read n bytes from the buffer if it can, otherwise return None.
1535 This function is simple enough that it can run unlocked. */
1536static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001537_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001538{
1539 Py_ssize_t current_size;
1540
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001541 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1542 if (n <= current_size) {
1543 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001544 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1545 if (res != NULL)
1546 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001547 return res;
1548 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001549 Py_RETURN_NONE;
1550}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001551
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001552/* Generic read function: read from the stream until enough bytes are read,
1553 * or until an EOF occurs or until read() would block.
1554 */
1555static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001556_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001557{
1558 PyObject *res = NULL;
1559 Py_ssize_t current_size, remaining, written;
1560 char *out;
1561
1562 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1563 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001564 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001565
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001566 res = PyBytes_FromStringAndSize(NULL, n);
1567 if (res == NULL)
1568 goto error;
1569 out = PyBytes_AS_STRING(res);
1570 remaining = n;
1571 written = 0;
1572 if (current_size > 0) {
1573 memcpy(out, self->buffer + self->pos, current_size);
1574 remaining -= current_size;
1575 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001576 self->pos += current_size;
1577 }
1578 /* Flush the write buffer if necessary */
1579 if (self->writable) {
1580 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1581 if (r == NULL)
1582 goto error;
1583 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001584 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001585 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001586 while (remaining > 0) {
1587 /* We want to read a whole block at the end into buffer.
1588 If we had readv() we could do this in one pass. */
1589 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1590 if (r == 0)
1591 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001592 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001593 if (r == -1)
1594 goto error;
1595 if (r == 0 || r == -2) {
1596 /* EOF occurred or read() would block. */
1597 if (r == 0 || written > 0) {
1598 if (_PyBytes_Resize(&res, written))
1599 goto error;
1600 return res;
1601 }
1602 Py_DECREF(res);
1603 Py_INCREF(Py_None);
1604 return Py_None;
1605 }
1606 remaining -= r;
1607 written += r;
1608 }
1609 assert(remaining <= self->buffer_size);
1610 self->pos = 0;
1611 self->raw_pos = 0;
1612 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001613 /* NOTE: when the read is satisfied, we avoid issuing any additional
1614 reads, which could block indefinitely (e.g. on a socket).
1615 See issue #9550. */
1616 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001617 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001618 if (r == -1)
1619 goto error;
1620 if (r == 0 || r == -2) {
1621 /* EOF occurred or read() would block. */
1622 if (r == 0 || written > 0) {
1623 if (_PyBytes_Resize(&res, written))
1624 goto error;
1625 return res;
1626 }
1627 Py_DECREF(res);
1628 Py_INCREF(Py_None);
1629 return Py_None;
1630 }
1631 if (remaining > r) {
1632 memcpy(out + written, self->buffer + self->pos, r);
1633 written += r;
1634 self->pos += r;
1635 remaining -= r;
1636 }
1637 else if (remaining > 0) {
1638 memcpy(out + written, self->buffer + self->pos, remaining);
1639 written += remaining;
1640 self->pos += remaining;
1641 remaining = 0;
1642 }
1643 if (remaining == 0)
1644 break;
1645 }
1646
1647 return res;
1648
1649error:
1650 Py_XDECREF(res);
1651 return NULL;
1652}
1653
1654static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +02001655_bufferedreader_peek_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001656{
1657 Py_ssize_t have, r;
1658
1659 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1660 /* Constraints:
1661 1. we don't want to advance the file position.
1662 2. we don't want to lose block alignment, so we can't shift the buffer
1663 to make some place.
1664 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1665 */
1666 if (have > 0) {
1667 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1668 }
1669
1670 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001671 _bufferedreader_reset_buf(self);
1672 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001673 if (r == -1)
1674 return NULL;
1675 if (r == -2)
1676 r = 0;
1677 self->pos = 0;
1678 return PyBytes_FromStringAndSize(self->buffer, r);
1679}
1680
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001681static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001682 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001683 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1684 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1685 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1686 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1687 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1688 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1689 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1690 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001691 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001692 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001693
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001694 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1695 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1696 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001697 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001698 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1699 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1700 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1701 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001702 {NULL, NULL}
1703};
1704
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001705static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001706 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001707 {NULL}
1708};
1709
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001710static PyGetSetDef bufferedreader_getset[] = {
1711 {"closed", (getter)buffered_closed_get, NULL, NULL},
1712 {"name", (getter)buffered_name_get, NULL, NULL},
1713 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001714 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001715};
1716
1717
1718PyTypeObject PyBufferedReader_Type = {
1719 PyVarObject_HEAD_INIT(NULL, 0)
1720 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001721 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001722 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001723 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001724 0, /*tp_print*/
1725 0, /*tp_getattr*/
1726 0, /*tp_setattr*/
1727 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001728 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001729 0, /*tp_as_number*/
1730 0, /*tp_as_sequence*/
1731 0, /*tp_as_mapping*/
1732 0, /*tp_hash */
1733 0, /*tp_call*/
1734 0, /*tp_str*/
1735 0, /*tp_getattro*/
1736 0, /*tp_setattro*/
1737 0, /*tp_as_buffer*/
1738 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1739 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001740 bufferedreader_doc, /* tp_doc */
1741 (traverseproc)buffered_traverse, /* tp_traverse */
1742 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001743 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001744 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001745 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001746 (iternextfunc)buffered_iternext, /* tp_iternext */
1747 bufferedreader_methods, /* tp_methods */
1748 bufferedreader_members, /* tp_members */
1749 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001750 0, /* tp_base */
1751 0, /* tp_dict */
1752 0, /* tp_descr_get */
1753 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001754 offsetof(buffered, dict), /* tp_dictoffset */
1755 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001756 0, /* tp_alloc */
1757 PyType_GenericNew, /* tp_new */
1758};
1759
1760
Benjamin Peterson59406a92009-03-26 17:10:29 +00001761
1762static int
1763complain_about_max_buffer_size(void)
1764{
1765 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1766 "max_buffer_size is deprecated", 1) < 0)
1767 return 0;
1768 return 1;
1769}
1770
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001771/*
1772 * class BufferedWriter
1773 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001774PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001775 "A buffer for a writeable sequential RawIO object.\n"
1776 "\n"
1777 "The constructor creates a BufferedWriter for the given writeable raw\n"
1778 "stream. If the buffer_size is not given, it defaults to\n"
1779 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1780 );
1781
1782static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001783_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001784{
1785 self->write_pos = 0;
1786 self->write_end = -1;
1787}
1788
1789static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001790bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001791{
1792 /* TODO: properly deprecate max_buffer_size */
1793 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1794 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001795 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001796 PyObject *raw;
1797
1798 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001799 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001800
1801 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1802 &raw, &buffer_size, &max_buffer_size)) {
1803 return -1;
1804 }
1805
Benjamin Peterson59406a92009-03-26 17:10:29 +00001806 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1807 return -1;
1808
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001809 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001810 return -1;
1811
1812 Py_CLEAR(self->raw);
1813 Py_INCREF(raw);
1814 self->raw = raw;
1815 self->readable = 0;
1816 self->writable = 1;
1817
1818 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001819 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001820 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001821 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001822 self->pos = 0;
1823
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001824 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1825 Py_TYPE(raw) == &PyFileIO_Type);
1826
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001827 self->ok = 1;
1828 return 0;
1829}
1830
1831static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001832_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001833{
1834 Py_buffer buf;
1835 PyObject *memobj, *res;
1836 Py_ssize_t n;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001837 int errnum;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001838 /* NOTE: the buffer needn't be released as its object is NULL. */
1839 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1840 return -1;
1841 memobj = PyMemoryView_FromBuffer(&buf);
1842 if (memobj == NULL)
1843 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001844 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1845 occurs so we needn't do it ourselves.
1846 We then retry writing, ignoring the signal if no handler has
1847 raised (see issue #10956).
1848 */
1849 do {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001850 errno = 0;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001851 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001852 errnum = errno;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001853 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001854 Py_DECREF(memobj);
1855 if (res == NULL)
1856 return -1;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001857 if (res == Py_None) {
1858 /* Non-blocking stream would have blocked. Special return code!
1859 Being paranoid we reset errno in case it is changed by code
1860 triggered by a decref. errno is used by _set_BlockingIOError(). */
1861 Py_DECREF(res);
1862 errno = errnum;
1863 return -2;
1864 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001865 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1866 Py_DECREF(res);
1867 if (n < 0 || n > len) {
1868 PyErr_Format(PyExc_IOError,
1869 "raw write() returned invalid length %zd "
1870 "(should have been between 0 and %zd)", n, len);
1871 return -1;
1872 }
1873 if (n > 0 && self->abs_pos != -1)
1874 self->abs_pos += n;
1875 return n;
1876}
1877
1878/* `restore_pos` is 1 if we need to restore the raw stream position at
1879 the end, 0 otherwise. */
1880static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001881_bufferedwriter_flush_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001882{
1883 Py_ssize_t written = 0;
1884 Py_off_t n, rewind;
1885
1886 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1887 goto end;
1888 /* First, rewind */
1889 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1890 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001891 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001892 if (n < 0) {
1893 goto error;
1894 }
1895 self->raw_pos -= rewind;
1896 }
1897 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001898 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001899 self->buffer + self->write_pos,
1900 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1901 Py_off_t, Py_ssize_t));
1902 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001903 goto error;
1904 }
1905 else if (n == -2) {
1906 _set_BlockingIOError("write could not complete without blocking",
1907 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001908 goto error;
1909 }
1910 self->write_pos += n;
1911 self->raw_pos = self->write_pos;
1912 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001913 /* Partial writes can return successfully when interrupted by a
1914 signal (see write(2)). We must run signal handlers before
1915 blocking another time, possibly indefinitely. */
1916 if (PyErr_CheckSignals() < 0)
1917 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001918 }
1919
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001920 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001921
1922end:
1923 Py_RETURN_NONE;
1924
1925error:
1926 return NULL;
1927}
1928
1929static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001930bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001931{
1932 PyObject *res = NULL;
1933 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001934 Py_ssize_t written, avail, remaining;
1935 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001936
1937 CHECK_INITIALIZED(self)
1938 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1939 return NULL;
1940 }
1941
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001942 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001943 PyErr_SetString(PyExc_ValueError, "write to closed file");
1944 PyBuffer_Release(&buf);
1945 return NULL;
1946 }
1947
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001948 if (!ENTER_BUFFERED(self)) {
1949 PyBuffer_Release(&buf);
1950 return NULL;
1951 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001952
1953 /* Fast path: the data to write can be fully buffered. */
1954 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1955 self->pos = 0;
1956 self->raw_pos = 0;
1957 }
1958 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1959 if (buf.len <= avail) {
1960 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02001961 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001962 self->write_pos = self->pos;
1963 }
1964 ADJUST_POSITION(self, self->pos + buf.len);
1965 if (self->pos > self->write_end)
1966 self->write_end = self->pos;
1967 written = buf.len;
1968 goto end;
1969 }
1970
1971 /* First write the current buffer */
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001972 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001973 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001974 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001975 if (w == NULL)
1976 goto error;
1977 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001978 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001979 /* Make some place by shifting the buffer. */
1980 assert(VALID_WRITE_BUFFER(self));
1981 memmove(self->buffer, self->buffer + self->write_pos,
1982 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1983 Py_off_t, Py_ssize_t));
1984 self->write_end -= self->write_pos;
1985 self->raw_pos -= self->write_pos;
1986 self->pos -= self->write_pos;
1987 self->write_pos = 0;
1988 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1989 Py_off_t, Py_ssize_t);
1990 if (buf.len <= avail) {
1991 /* Everything can be buffered */
1992 PyErr_Clear();
1993 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1994 self->write_end += buf.len;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001995 self->pos += buf.len;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001996 written = buf.len;
1997 goto end;
1998 }
1999 /* Buffer as much as possible. */
2000 memcpy(self->buffer + self->write_end, buf.buf, avail);
2001 self->write_end += avail;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002002 self->pos += avail;
2003 /* XXX Modifying the existing exception e using the pointer w
2004 will change e.characters_written but not e.args[2].
2005 Therefore we just replace with a new error. */
2006 _set_BlockingIOError("write could not complete without blocking",
2007 avail);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002008 goto error;
2009 }
2010 Py_CLEAR(res);
2011
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002012 /* Adjust the raw stream position if it is away from the logical stream
2013 position. This happens if the read buffer has been filled but not
2014 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2015 the raw stream by itself).
2016 Fixes issue #6629.
2017 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002018 offset = RAW_OFFSET(self);
2019 if (offset != 0) {
2020 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002021 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002022 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002023 }
2024
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002025 /* Then write buf itself. At this point the buffer has been emptied. */
2026 remaining = buf.len;
2027 written = 0;
2028 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002029 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002030 self, (char *) buf.buf + written, buf.len - written);
2031 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002032 goto error;
2033 } else if (n == -2) {
2034 /* Write failed because raw file is non-blocking */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002035 if (remaining > self->buffer_size) {
2036 /* Can't buffer everything, still buffer as much as possible */
2037 memcpy(self->buffer,
2038 (char *) buf.buf + written, self->buffer_size);
2039 self->raw_pos = 0;
2040 ADJUST_POSITION(self, self->buffer_size);
2041 self->write_end = self->buffer_size;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002042 written += self->buffer_size;
2043 _set_BlockingIOError("write could not complete without "
2044 "blocking", written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002045 goto error;
2046 }
2047 PyErr_Clear();
2048 break;
2049 }
2050 written += n;
2051 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002052 /* Partial writes can return successfully when interrupted by a
2053 signal (see write(2)). We must run signal handlers before
2054 blocking another time, possibly indefinitely. */
2055 if (PyErr_CheckSignals() < 0)
2056 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002057 }
2058 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002059 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002060 if (remaining > 0) {
2061 memcpy(self->buffer, (char *) buf.buf + written, remaining);
2062 written += remaining;
2063 }
2064 self->write_pos = 0;
2065 /* TODO: sanity check (remaining >= 0) */
2066 self->write_end = remaining;
2067 ADJUST_POSITION(self, remaining);
2068 self->raw_pos = 0;
2069
2070end:
2071 res = PyLong_FromSsize_t(written);
2072
2073error:
2074 LEAVE_BUFFERED(self)
2075 PyBuffer_Release(&buf);
2076 return res;
2077}
2078
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002079static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002080 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002081 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2082 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2083 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2084 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2085 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2086 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2087 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002088 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002089 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002090
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002091 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2092 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2093 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2094 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2095 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002096 {NULL, NULL}
2097};
2098
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002099static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002100 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002101 {NULL}
2102};
2103
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002104static PyGetSetDef bufferedwriter_getset[] = {
2105 {"closed", (getter)buffered_closed_get, NULL, NULL},
2106 {"name", (getter)buffered_name_get, NULL, NULL},
2107 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002108 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002109};
2110
2111
2112PyTypeObject PyBufferedWriter_Type = {
2113 PyVarObject_HEAD_INIT(NULL, 0)
2114 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002115 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002116 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002117 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002118 0, /*tp_print*/
2119 0, /*tp_getattr*/
2120 0, /*tp_setattr*/
2121 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002122 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002123 0, /*tp_as_number*/
2124 0, /*tp_as_sequence*/
2125 0, /*tp_as_mapping*/
2126 0, /*tp_hash */
2127 0, /*tp_call*/
2128 0, /*tp_str*/
2129 0, /*tp_getattro*/
2130 0, /*tp_setattro*/
2131 0, /*tp_as_buffer*/
2132 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2133 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002134 bufferedwriter_doc, /* tp_doc */
2135 (traverseproc)buffered_traverse, /* tp_traverse */
2136 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002137 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002138 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002139 0, /* tp_iter */
2140 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002141 bufferedwriter_methods, /* tp_methods */
2142 bufferedwriter_members, /* tp_members */
2143 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002144 0, /* tp_base */
2145 0, /* tp_dict */
2146 0, /* tp_descr_get */
2147 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002148 offsetof(buffered, dict), /* tp_dictoffset */
2149 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002150 0, /* tp_alloc */
2151 PyType_GenericNew, /* tp_new */
2152};
2153
2154
2155
2156/*
2157 * BufferedRWPair
2158 */
2159
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002160PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002161 "A buffered reader and writer object together.\n"
2162 "\n"
2163 "A buffered reader object and buffered writer object put together to\n"
2164 "form a sequential IO object that can read and write. This is typically\n"
2165 "used with a socket or two-way pipe.\n"
2166 "\n"
2167 "reader and writer are RawIOBase objects that are readable and\n"
2168 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002169 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002170 );
2171
2172/* XXX The usefulness of this (compared to having two separate IO objects) is
2173 * questionable.
2174 */
2175
2176typedef struct {
2177 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002178 buffered *reader;
2179 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002180 PyObject *dict;
2181 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002182} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002183
2184static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002185bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002186{
2187 PyObject *reader, *writer;
2188 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002189 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002190
2191 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2192 &buffer_size, &max_buffer_size)) {
2193 return -1;
2194 }
2195
Benjamin Peterson59406a92009-03-26 17:10:29 +00002196 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2197 return -1;
2198
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002199 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002200 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002201 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002202 return -1;
2203
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002204 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002205 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002206 if (self->reader == NULL)
2207 return -1;
2208
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002209 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002210 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002211 if (self->writer == NULL) {
2212 Py_CLEAR(self->reader);
2213 return -1;
2214 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002215
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002216 return 0;
2217}
2218
2219static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002220bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002221{
2222 Py_VISIT(self->dict);
2223 return 0;
2224}
2225
2226static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002227bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002228{
2229 Py_CLEAR(self->reader);
2230 Py_CLEAR(self->writer);
2231 Py_CLEAR(self->dict);
2232 return 0;
2233}
2234
2235static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002236bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002237{
2238 _PyObject_GC_UNTRACK(self);
2239 Py_CLEAR(self->reader);
2240 Py_CLEAR(self->writer);
2241 Py_CLEAR(self->dict);
2242 Py_TYPE(self)->tp_free((PyObject *) self);
2243}
2244
2245static PyObject *
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002246_forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002247{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002248 PyObject *func = _PyObject_GetAttrId((PyObject *)self, name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002249 PyObject *ret;
2250
2251 if (func == NULL) {
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002252 PyErr_SetString(PyExc_AttributeError, name->string);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002253 return NULL;
2254 }
2255
2256 ret = PyObject_CallObject(func, args);
2257 Py_DECREF(func);
2258 return ret;
2259}
2260
2261static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002262bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002263{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002264 return _forward_call(self->reader, &PyId_read, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002265}
2266
2267static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002268bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002269{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002270 return _forward_call(self->reader, &PyId_peek, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002271}
2272
2273static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002274bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002275{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002276 return _forward_call(self->reader, &PyId_read1, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002277}
2278
2279static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002280bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002281{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002282 return _forward_call(self->reader, &PyId_readinto, args);
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002283}
2284
2285static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002286bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002287{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002288 return _forward_call(self->writer, &PyId_write, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002289}
2290
2291static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002292bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002293{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002294 return _forward_call(self->writer, &PyId_flush, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002295}
2296
2297static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002298bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002299{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002300 return _forward_call(self->reader, &PyId_readable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002301}
2302
2303static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002304bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002305{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002306 return _forward_call(self->writer, &PyId_writable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002307}
2308
2309static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002310bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002311{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002312 PyObject *ret = _forward_call(self->writer, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002313 if (ret == NULL)
2314 return NULL;
2315 Py_DECREF(ret);
2316
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002317 return _forward_call(self->reader, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002318}
2319
2320static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002321bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002322{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002323 PyObject *ret = _forward_call(self->writer, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002324
2325 if (ret != Py_False) {
2326 /* either True or exception */
2327 return ret;
2328 }
2329 Py_DECREF(ret);
2330
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002331 return _forward_call(self->reader, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002332}
2333
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002334static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002335bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002336{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002337 if (self->writer == NULL) {
2338 PyErr_SetString(PyExc_RuntimeError,
2339 "the BufferedRWPair object is being garbage-collected");
2340 return NULL;
2341 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002342 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2343}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002344
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002345static PyMethodDef bufferedrwpair_methods[] = {
2346 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2347 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2348 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2349 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002350
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002351 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2352 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002353
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002354 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2355 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002356
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002357 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2358 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002359
Antoine Pitrou243757e2010-11-05 21:15:39 +00002360 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2361
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002362 {NULL, NULL}
2363};
2364
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002365static PyGetSetDef bufferedrwpair_getset[] = {
2366 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002367 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002368};
2369
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002370PyTypeObject PyBufferedRWPair_Type = {
2371 PyVarObject_HEAD_INIT(NULL, 0)
2372 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002373 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002374 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002375 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002376 0, /*tp_print*/
2377 0, /*tp_getattr*/
2378 0, /*tp_setattr*/
2379 0, /*tp_compare */
2380 0, /*tp_repr*/
2381 0, /*tp_as_number*/
2382 0, /*tp_as_sequence*/
2383 0, /*tp_as_mapping*/
2384 0, /*tp_hash */
2385 0, /*tp_call*/
2386 0, /*tp_str*/
2387 0, /*tp_getattro*/
2388 0, /*tp_setattro*/
2389 0, /*tp_as_buffer*/
2390 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2391 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002392 bufferedrwpair_doc, /* tp_doc */
2393 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2394 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002395 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002396 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002397 0, /* tp_iter */
2398 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002399 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002400 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002401 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002402 0, /* tp_base */
2403 0, /* tp_dict */
2404 0, /* tp_descr_get */
2405 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002406 offsetof(rwpair, dict), /* tp_dictoffset */
2407 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002408 0, /* tp_alloc */
2409 PyType_GenericNew, /* tp_new */
2410};
2411
2412
2413
2414/*
2415 * BufferedRandom
2416 */
2417
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002418PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002419 "A buffered interface to random access streams.\n"
2420 "\n"
2421 "The constructor creates a reader and writer for a seekable stream,\n"
2422 "raw, given in the first argument. If the buffer_size is omitted it\n"
2423 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2424 );
2425
2426static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002427bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002428{
2429 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2430 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002431 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002432 PyObject *raw;
2433
2434 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002435 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002436
2437 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2438 &raw, &buffer_size, &max_buffer_size)) {
2439 return -1;
2440 }
2441
Benjamin Peterson59406a92009-03-26 17:10:29 +00002442 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2443 return -1;
2444
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002445 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002446 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002447 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002448 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002449 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002450 return -1;
2451
2452 Py_CLEAR(self->raw);
2453 Py_INCREF(raw);
2454 self->raw = raw;
2455 self->buffer_size = buffer_size;
2456 self->readable = 1;
2457 self->writable = 1;
2458
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002459 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002460 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002461 _bufferedreader_reset_buf(self);
2462 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002463 self->pos = 0;
2464
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002465 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2466 Py_TYPE(raw) == &PyFileIO_Type);
2467
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002468 self->ok = 1;
2469 return 0;
2470}
2471
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002472static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002473 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002474 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2475 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2476 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2477 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2478 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2479 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2480 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002481 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002482 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002483
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002484 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002485
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002486 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2487 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2488 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2489 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2490 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2491 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2492 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2493 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2494 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002495 {NULL, NULL}
2496};
2497
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002498static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002499 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002500 {NULL}
2501};
2502
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002503static PyGetSetDef bufferedrandom_getset[] = {
2504 {"closed", (getter)buffered_closed_get, NULL, NULL},
2505 {"name", (getter)buffered_name_get, NULL, NULL},
2506 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002507 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002508};
2509
2510
2511PyTypeObject PyBufferedRandom_Type = {
2512 PyVarObject_HEAD_INIT(NULL, 0)
2513 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002514 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002515 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002516 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002517 0, /*tp_print*/
2518 0, /*tp_getattr*/
2519 0, /*tp_setattr*/
2520 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002521 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002522 0, /*tp_as_number*/
2523 0, /*tp_as_sequence*/
2524 0, /*tp_as_mapping*/
2525 0, /*tp_hash */
2526 0, /*tp_call*/
2527 0, /*tp_str*/
2528 0, /*tp_getattro*/
2529 0, /*tp_setattro*/
2530 0, /*tp_as_buffer*/
2531 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2532 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002533 bufferedrandom_doc, /* tp_doc */
2534 (traverseproc)buffered_traverse, /* tp_traverse */
2535 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002536 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002537 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002538 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002539 (iternextfunc)buffered_iternext, /* tp_iternext */
2540 bufferedrandom_methods, /* tp_methods */
2541 bufferedrandom_members, /* tp_members */
2542 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002543 0, /* tp_base */
2544 0, /*tp_dict*/
2545 0, /* tp_descr_get */
2546 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002547 offsetof(buffered, dict), /*tp_dictoffset*/
2548 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002549 0, /* tp_alloc */
2550 PyType_GenericNew, /* tp_new */
2551};