blob: 67b7cc4501a4aad90905d822700779c12610b9cc [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
Antoine Pitrou10f0c502012-07-29 19:02:46 +0200401static PyObject *
402buffered_sizeof(buffered *self, void *unused)
403{
404 Py_ssize_t res;
405
406 res = sizeof(buffered);
407 if (self->buffer)
408 res += self->buffer_size;
409 return PyLong_FromSsize_t(res);
410}
411
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000412static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000413buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000414{
415 Py_VISIT(self->raw);
416 Py_VISIT(self->dict);
417 return 0;
418}
419
420static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000421buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000422{
423 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
424 return -1;
425 self->ok = 0;
426 Py_CLEAR(self->raw);
427 Py_CLEAR(self->dict);
428 return 0;
429}
430
Antoine Pitroue033e062010-10-29 10:38:18 +0000431/* Because this can call arbitrary code, it shouldn't be called when
432 the refcount is 0 (that is, not directly from tp_dealloc unless
433 the refcount has been temporarily re-incremented). */
Matthias Klosebee33162010-11-16 20:07:51 +0000434static PyObject *
Antoine Pitroue033e062010-10-29 10:38:18 +0000435buffered_dealloc_warn(buffered *self, PyObject *source)
436{
437 if (self->ok && self->raw) {
438 PyObject *r;
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200439 r = _PyObject_CallMethodId(self->raw, &PyId__dealloc_warn, "O", source);
Antoine Pitroue033e062010-10-29 10:38:18 +0000440 if (r)
441 Py_DECREF(r);
442 else
443 PyErr_Clear();
444 }
445 Py_RETURN_NONE;
446}
447
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000448/*
449 * _BufferedIOMixin methods
450 * This is not a class, just a collection of methods that will be reused
451 * by BufferedReader and BufferedWriter
452 */
453
454/* Flush and close */
455
456static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000457buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000458{
459 CHECK_INITIALIZED(self)
460 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
461}
462
463static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000464buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000465{
466 int closed;
467 PyObject *res;
468 CHECK_INITIALIZED_INT(self)
469 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
470 if (res == NULL)
471 return -1;
472 closed = PyObject_IsTrue(res);
473 Py_DECREF(res);
474 return closed;
475}
476
477static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000478buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000479{
480 CHECK_INITIALIZED(self)
481 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
482}
483
484static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000485buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000486{
487 PyObject *res = NULL;
488 int r;
489
490 CHECK_INITIALIZED(self)
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000491 if (!ENTER_BUFFERED(self))
492 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000493
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000494 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000495 if (r < 0)
496 goto end;
497 if (r > 0) {
498 res = Py_None;
499 Py_INCREF(res);
500 goto end;
501 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000502
503 if (self->deallocating) {
504 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
505 if (r)
506 Py_DECREF(r);
507 else
508 PyErr_Clear();
509 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000510 /* flush() will most probably re-take the lock, so drop it first */
511 LEAVE_BUFFERED(self)
512 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000513 if (!ENTER_BUFFERED(self))
514 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000515 if (res == NULL) {
Antoine Pitrou6be88762010-05-03 16:48:20 +0000516 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000517 }
518 Py_XDECREF(res);
519
520 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
521
522end:
523 LEAVE_BUFFERED(self)
524 return res;
525}
526
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000527/* detach */
528
529static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000530buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000531{
532 PyObject *raw, *res;
533 CHECK_INITIALIZED(self)
534 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
535 if (res == NULL)
536 return NULL;
537 Py_DECREF(res);
538 raw = self->raw;
539 self->raw = NULL;
540 self->detached = 1;
541 self->ok = 0;
542 return raw;
543}
544
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000545/* Inquiries */
546
547static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000548buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000549{
550 CHECK_INITIALIZED(self)
551 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
552}
553
554static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000555buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000556{
557 CHECK_INITIALIZED(self)
558 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
559}
560
561static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000562buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000563{
564 CHECK_INITIALIZED(self)
565 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
566}
567
568static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000569buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000570{
571 CHECK_INITIALIZED(self)
Martin v. Löwis767046a2011-10-14 15:35:36 +0200572 return _PyObject_GetAttrId(self->raw, &PyId_name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000573}
574
575static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000576buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000577{
578 CHECK_INITIALIZED(self)
Martin v. Löwis767046a2011-10-14 15:35:36 +0200579 return _PyObject_GetAttrId(self->raw, &PyId_mode);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000580}
581
582/* Lower-level APIs */
583
584static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000585buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000586{
587 CHECK_INITIALIZED(self)
588 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
589}
590
591static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000592buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000593{
594 CHECK_INITIALIZED(self)
595 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
596}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000597
Antoine Pitrou243757e2010-11-05 21:15:39 +0000598/* Serialization */
599
600static PyObject *
601buffered_getstate(buffered *self, PyObject *args)
602{
603 PyErr_Format(PyExc_TypeError,
604 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
605 return NULL;
606}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000607
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000608/* Forward decls */
609static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100610_bufferedwriter_flush_unlocked(buffered *);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000611static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000612_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000613static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000614_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000615static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000616_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000617static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +0200618_bufferedreader_peek_unlocked(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000619static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000620_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000621static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000622_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000623static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000624_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200625static Py_ssize_t
626_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000627
628/*
629 * Helpers
630 */
631
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100632/* Sets the current error to BlockingIOError */
633static void
634_set_BlockingIOError(char *msg, Py_ssize_t written)
635{
636 PyObject *err;
637 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
638 errno, msg, written);
639 if (err)
640 PyErr_SetObject(PyExc_BlockingIOError, err);
641 Py_XDECREF(err);
642}
643
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000644/* Returns the address of the `written` member if a BlockingIOError was
645 raised, NULL otherwise. The error is always re-raised. */
646static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000647_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000648{
649 PyObject *t, *v, *tb;
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200650 PyOSErrorObject *err;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000651
652 PyErr_Fetch(&t, &v, &tb);
653 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
654 PyErr_Restore(t, v, tb);
655 return NULL;
656 }
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200657 err = (PyOSErrorObject *) v;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000658 /* TODO: sanity check (err->written >= 0) */
659 PyErr_Restore(t, v, tb);
660 return &err->written;
661}
662
663static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000664_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000665{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000666 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000667 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000668 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
669 if (res == NULL)
670 return -1;
671 n = PyNumber_AsOff_t(res, PyExc_ValueError);
672 Py_DECREF(res);
673 if (n < 0) {
674 if (!PyErr_Occurred())
675 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000676 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200677 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000678 return -1;
679 }
680 self->abs_pos = n;
681 return n;
682}
683
684static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000685_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000686{
687 PyObject *res, *posobj, *whenceobj;
688 Py_off_t n;
689
690 posobj = PyLong_FromOff_t(target);
691 if (posobj == NULL)
692 return -1;
693 whenceobj = PyLong_FromLong(whence);
694 if (whenceobj == NULL) {
695 Py_DECREF(posobj);
696 return -1;
697 }
698 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
699 posobj, whenceobj, NULL);
700 Py_DECREF(posobj);
701 Py_DECREF(whenceobj);
702 if (res == NULL)
703 return -1;
704 n = PyNumber_AsOff_t(res, PyExc_ValueError);
705 Py_DECREF(res);
706 if (n < 0) {
707 if (!PyErr_Occurred())
708 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000709 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200710 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000711 return -1;
712 }
713 self->abs_pos = n;
714 return n;
715}
716
717static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000718_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000719{
720 Py_ssize_t n;
721 if (self->buffer_size <= 0) {
722 PyErr_SetString(PyExc_ValueError,
723 "buffer size must be strictly positive");
724 return -1;
725 }
726 if (self->buffer)
727 PyMem_Free(self->buffer);
728 self->buffer = PyMem_Malloc(self->buffer_size);
729 if (self->buffer == NULL) {
730 PyErr_NoMemory();
731 return -1;
732 }
Georg Brandldfd73442009-04-05 11:47:34 +0000733#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000734 if (self->lock)
735 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000736 self->lock = PyThread_allocate_lock();
737 if (self->lock == NULL) {
738 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
739 return -1;
740 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000741 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000742#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000743 /* Find out whether buffer_size is a power of 2 */
744 /* XXX is this optimization useful? */
745 for (n = self->buffer_size - 1; n & 1; n >>= 1)
746 ;
747 if (n == 0)
748 self->buffer_mask = self->buffer_size - 1;
749 else
750 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000751 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000752 PyErr_Clear();
753 return 0;
754}
755
Antoine Pitrou707ce822011-02-25 21:24:11 +0000756/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
757 clears the error indicator), 0 otherwise.
758 Should only be called when PyErr_Occurred() is true.
759*/
Gregory P. Smith51359922012-06-23 23:55:39 -0700760int
761_PyIO_trap_eintr(void)
Antoine Pitrou707ce822011-02-25 21:24:11 +0000762{
763 static PyObject *eintr_int = NULL;
764 PyObject *typ, *val, *tb;
765 PyEnvironmentErrorObject *env_err;
766
767 if (eintr_int == NULL) {
768 eintr_int = PyLong_FromLong(EINTR);
769 assert(eintr_int != NULL);
770 }
771 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
772 return 0;
773 PyErr_Fetch(&typ, &val, &tb);
774 PyErr_NormalizeException(&typ, &val, &tb);
775 env_err = (PyEnvironmentErrorObject *) val;
776 assert(env_err != NULL);
777 if (env_err->myerrno != NULL &&
778 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
779 Py_DECREF(typ);
780 Py_DECREF(val);
781 Py_XDECREF(tb);
782 return 1;
783 }
784 /* This silences any error set by PyObject_RichCompareBool() */
785 PyErr_Restore(typ, val, tb);
786 return 0;
787}
788
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000789/*
790 * Shared methods and wrappers
791 */
792
793static PyObject *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200794buffered_flush_and_rewind_unlocked(buffered *self)
795{
796 PyObject *res;
797
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100798 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200799 if (res == NULL)
800 return NULL;
801 Py_DECREF(res);
802
803 if (self->readable) {
804 /* Rewind the raw stream so that its position corresponds to
805 the current logical position. */
806 Py_off_t n;
807 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
808 _bufferedreader_reset_buf(self);
809 if (n == -1)
810 return NULL;
811 }
812 Py_RETURN_NONE;
813}
814
815static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000816buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000817{
818 PyObject *res;
819
820 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000821 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000822
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000823 if (!ENTER_BUFFERED(self))
824 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200825 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000826 LEAVE_BUFFERED(self)
827
828 return res;
829}
830
831static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000832buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000833{
834 Py_ssize_t n = 0;
835 PyObject *res = NULL;
836
837 CHECK_INITIALIZED(self)
838 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
839 return NULL;
840 }
841
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000842 if (!ENTER_BUFFERED(self))
843 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000844
845 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200846 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000847 if (res == NULL)
848 goto end;
849 Py_CLEAR(res);
850 }
Victor Stinnerbc93a112011-06-01 00:01:24 +0200851 res = _bufferedreader_peek_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000852
853end:
854 LEAVE_BUFFERED(self)
855 return res;
856}
857
858static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000859buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000860{
861 Py_ssize_t n = -1;
862 PyObject *res;
863
864 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000865 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000866 return NULL;
867 }
868 if (n < -1) {
869 PyErr_SetString(PyExc_ValueError,
870 "read length must be positive or -1");
871 return NULL;
872 }
873
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000874 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000875
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000876 if (n == -1) {
877 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000878 if (!ENTER_BUFFERED(self))
879 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000880 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000881 }
882 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000883 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200884 if (res != Py_None)
885 return res;
886 Py_DECREF(res);
887 if (!ENTER_BUFFERED(self))
888 return NULL;
889 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000890 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000891
Antoine Pitroue05565e2011-08-20 14:39:23 +0200892 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000893 return res;
894}
895
896static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000897buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000898{
899 Py_ssize_t n, have, r;
900 PyObject *res = NULL;
901
902 CHECK_INITIALIZED(self)
903 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
904 return NULL;
905 }
906
907 if (n < 0) {
908 PyErr_SetString(PyExc_ValueError,
909 "read length must be positive");
910 return NULL;
911 }
912 if (n == 0)
913 return PyBytes_FromStringAndSize(NULL, 0);
914
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000915 /* Return up to n bytes. If at least one byte is buffered, we
916 only return buffered bytes. Otherwise, we do one raw read. */
917
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000918 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
919 if (have > 0) {
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100920 n = Py_MIN(have, n);
921 res = _bufferedreader_read_fast(self, n);
922 assert(res != Py_None);
923 return res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000924 }
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100925 res = PyBytes_FromStringAndSize(NULL, n);
926 if (res == NULL)
927 return NULL;
928 if (!ENTER_BUFFERED(self)) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200929 Py_DECREF(res);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100930 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200931 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000932 _bufferedreader_reset_buf(self);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100933 r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
934 LEAVE_BUFFERED(self)
935 if (r == -1) {
936 Py_DECREF(res);
937 return NULL;
938 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000939 if (r == -2)
940 r = 0;
941 if (n > r)
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100942 _PyBytes_Resize(&res, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000943 return res;
944}
945
946static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000947buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000948{
Antoine Pitrou3486a982011-05-12 01:57:53 +0200949 Py_buffer buf;
950 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000951 PyObject *res = NULL;
952
953 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +0200954
955 if (!PyArg_ParseTuple(args, "w*:readinto", &buf))
956 return NULL;
957
958 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
959 if (n > 0) {
960 if (n >= buf.len) {
961 memcpy(buf.buf, self->buffer + self->pos, buf.len);
962 self->pos += buf.len;
963 res = PyLong_FromSsize_t(buf.len);
964 goto end_unlocked;
965 }
966 memcpy(buf.buf, self->buffer + self->pos, n);
967 self->pos += n;
968 written = n;
969 }
970
971 if (!ENTER_BUFFERED(self))
972 goto end_unlocked;
973
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000974 if (self->writable) {
Antoine Pitroue8bb1a02011-08-20 14:52:04 +0200975 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000976 if (res == NULL)
977 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200978 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000979 }
Antoine Pitrou3486a982011-05-12 01:57:53 +0200980
981 _bufferedreader_reset_buf(self);
982 self->pos = 0;
983
984 for (remaining = buf.len - written;
985 remaining > 0;
986 written += n, remaining -= n) {
987 /* If remaining bytes is larger than internal buffer size, copy
988 * directly into caller's buffer. */
989 if (remaining > self->buffer_size) {
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200990 n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
991 remaining);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200992 }
993 else {
994 n = _bufferedreader_fill_buffer(self);
995 if (n > 0) {
996 if (n > remaining)
997 n = remaining;
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200998 memcpy((char *) buf.buf + written,
999 self->buffer + self->pos, n);
Antoine Pitrou3486a982011-05-12 01:57:53 +02001000 self->pos += n;
1001 continue; /* short circuit */
1002 }
1003 }
1004 if (n == 0 || (n == -2 && written > 0))
1005 break;
1006 if (n < 0) {
1007 if (n == -2) {
1008 Py_INCREF(Py_None);
1009 res = Py_None;
1010 }
1011 goto end;
1012 }
1013 }
1014 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001015
1016end:
Antoine Pitrou3486a982011-05-12 01:57:53 +02001017 LEAVE_BUFFERED(self);
1018end_unlocked:
1019 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001020 return res;
1021}
1022
1023static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001024_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001025{
1026 PyObject *res = NULL;
1027 PyObject *chunks = NULL;
1028 Py_ssize_t n, written = 0;
1029 const char *start, *s, *end;
1030
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001031 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001032
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001033 /* First, try to find a line in the buffer. This can run unlocked because
1034 the calls to the C API are simple enough that they can't trigger
1035 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001036 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1037 if (limit >= 0 && n > limit)
1038 n = limit;
1039 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001040 s = memchr(start, '\n', n);
1041 if (s != NULL) {
1042 res = PyBytes_FromStringAndSize(start, s - start + 1);
1043 if (res != NULL)
1044 self->pos += s - start + 1;
1045 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001046 }
1047 if (n == limit) {
1048 res = PyBytes_FromStringAndSize(start, n);
1049 if (res != NULL)
1050 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001051 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001052 }
1053
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001054 if (!ENTER_BUFFERED(self))
1055 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001056
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001057 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001058 chunks = PyList_New(0);
1059 if (chunks == NULL)
1060 goto end;
1061 if (n > 0) {
1062 res = PyBytes_FromStringAndSize(start, n);
1063 if (res == NULL)
1064 goto end;
1065 if (PyList_Append(chunks, res) < 0) {
1066 Py_CLEAR(res);
1067 goto end;
1068 }
1069 Py_CLEAR(res);
1070 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001071 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001072 if (limit >= 0)
1073 limit -= n;
1074 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001075 if (self->writable) {
1076 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1077 if (r == NULL)
1078 goto end;
1079 Py_DECREF(r);
1080 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001081
1082 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001083 _bufferedreader_reset_buf(self);
1084 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001085 if (n == -1)
1086 goto end;
1087 if (n <= 0)
1088 break;
1089 if (limit >= 0 && n > limit)
1090 n = limit;
1091 start = self->buffer;
1092 end = start + n;
1093 s = start;
1094 while (s < end) {
1095 if (*s++ == '\n') {
1096 res = PyBytes_FromStringAndSize(start, s - start);
1097 if (res == NULL)
1098 goto end;
1099 self->pos = s - start;
1100 goto found;
1101 }
1102 }
1103 res = PyBytes_FromStringAndSize(start, n);
1104 if (res == NULL)
1105 goto end;
1106 if (n == limit) {
1107 self->pos = n;
1108 break;
1109 }
1110 if (PyList_Append(chunks, res) < 0) {
1111 Py_CLEAR(res);
1112 goto end;
1113 }
1114 Py_CLEAR(res);
1115 written += n;
1116 if (limit >= 0)
1117 limit -= n;
1118 }
1119found:
1120 if (res != NULL && PyList_Append(chunks, res) < 0) {
1121 Py_CLEAR(res);
1122 goto end;
1123 }
1124 Py_CLEAR(res);
1125 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1126
1127end:
1128 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001129end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001130 Py_XDECREF(chunks);
1131 return res;
1132}
1133
1134static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001135buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001136{
1137 Py_ssize_t limit = -1;
1138
1139 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001140 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001141 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001142 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001143}
1144
1145
1146static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001147buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001148{
1149 Py_off_t pos;
1150
1151 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001152 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001153 if (pos == -1)
1154 return NULL;
1155 pos -= RAW_OFFSET(self);
1156 /* TODO: sanity check (pos >= 0) */
1157 return PyLong_FromOff_t(pos);
1158}
1159
1160static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001161buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001162{
1163 Py_off_t target, n;
1164 int whence = 0;
1165 PyObject *targetobj, *res = NULL;
1166
1167 CHECK_INITIALIZED(self)
1168 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1169 return NULL;
1170 }
Jesus Cea94363612012-06-22 18:32:07 +02001171
1172 /* Do some error checking instead of trusting OS 'seek()'
1173 ** error detection, just in case.
1174 */
1175 if ((whence < 0 || whence >2)
1176#ifdef SEEK_HOLE
1177 && (whence != SEEK_HOLE)
1178#endif
1179#ifdef SEEK_DATA
1180 && (whence != SEEK_DATA)
1181#endif
1182 ) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001183 PyErr_Format(PyExc_ValueError,
Jesus Cea94363612012-06-22 18:32:07 +02001184 "whence value %d unsupported", whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001185 return NULL;
1186 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001187
1188 CHECK_CLOSED(self, "seek of closed file")
1189
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001190 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1191 return NULL;
1192
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001193 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1194 if (target == -1 && PyErr_Occurred())
1195 return NULL;
1196
Jesus Cea94363612012-06-22 18:32:07 +02001197 /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1198 buffer. Other whence values must be managed without this optimization.
1199 Some Operating Systems can provide additional values, like
1200 SEEK_HOLE/SEEK_DATA. */
1201 if (((whence == 0) || (whence == 1)) && self->readable) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001202 Py_off_t current, avail;
1203 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001204 so as to return quickly if possible. Also, we needn't take the
1205 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001206 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001207 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1208 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001209 current = RAW_TELL(self);
1210 avail = READAHEAD(self);
1211 if (avail > 0) {
1212 Py_off_t offset;
1213 if (whence == 0)
1214 offset = target - (current - RAW_OFFSET(self));
1215 else
1216 offset = target;
1217 if (offset >= -self->pos && offset <= avail) {
1218 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001219 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001220 }
1221 }
1222 }
1223
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001224 if (!ENTER_BUFFERED(self))
1225 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001226
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001227 /* Fallback: invoke raw seek() method and clear buffer */
1228 if (self->writable) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001229 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001230 if (res == NULL)
1231 goto end;
1232 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001233 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001234 }
1235
1236 /* TODO: align on block boundary and read buffer if needed? */
1237 if (whence == 1)
1238 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001239 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001240 if (n == -1)
1241 goto end;
1242 self->raw_pos = -1;
1243 res = PyLong_FromOff_t(n);
1244 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001245 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001246
1247end:
1248 LEAVE_BUFFERED(self)
1249 return res;
1250}
1251
1252static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001253buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001254{
1255 PyObject *pos = Py_None;
1256 PyObject *res = NULL;
1257
1258 CHECK_INITIALIZED(self)
1259 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1260 return NULL;
1261 }
1262
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001263 if (!ENTER_BUFFERED(self))
1264 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001265
1266 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001267 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001268 if (res == NULL)
1269 goto end;
1270 Py_CLEAR(res);
1271 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001272 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1273 if (res == NULL)
1274 goto end;
1275 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001276 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001277 PyErr_Clear();
1278
1279end:
1280 LEAVE_BUFFERED(self)
1281 return res;
1282}
1283
1284static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001285buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001286{
1287 PyObject *line;
1288 PyTypeObject *tp;
1289
1290 CHECK_INITIALIZED(self);
1291
1292 tp = Py_TYPE(self);
1293 if (tp == &PyBufferedReader_Type ||
1294 tp == &PyBufferedRandom_Type) {
1295 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001296 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001297 }
1298 else {
1299 line = PyObject_CallMethodObjArgs((PyObject *)self,
1300 _PyIO_str_readline, NULL);
1301 if (line && !PyBytes_Check(line)) {
1302 PyErr_Format(PyExc_IOError,
1303 "readline() should have returned a bytes object, "
1304 "not '%.200s'", Py_TYPE(line)->tp_name);
1305 Py_DECREF(line);
1306 return NULL;
1307 }
1308 }
1309
1310 if (line == NULL)
1311 return NULL;
1312
1313 if (PyBytes_GET_SIZE(line) == 0) {
1314 /* Reached EOF or would have blocked */
1315 Py_DECREF(line);
1316 return NULL;
1317 }
1318
1319 return line;
1320}
1321
Antoine Pitrou716c4442009-05-23 19:04:03 +00001322static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001323buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001324{
1325 PyObject *nameobj, *res;
1326
Martin v. Löwis767046a2011-10-14 15:35:36 +02001327 nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
Antoine Pitrou716c4442009-05-23 19:04:03 +00001328 if (nameobj == NULL) {
1329 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1330 PyErr_Clear();
1331 else
1332 return NULL;
1333 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1334 }
1335 else {
1336 res = PyUnicode_FromFormat("<%s name=%R>",
1337 Py_TYPE(self)->tp_name, nameobj);
1338 Py_DECREF(nameobj);
1339 }
1340 return res;
1341}
1342
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001343/*
1344 * class BufferedReader
1345 */
1346
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001347PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001348 "Create a new buffered reader using the given readable raw IO object.");
1349
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001350static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001351{
1352 self->read_end = -1;
1353}
1354
1355static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001356bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001357{
1358 char *kwlist[] = {"raw", "buffer_size", NULL};
1359 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1360 PyObject *raw;
1361
1362 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001363 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001364
1365 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1366 &raw, &buffer_size)) {
1367 return -1;
1368 }
1369
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001370 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001371 return -1;
1372
1373 Py_CLEAR(self->raw);
1374 Py_INCREF(raw);
1375 self->raw = raw;
1376 self->buffer_size = buffer_size;
1377 self->readable = 1;
1378 self->writable = 0;
1379
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001380 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001381 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001382 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001383
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001384 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1385 Py_TYPE(raw) == &PyFileIO_Type);
1386
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001387 self->ok = 1;
1388 return 0;
1389}
1390
1391static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001392_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001393{
1394 Py_buffer buf;
1395 PyObject *memobj, *res;
1396 Py_ssize_t n;
1397 /* NOTE: the buffer needn't be released as its object is NULL. */
1398 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1399 return -1;
1400 memobj = PyMemoryView_FromBuffer(&buf);
1401 if (memobj == NULL)
1402 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001403 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1404 occurs so we needn't do it ourselves.
1405 We then retry reading, ignoring the signal if no handler has
1406 raised (see issue #10956).
1407 */
1408 do {
1409 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
Gregory P. Smith51359922012-06-23 23:55:39 -07001410 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001411 Py_DECREF(memobj);
1412 if (res == NULL)
1413 return -1;
1414 if (res == Py_None) {
1415 /* Non-blocking stream would have blocked. Special return code! */
1416 Py_DECREF(res);
1417 return -2;
1418 }
1419 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1420 Py_DECREF(res);
1421 if (n < 0 || n > len) {
1422 PyErr_Format(PyExc_IOError,
1423 "raw readinto() returned invalid length %zd "
1424 "(should have been between 0 and %zd)", n, len);
1425 return -1;
1426 }
1427 if (n > 0 && self->abs_pos != -1)
1428 self->abs_pos += n;
1429 return n;
1430}
1431
1432static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001433_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001434{
1435 Py_ssize_t start, len, n;
1436 if (VALID_READ_BUFFER(self))
1437 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1438 else
1439 start = 0;
1440 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001441 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001442 if (n <= 0)
1443 return n;
1444 self->read_end = start + n;
1445 self->raw_pos = start + n;
1446 return n;
1447}
1448
1449static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001450_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001451{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001452 Py_ssize_t current_size;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001453 PyObject *res, *data = NULL, *chunk, *chunks;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001454
1455 /* First copy what we have in the current buffer. */
1456 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1457 if (current_size) {
1458 data = PyBytes_FromStringAndSize(
1459 self->buffer + self->pos, current_size);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001460 if (data == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001461 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001462 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001463 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001464 /* We're going past the buffer's bounds, flush it */
1465 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001466 res = buffered_flush_and_rewind_unlocked(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001467 if (res == NULL)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001468 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001469 Py_CLEAR(res);
1470 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001471 _bufferedreader_reset_buf(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001472
1473 if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
1474 chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
1475 if (chunk == NULL)
1476 return NULL;
1477 if (chunk != Py_None && !PyBytes_Check(chunk)) {
1478 Py_XDECREF(data);
1479 Py_DECREF(chunk);
1480 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1481 return NULL;
1482 }
1483 if (chunk == Py_None) {
1484 if (current_size == 0)
1485 return chunk;
1486 else {
1487 Py_DECREF(chunk);
1488 return data;
1489 }
1490 }
1491 else if (current_size) {
1492 PyBytes_Concat(&data, chunk);
1493 Py_DECREF(chunk);
1494 if (data == NULL)
1495 return NULL;
1496 return data;
1497 } else
1498 return chunk;
1499 }
1500
1501 chunks = PyList_New(0);
1502 if (chunks == NULL)
1503 return NULL;
1504
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001505 while (1) {
1506 if (data) {
1507 if (PyList_Append(chunks, data) < 0) {
1508 Py_DECREF(data);
1509 Py_DECREF(chunks);
1510 return NULL;
1511 }
1512 Py_DECREF(data);
1513 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001514
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001515 /* Read until EOF or until read() would block. */
1516 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1517 if (data == NULL) {
1518 Py_DECREF(chunks);
1519 return NULL;
1520 }
1521 if (data != Py_None && !PyBytes_Check(data)) {
1522 Py_DECREF(data);
1523 Py_DECREF(chunks);
1524 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1525 return NULL;
1526 }
1527 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1528 if (current_size == 0) {
1529 Py_DECREF(chunks);
1530 return data;
1531 }
1532 else {
1533 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1534 Py_DECREF(data);
1535 Py_DECREF(chunks);
1536 return res;
1537 }
1538 }
1539 current_size += PyBytes_GET_SIZE(data);
1540 if (self->abs_pos != -1)
1541 self->abs_pos += PyBytes_GET_SIZE(data);
1542 }
1543}
1544
1545/* Read n bytes from the buffer if it can, otherwise return None.
1546 This function is simple enough that it can run unlocked. */
1547static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001548_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001549{
1550 Py_ssize_t current_size;
1551
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001552 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1553 if (n <= current_size) {
1554 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001555 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1556 if (res != NULL)
1557 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001558 return res;
1559 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001560 Py_RETURN_NONE;
1561}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001562
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001563/* Generic read function: read from the stream until enough bytes are read,
1564 * or until an EOF occurs or until read() would block.
1565 */
1566static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001567_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001568{
1569 PyObject *res = NULL;
1570 Py_ssize_t current_size, remaining, written;
1571 char *out;
1572
1573 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1574 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001575 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001576
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001577 res = PyBytes_FromStringAndSize(NULL, n);
1578 if (res == NULL)
1579 goto error;
1580 out = PyBytes_AS_STRING(res);
1581 remaining = n;
1582 written = 0;
1583 if (current_size > 0) {
1584 memcpy(out, self->buffer + self->pos, current_size);
1585 remaining -= current_size;
1586 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001587 self->pos += current_size;
1588 }
1589 /* Flush the write buffer if necessary */
1590 if (self->writable) {
1591 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1592 if (r == NULL)
1593 goto error;
1594 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001595 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001596 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001597 while (remaining > 0) {
1598 /* We want to read a whole block at the end into buffer.
1599 If we had readv() we could do this in one pass. */
1600 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1601 if (r == 0)
1602 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001603 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001604 if (r == -1)
1605 goto error;
1606 if (r == 0 || r == -2) {
1607 /* EOF occurred or read() would block. */
1608 if (r == 0 || written > 0) {
1609 if (_PyBytes_Resize(&res, written))
1610 goto error;
1611 return res;
1612 }
1613 Py_DECREF(res);
1614 Py_INCREF(Py_None);
1615 return Py_None;
1616 }
1617 remaining -= r;
1618 written += r;
1619 }
1620 assert(remaining <= self->buffer_size);
1621 self->pos = 0;
1622 self->raw_pos = 0;
1623 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001624 /* NOTE: when the read is satisfied, we avoid issuing any additional
1625 reads, which could block indefinitely (e.g. on a socket).
1626 See issue #9550. */
1627 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001628 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001629 if (r == -1)
1630 goto error;
1631 if (r == 0 || r == -2) {
1632 /* EOF occurred or read() would block. */
1633 if (r == 0 || written > 0) {
1634 if (_PyBytes_Resize(&res, written))
1635 goto error;
1636 return res;
1637 }
1638 Py_DECREF(res);
1639 Py_INCREF(Py_None);
1640 return Py_None;
1641 }
1642 if (remaining > r) {
1643 memcpy(out + written, self->buffer + self->pos, r);
1644 written += r;
1645 self->pos += r;
1646 remaining -= r;
1647 }
1648 else if (remaining > 0) {
1649 memcpy(out + written, self->buffer + self->pos, remaining);
1650 written += remaining;
1651 self->pos += remaining;
1652 remaining = 0;
1653 }
1654 if (remaining == 0)
1655 break;
1656 }
1657
1658 return res;
1659
1660error:
1661 Py_XDECREF(res);
1662 return NULL;
1663}
1664
1665static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +02001666_bufferedreader_peek_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001667{
1668 Py_ssize_t have, r;
1669
1670 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1671 /* Constraints:
1672 1. we don't want to advance the file position.
1673 2. we don't want to lose block alignment, so we can't shift the buffer
1674 to make some place.
1675 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1676 */
1677 if (have > 0) {
1678 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1679 }
1680
1681 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001682 _bufferedreader_reset_buf(self);
1683 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001684 if (r == -1)
1685 return NULL;
1686 if (r == -2)
1687 r = 0;
1688 self->pos = 0;
1689 return PyBytes_FromStringAndSize(self->buffer, r);
1690}
1691
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001692static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001693 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001694 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1695 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1696 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1697 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1698 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1699 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1700 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1701 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001702 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001703 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001704
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001705 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1706 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1707 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001708 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001709 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1710 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1711 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1712 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02001713 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001714 {NULL, NULL}
1715};
1716
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001717static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001718 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001719 {NULL}
1720};
1721
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001722static PyGetSetDef bufferedreader_getset[] = {
1723 {"closed", (getter)buffered_closed_get, NULL, NULL},
1724 {"name", (getter)buffered_name_get, NULL, NULL},
1725 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001726 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001727};
1728
1729
1730PyTypeObject PyBufferedReader_Type = {
1731 PyVarObject_HEAD_INIT(NULL, 0)
1732 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001733 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001734 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001735 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001736 0, /*tp_print*/
1737 0, /*tp_getattr*/
1738 0, /*tp_setattr*/
1739 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001740 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001741 0, /*tp_as_number*/
1742 0, /*tp_as_sequence*/
1743 0, /*tp_as_mapping*/
1744 0, /*tp_hash */
1745 0, /*tp_call*/
1746 0, /*tp_str*/
1747 0, /*tp_getattro*/
1748 0, /*tp_setattro*/
1749 0, /*tp_as_buffer*/
1750 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1751 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001752 bufferedreader_doc, /* tp_doc */
1753 (traverseproc)buffered_traverse, /* tp_traverse */
1754 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001755 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001756 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001757 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001758 (iternextfunc)buffered_iternext, /* tp_iternext */
1759 bufferedreader_methods, /* tp_methods */
1760 bufferedreader_members, /* tp_members */
1761 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001762 0, /* tp_base */
1763 0, /* tp_dict */
1764 0, /* tp_descr_get */
1765 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001766 offsetof(buffered, dict), /* tp_dictoffset */
1767 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001768 0, /* tp_alloc */
1769 PyType_GenericNew, /* tp_new */
1770};
1771
1772
Benjamin Peterson59406a92009-03-26 17:10:29 +00001773
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001774/*
1775 * class BufferedWriter
1776 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001777PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001778 "A buffer for a writeable sequential RawIO object.\n"
1779 "\n"
1780 "The constructor creates a BufferedWriter for the given writeable raw\n"
1781 "stream. If the buffer_size is not given, it defaults to\n"
Florent Xicluna109d5732012-07-07 17:03:22 +02001782 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001783 );
1784
1785static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001786_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001787{
1788 self->write_pos = 0;
1789 self->write_end = -1;
1790}
1791
1792static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001793bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001794{
Florent Xicluna109d5732012-07-07 17:03:22 +02001795 char *kwlist[] = {"raw", "buffer_size", NULL};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001796 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001797 PyObject *raw;
1798
1799 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001800 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001801
Florent Xicluna109d5732012-07-07 17:03:22 +02001802 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1803 &raw, &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001804 return -1;
1805 }
1806
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001807 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001808 return -1;
1809
1810 Py_CLEAR(self->raw);
1811 Py_INCREF(raw);
1812 self->raw = raw;
1813 self->readable = 0;
1814 self->writable = 1;
1815
1816 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001817 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001818 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001819 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001820 self->pos = 0;
1821
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001822 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1823 Py_TYPE(raw) == &PyFileIO_Type);
1824
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001825 self->ok = 1;
1826 return 0;
1827}
1828
1829static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001830_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001831{
1832 Py_buffer buf;
1833 PyObject *memobj, *res;
1834 Py_ssize_t n;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001835 int errnum;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001836 /* NOTE: the buffer needn't be released as its object is NULL. */
1837 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1838 return -1;
1839 memobj = PyMemoryView_FromBuffer(&buf);
1840 if (memobj == NULL)
1841 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001842 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1843 occurs so we needn't do it ourselves.
1844 We then retry writing, ignoring the signal if no handler has
1845 raised (see issue #10956).
1846 */
1847 do {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001848 errno = 0;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001849 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001850 errnum = errno;
Gregory P. Smith51359922012-06-23 23:55:39 -07001851 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001852 Py_DECREF(memobj);
1853 if (res == NULL)
1854 return -1;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001855 if (res == Py_None) {
1856 /* Non-blocking stream would have blocked. Special return code!
1857 Being paranoid we reset errno in case it is changed by code
1858 triggered by a decref. errno is used by _set_BlockingIOError(). */
1859 Py_DECREF(res);
1860 errno = errnum;
1861 return -2;
1862 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001863 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1864 Py_DECREF(res);
1865 if (n < 0 || n > len) {
1866 PyErr_Format(PyExc_IOError,
1867 "raw write() returned invalid length %zd "
1868 "(should have been between 0 and %zd)", n, len);
1869 return -1;
1870 }
1871 if (n > 0 && self->abs_pos != -1)
1872 self->abs_pos += n;
1873 return n;
1874}
1875
1876/* `restore_pos` is 1 if we need to restore the raw stream position at
1877 the end, 0 otherwise. */
1878static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001879_bufferedwriter_flush_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001880{
1881 Py_ssize_t written = 0;
1882 Py_off_t n, rewind;
1883
1884 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1885 goto end;
1886 /* First, rewind */
1887 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1888 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001889 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001890 if (n < 0) {
1891 goto error;
1892 }
1893 self->raw_pos -= rewind;
1894 }
1895 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001896 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001897 self->buffer + self->write_pos,
1898 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1899 Py_off_t, Py_ssize_t));
1900 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001901 goto error;
1902 }
1903 else if (n == -2) {
1904 _set_BlockingIOError("write could not complete without blocking",
1905 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001906 goto error;
1907 }
1908 self->write_pos += n;
1909 self->raw_pos = self->write_pos;
1910 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001911 /* Partial writes can return successfully when interrupted by a
1912 signal (see write(2)). We must run signal handlers before
1913 blocking another time, possibly indefinitely. */
1914 if (PyErr_CheckSignals() < 0)
1915 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001916 }
1917
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001918 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001919
1920end:
1921 Py_RETURN_NONE;
1922
1923error:
1924 return NULL;
1925}
1926
1927static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001928bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001929{
1930 PyObject *res = NULL;
1931 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001932 Py_ssize_t written, avail, remaining;
1933 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001934
1935 CHECK_INITIALIZED(self)
1936 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1937 return NULL;
1938 }
1939
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001940 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001941 PyErr_SetString(PyExc_ValueError, "write to closed file");
1942 PyBuffer_Release(&buf);
1943 return NULL;
1944 }
1945
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001946 if (!ENTER_BUFFERED(self)) {
1947 PyBuffer_Release(&buf);
1948 return NULL;
1949 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001950
1951 /* Fast path: the data to write can be fully buffered. */
1952 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1953 self->pos = 0;
1954 self->raw_pos = 0;
1955 }
1956 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1957 if (buf.len <= avail) {
1958 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02001959 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001960 self->write_pos = self->pos;
1961 }
1962 ADJUST_POSITION(self, self->pos + buf.len);
1963 if (self->pos > self->write_end)
1964 self->write_end = self->pos;
1965 written = buf.len;
1966 goto end;
1967 }
1968
1969 /* First write the current buffer */
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001970 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001971 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001972 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001973 if (w == NULL)
1974 goto error;
1975 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001976 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001977 /* Make some place by shifting the buffer. */
1978 assert(VALID_WRITE_BUFFER(self));
1979 memmove(self->buffer, self->buffer + self->write_pos,
1980 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1981 Py_off_t, Py_ssize_t));
1982 self->write_end -= self->write_pos;
1983 self->raw_pos -= self->write_pos;
1984 self->pos -= self->write_pos;
1985 self->write_pos = 0;
1986 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1987 Py_off_t, Py_ssize_t);
1988 if (buf.len <= avail) {
1989 /* Everything can be buffered */
1990 PyErr_Clear();
1991 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1992 self->write_end += buf.len;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001993 self->pos += buf.len;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001994 written = buf.len;
1995 goto end;
1996 }
1997 /* Buffer as much as possible. */
1998 memcpy(self->buffer + self->write_end, buf.buf, avail);
1999 self->write_end += avail;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002000 self->pos += avail;
2001 /* XXX Modifying the existing exception e using the pointer w
2002 will change e.characters_written but not e.args[2].
2003 Therefore we just replace with a new error. */
2004 _set_BlockingIOError("write could not complete without blocking",
2005 avail);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002006 goto error;
2007 }
2008 Py_CLEAR(res);
2009
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002010 /* Adjust the raw stream position if it is away from the logical stream
2011 position. This happens if the read buffer has been filled but not
2012 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2013 the raw stream by itself).
2014 Fixes issue #6629.
2015 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002016 offset = RAW_OFFSET(self);
2017 if (offset != 0) {
2018 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002019 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002020 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002021 }
2022
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002023 /* Then write buf itself. At this point the buffer has been emptied. */
2024 remaining = buf.len;
2025 written = 0;
2026 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002027 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002028 self, (char *) buf.buf + written, buf.len - written);
2029 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002030 goto error;
2031 } else if (n == -2) {
2032 /* Write failed because raw file is non-blocking */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002033 if (remaining > self->buffer_size) {
2034 /* Can't buffer everything, still buffer as much as possible */
2035 memcpy(self->buffer,
2036 (char *) buf.buf + written, self->buffer_size);
2037 self->raw_pos = 0;
2038 ADJUST_POSITION(self, self->buffer_size);
2039 self->write_end = self->buffer_size;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002040 written += self->buffer_size;
2041 _set_BlockingIOError("write could not complete without "
2042 "blocking", written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002043 goto error;
2044 }
2045 PyErr_Clear();
2046 break;
2047 }
2048 written += n;
2049 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002050 /* Partial writes can return successfully when interrupted by a
2051 signal (see write(2)). We must run signal handlers before
2052 blocking another time, possibly indefinitely. */
2053 if (PyErr_CheckSignals() < 0)
2054 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002055 }
2056 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002057 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002058 if (remaining > 0) {
2059 memcpy(self->buffer, (char *) buf.buf + written, remaining);
2060 written += remaining;
2061 }
2062 self->write_pos = 0;
2063 /* TODO: sanity check (remaining >= 0) */
2064 self->write_end = remaining;
2065 ADJUST_POSITION(self, remaining);
2066 self->raw_pos = 0;
2067
2068end:
2069 res = PyLong_FromSsize_t(written);
2070
2071error:
2072 LEAVE_BUFFERED(self)
2073 PyBuffer_Release(&buf);
2074 return res;
2075}
2076
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002077static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002078 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002079 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2080 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2081 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2082 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2083 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2084 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2085 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002086 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002087 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002088
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002089 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2090 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2091 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2092 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2093 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002094 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002095 {NULL, NULL}
2096};
2097
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002098static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002099 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002100 {NULL}
2101};
2102
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002103static PyGetSetDef bufferedwriter_getset[] = {
2104 {"closed", (getter)buffered_closed_get, NULL, NULL},
2105 {"name", (getter)buffered_name_get, NULL, NULL},
2106 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002107 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002108};
2109
2110
2111PyTypeObject PyBufferedWriter_Type = {
2112 PyVarObject_HEAD_INIT(NULL, 0)
2113 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002114 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002115 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002116 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002117 0, /*tp_print*/
2118 0, /*tp_getattr*/
2119 0, /*tp_setattr*/
2120 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002121 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002122 0, /*tp_as_number*/
2123 0, /*tp_as_sequence*/
2124 0, /*tp_as_mapping*/
2125 0, /*tp_hash */
2126 0, /*tp_call*/
2127 0, /*tp_str*/
2128 0, /*tp_getattro*/
2129 0, /*tp_setattro*/
2130 0, /*tp_as_buffer*/
2131 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2132 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002133 bufferedwriter_doc, /* tp_doc */
2134 (traverseproc)buffered_traverse, /* tp_traverse */
2135 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002136 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002137 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002138 0, /* tp_iter */
2139 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002140 bufferedwriter_methods, /* tp_methods */
2141 bufferedwriter_members, /* tp_members */
2142 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002143 0, /* tp_base */
2144 0, /* tp_dict */
2145 0, /* tp_descr_get */
2146 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002147 offsetof(buffered, dict), /* tp_dictoffset */
2148 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002149 0, /* tp_alloc */
2150 PyType_GenericNew, /* tp_new */
2151};
2152
2153
2154
2155/*
2156 * BufferedRWPair
2157 */
2158
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002159PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002160 "A buffered reader and writer object together.\n"
2161 "\n"
2162 "A buffered reader object and buffered writer object put together to\n"
2163 "form a sequential IO object that can read and write. This is typically\n"
2164 "used with a socket or two-way pipe.\n"
2165 "\n"
2166 "reader and writer are RawIOBase objects that are readable and\n"
2167 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002168 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002169 );
2170
2171/* XXX The usefulness of this (compared to having two separate IO objects) is
2172 * questionable.
2173 */
2174
2175typedef struct {
2176 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002177 buffered *reader;
2178 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002179 PyObject *dict;
2180 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002181} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002182
2183static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002184bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002185{
2186 PyObject *reader, *writer;
2187 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002188
Florent Xicluna109d5732012-07-07 17:03:22 +02002189 if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer,
2190 &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002191 return -1;
2192 }
2193
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002194 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002195 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002196 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002197 return -1;
2198
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002199 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002200 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002201 if (self->reader == NULL)
2202 return -1;
2203
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002204 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002205 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002206 if (self->writer == NULL) {
2207 Py_CLEAR(self->reader);
2208 return -1;
2209 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002210
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002211 return 0;
2212}
2213
2214static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002215bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002216{
2217 Py_VISIT(self->dict);
2218 return 0;
2219}
2220
2221static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002222bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002223{
2224 Py_CLEAR(self->reader);
2225 Py_CLEAR(self->writer);
2226 Py_CLEAR(self->dict);
2227 return 0;
2228}
2229
2230static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002231bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002232{
2233 _PyObject_GC_UNTRACK(self);
2234 Py_CLEAR(self->reader);
2235 Py_CLEAR(self->writer);
2236 Py_CLEAR(self->dict);
2237 Py_TYPE(self)->tp_free((PyObject *) self);
2238}
2239
2240static PyObject *
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002241_forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002242{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002243 PyObject *func = _PyObject_GetAttrId((PyObject *)self, name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002244 PyObject *ret;
2245
2246 if (func == NULL) {
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002247 PyErr_SetString(PyExc_AttributeError, name->string);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002248 return NULL;
2249 }
2250
2251 ret = PyObject_CallObject(func, args);
2252 Py_DECREF(func);
2253 return ret;
2254}
2255
2256static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002257bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002258{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002259 return _forward_call(self->reader, &PyId_read, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002260}
2261
2262static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002263bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002264{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002265 return _forward_call(self->reader, &PyId_peek, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002266}
2267
2268static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002269bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002270{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002271 return _forward_call(self->reader, &PyId_read1, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002272}
2273
2274static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002275bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002276{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002277 return _forward_call(self->reader, &PyId_readinto, args);
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002278}
2279
2280static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002281bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002282{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002283 return _forward_call(self->writer, &PyId_write, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002284}
2285
2286static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002287bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002288{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002289 return _forward_call(self->writer, &PyId_flush, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002290}
2291
2292static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002293bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002294{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002295 return _forward_call(self->reader, &PyId_readable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002296}
2297
2298static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002299bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002300{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002301 return _forward_call(self->writer, &PyId_writable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002302}
2303
2304static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002305bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002306{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002307 PyObject *ret = _forward_call(self->writer, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002308 if (ret == NULL)
2309 return NULL;
2310 Py_DECREF(ret);
2311
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002312 return _forward_call(self->reader, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002313}
2314
2315static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002316bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002317{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002318 PyObject *ret = _forward_call(self->writer, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002319
2320 if (ret != Py_False) {
2321 /* either True or exception */
2322 return ret;
2323 }
2324 Py_DECREF(ret);
2325
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002326 return _forward_call(self->reader, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002327}
2328
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002329static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002330bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002331{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002332 if (self->writer == NULL) {
2333 PyErr_SetString(PyExc_RuntimeError,
2334 "the BufferedRWPair object is being garbage-collected");
2335 return NULL;
2336 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002337 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2338}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002339
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002340static PyMethodDef bufferedrwpair_methods[] = {
2341 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2342 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2343 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2344 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002345
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002346 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2347 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002348
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002349 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2350 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002351
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002352 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2353 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002354
Antoine Pitrou243757e2010-11-05 21:15:39 +00002355 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2356
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002357 {NULL, NULL}
2358};
2359
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002360static PyGetSetDef bufferedrwpair_getset[] = {
2361 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002362 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002363};
2364
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002365PyTypeObject PyBufferedRWPair_Type = {
2366 PyVarObject_HEAD_INIT(NULL, 0)
2367 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002368 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002369 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002370 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002371 0, /*tp_print*/
2372 0, /*tp_getattr*/
2373 0, /*tp_setattr*/
2374 0, /*tp_compare */
2375 0, /*tp_repr*/
2376 0, /*tp_as_number*/
2377 0, /*tp_as_sequence*/
2378 0, /*tp_as_mapping*/
2379 0, /*tp_hash */
2380 0, /*tp_call*/
2381 0, /*tp_str*/
2382 0, /*tp_getattro*/
2383 0, /*tp_setattro*/
2384 0, /*tp_as_buffer*/
2385 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2386 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002387 bufferedrwpair_doc, /* tp_doc */
2388 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2389 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002390 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002391 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002392 0, /* tp_iter */
2393 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002394 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002395 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002396 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002397 0, /* tp_base */
2398 0, /* tp_dict */
2399 0, /* tp_descr_get */
2400 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002401 offsetof(rwpair, dict), /* tp_dictoffset */
2402 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002403 0, /* tp_alloc */
2404 PyType_GenericNew, /* tp_new */
2405};
2406
2407
2408
2409/*
2410 * BufferedRandom
2411 */
2412
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002413PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002414 "A buffered interface to random access streams.\n"
2415 "\n"
2416 "The constructor creates a reader and writer for a seekable stream,\n"
2417 "raw, given in the first argument. If the buffer_size is omitted it\n"
Florent Xicluna109d5732012-07-07 17:03:22 +02002418 "defaults to DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002419 );
2420
2421static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002422bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002423{
Florent Xicluna109d5732012-07-07 17:03:22 +02002424 char *kwlist[] = {"raw", "buffer_size", NULL};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002425 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002426 PyObject *raw;
2427
2428 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002429 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002430
Florent Xicluna109d5732012-07-07 17:03:22 +02002431 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
2432 &raw, &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002433 return -1;
2434 }
2435
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002436 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002437 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002438 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002439 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002440 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002441 return -1;
2442
2443 Py_CLEAR(self->raw);
2444 Py_INCREF(raw);
2445 self->raw = raw;
2446 self->buffer_size = buffer_size;
2447 self->readable = 1;
2448 self->writable = 1;
2449
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002450 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002451 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002452 _bufferedreader_reset_buf(self);
2453 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002454 self->pos = 0;
2455
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002456 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2457 Py_TYPE(raw) == &PyFileIO_Type);
2458
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002459 self->ok = 1;
2460 return 0;
2461}
2462
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002463static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002464 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002465 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2466 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2467 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2468 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2469 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2470 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2471 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002472 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002473 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002474
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002475 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002476
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002477 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2478 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2479 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2480 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2481 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2482 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2483 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2484 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2485 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002486 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002487 {NULL, NULL}
2488};
2489
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002490static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002491 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002492 {NULL}
2493};
2494
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002495static PyGetSetDef bufferedrandom_getset[] = {
2496 {"closed", (getter)buffered_closed_get, NULL, NULL},
2497 {"name", (getter)buffered_name_get, NULL, NULL},
2498 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002499 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002500};
2501
2502
2503PyTypeObject PyBufferedRandom_Type = {
2504 PyVarObject_HEAD_INIT(NULL, 0)
2505 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002506 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002507 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002508 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002509 0, /*tp_print*/
2510 0, /*tp_getattr*/
2511 0, /*tp_setattr*/
2512 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002513 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002514 0, /*tp_as_number*/
2515 0, /*tp_as_sequence*/
2516 0, /*tp_as_mapping*/
2517 0, /*tp_hash */
2518 0, /*tp_call*/
2519 0, /*tp_str*/
2520 0, /*tp_getattro*/
2521 0, /*tp_setattro*/
2522 0, /*tp_as_buffer*/
2523 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2524 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002525 bufferedrandom_doc, /* tp_doc */
2526 (traverseproc)buffered_traverse, /* tp_traverse */
2527 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002528 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002529 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002530 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002531 (iternextfunc)buffered_iternext, /* tp_iternext */
2532 bufferedrandom_methods, /* tp_methods */
2533 bufferedrandom_members, /* tp_members */
2534 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002535 0, /* tp_base */
2536 0, /*tp_dict*/
2537 0, /* tp_descr_get */
2538 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002539 offsetof(buffered, dict), /*tp_dictoffset*/
2540 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002541 0, /* tp_alloc */
2542 PyType_GenericNew, /* tp_new */
2543};