blob: 30451692b3967f87585f9053213d0c6db9fd6926 [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"
3
4 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
6
7 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8*/
9
10#define PY_SSIZE_T_CLEAN
11#include "Python.h"
12#include "structmember.h"
13#include "pythread.h"
14#include "_iomodule.h"
15
16/*
17 * BufferedIOBase class, inherits from IOBase.
18 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000019PyDoc_STRVAR(bufferediobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000020 "Base class for buffered IO objects.\n"
21 "\n"
22 "The main difference with RawIOBase is that the read() method\n"
23 "supports omitting the size argument, and does not have a default\n"
24 "implementation that defers to readinto().\n"
25 "\n"
26 "In addition, read(), readinto() and write() may raise\n"
27 "BlockingIOError if the underlying raw stream is in non-blocking\n"
28 "mode and not ready; unlike their raw counterparts, they will never\n"
29 "return None.\n"
30 "\n"
31 "A typical implementation should not inherit from a RawIOBase\n"
32 "implementation, but wrap one.\n"
33 );
34
35static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000036bufferediobase_readinto(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000037{
38 Py_buffer buf;
39 Py_ssize_t len;
40 PyObject *data;
41
42 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
43 return NULL;
44 }
45
46 data = PyObject_CallMethod(self, "read", "n", buf.len);
47 if (data == NULL)
48 goto error;
49
50 if (!PyBytes_Check(data)) {
51 Py_DECREF(data);
52 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
53 goto error;
54 }
55
56 len = Py_SIZE(data);
57 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
58
59 PyBuffer_Release(&buf);
60 Py_DECREF(data);
61
62 return PyLong_FromSsize_t(len);
63
64 error:
65 PyBuffer_Release(&buf);
66 return NULL;
67}
68
69static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000070bufferediobase_unsupported(const char *message)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000071{
72 PyErr_SetString(IO_STATE->unsupported_operation, message);
73 return NULL;
74}
75
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000076PyDoc_STRVAR(bufferediobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +000077 "Disconnect this buffer from its underlying raw stream and return it.\n"
78 "\n"
79 "After the raw stream has been detached, the buffer is in an unusable\n"
80 "state.\n");
81
82static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000083bufferediobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +000084{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000085 return bufferediobase_unsupported("detach");
Benjamin Petersond2e0c792009-05-01 20:40:59 +000086}
87
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000088PyDoc_STRVAR(bufferediobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000089 "Read and return up to n bytes.\n"
90 "\n"
91 "If the argument is omitted, None, or negative, reads and\n"
92 "returns all data until EOF.\n"
93 "\n"
94 "If the argument is positive, and the underlying raw stream is\n"
95 "not 'interactive', multiple raw reads may be issued to satisfy\n"
96 "the byte count (unless EOF is reached first). But for\n"
97 "interactive raw streams (as well as sockets and pipes), at most\n"
98 "one raw read will be issued, and a short result does not imply\n"
99 "that EOF is imminent.\n"
100 "\n"
101 "Returns an empty bytes object on EOF.\n"
102 "\n"
103 "Returns None if the underlying raw stream was open in non-blocking\n"
104 "mode and no data is available at the moment.\n");
105
106static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000107bufferediobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000108{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000109 return bufferediobase_unsupported("read");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000110}
111
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000112PyDoc_STRVAR(bufferediobase_read1_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000113 "Read and return up to n bytes, with at most one read() call\n"
114 "to the underlying raw stream. A short result does not imply\n"
115 "that EOF is imminent.\n"
116 "\n"
117 "Returns an empty bytes object on EOF.\n");
118
119static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000120bufferediobase_read1(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000121{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000122 return bufferediobase_unsupported("read1");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000123}
124
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000125PyDoc_STRVAR(bufferediobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000126 "Write the given buffer to the IO stream.\n"
127 "\n"
128 "Returns the number of bytes written, which is never less than\n"
129 "len(b).\n"
130 "\n"
131 "Raises BlockingIOError if the buffer is full and the\n"
132 "underlying raw stream cannot accept more data at the moment.\n");
133
134static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000135bufferediobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000136{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000137 return bufferediobase_unsupported("write");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000138}
139
140
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000141static PyMethodDef bufferediobase_methods[] = {
142 {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
143 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
144 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
145 {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
146 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000147 {NULL, NULL}
148};
149
150PyTypeObject PyBufferedIOBase_Type = {
151 PyVarObject_HEAD_INIT(NULL, 0)
152 "_io._BufferedIOBase", /*tp_name*/
153 0, /*tp_basicsize*/
154 0, /*tp_itemsize*/
155 0, /*tp_dealloc*/
156 0, /*tp_print*/
157 0, /*tp_getattr*/
158 0, /*tp_setattr*/
159 0, /*tp_compare */
160 0, /*tp_repr*/
161 0, /*tp_as_number*/
162 0, /*tp_as_sequence*/
163 0, /*tp_as_mapping*/
164 0, /*tp_hash */
165 0, /*tp_call*/
166 0, /*tp_str*/
167 0, /*tp_getattro*/
168 0, /*tp_setattro*/
169 0, /*tp_as_buffer*/
170 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000171 bufferediobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000172 0, /* tp_traverse */
173 0, /* tp_clear */
174 0, /* tp_richcompare */
175 0, /* tp_weaklistoffset */
176 0, /* tp_iter */
177 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000178 bufferediobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000179 0, /* tp_members */
180 0, /* tp_getset */
181 &PyIOBase_Type, /* tp_base */
182 0, /* tp_dict */
183 0, /* tp_descr_get */
184 0, /* tp_descr_set */
185 0, /* tp_dictoffset */
186 0, /* tp_init */
187 0, /* tp_alloc */
188 0, /* tp_new */
189};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000190
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000191
192typedef struct {
193 PyObject_HEAD
194
195 PyObject *raw;
196 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000197 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000198 int readable;
199 int writable;
Antoine Pitroue033e062010-10-29 10:38:18 +0000200 int deallocating;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000201
202 /* True if this is a vanilla Buffered object (rather than a user derived
203 class) *and* the raw stream is a vanilla FileIO object. */
204 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000205
206 /* Absolute position inside the raw stream (-1 if unknown). */
207 Py_off_t abs_pos;
208
209 /* A static buffer of size `buffer_size` */
210 char *buffer;
211 /* Current logical position in the buffer. */
212 Py_off_t pos;
213 /* Position of the raw stream in the buffer. */
214 Py_off_t raw_pos;
215
216 /* Just after the last buffered byte in the buffer, or -1 if the buffer
217 isn't ready for reading. */
218 Py_off_t read_end;
219
220 /* Just after the last byte actually written */
221 Py_off_t write_pos;
222 /* Just after the last byte waiting to be written, or -1 if the buffer
223 isn't ready for writing. */
224 Py_off_t write_end;
225
Georg Brandldfd73442009-04-05 11:47:34 +0000226#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000227 PyThread_type_lock lock;
Georg Brandldfd73442009-04-05 11:47:34 +0000228#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000229
230 Py_ssize_t buffer_size;
231 Py_ssize_t buffer_mask;
232
233 PyObject *dict;
234 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000235} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000236
237/*
238 Implementation notes:
239
240 * BufferedReader, BufferedWriter and BufferedRandom try to share most
241 methods (this is helped by the members `readable` and `writable`, which
242 are initialized in the respective constructors)
243 * They also share a single buffer for reading and writing. This enables
244 interleaved reads and writes without flushing. It also makes the logic
245 a bit trickier to get right.
246 * The absolute position of the raw stream is cached, if possible, in the
247 `abs_pos` member. It must be updated every time an operation is done
248 on the raw stream. If not sure, it can be reinitialized by calling
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000249 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000250 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000251 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
252 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000253
254 NOTE: we should try to maintain block alignment of reads and writes to the
255 raw stream (according to the buffer size), but for now it is only done
256 in read() and friends.
257
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000258*/
259
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000260/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000261
Georg Brandldfd73442009-04-05 11:47:34 +0000262#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000263#define ENTER_BUFFERED(self) \
Antoine Pitrou5800b272009-11-01 12:05:48 +0000264 if (!PyThread_acquire_lock(self->lock, 0)) { \
265 Py_BEGIN_ALLOW_THREADS \
266 PyThread_acquire_lock(self->lock, 1); \
267 Py_END_ALLOW_THREADS \
268 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000269
270#define LEAVE_BUFFERED(self) \
271 PyThread_release_lock(self->lock);
Georg Brandldfd73442009-04-05 11:47:34 +0000272#else
273#define ENTER_BUFFERED(self)
274#define LEAVE_BUFFERED(self)
275#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000276
277#define CHECK_INITIALIZED(self) \
278 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000279 if (self->detached) { \
280 PyErr_SetString(PyExc_ValueError, \
281 "raw stream has been detached"); \
282 } else { \
283 PyErr_SetString(PyExc_ValueError, \
284 "I/O operation on uninitialized object"); \
285 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000286 return NULL; \
287 }
288
289#define CHECK_INITIALIZED_INT(self) \
290 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000291 if (self->detached) { \
292 PyErr_SetString(PyExc_ValueError, \
293 "raw stream has been detached"); \
294 } else { \
295 PyErr_SetString(PyExc_ValueError, \
296 "I/O operation on uninitialized object"); \
297 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000298 return -1; \
299 }
300
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000301#define IS_CLOSED(self) \
302 (self->fast_closed_checks \
303 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000304 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000305
306#define CHECK_CLOSED(self, error_msg) \
307 if (IS_CLOSED(self)) { \
308 PyErr_SetString(PyExc_ValueError, error_msg); \
309 return NULL; \
310 }
311
312
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000313#define VALID_READ_BUFFER(self) \
314 (self->readable && self->read_end != -1)
315
316#define VALID_WRITE_BUFFER(self) \
317 (self->writable && self->write_end != -1)
318
319#define ADJUST_POSITION(self, _new_pos) \
320 do { \
321 self->pos = _new_pos; \
322 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
323 self->read_end = self->pos; \
324 } while(0)
325
326#define READAHEAD(self) \
327 ((self->readable && VALID_READ_BUFFER(self)) \
328 ? (self->read_end - self->pos) : 0)
329
330#define RAW_OFFSET(self) \
331 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
332 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
333
334#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000335 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000336
337#define MINUS_LAST_BLOCK(self, size) \
338 (self->buffer_mask ? \
339 (size & ~self->buffer_mask) : \
340 (self->buffer_size * (size / self->buffer_size)))
341
342
343static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000344buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000345{
Antoine Pitroue033e062010-10-29 10:38:18 +0000346 self->deallocating = 1;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000347 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
348 return;
349 _PyObject_GC_UNTRACK(self);
350 self->ok = 0;
351 if (self->weakreflist != NULL)
352 PyObject_ClearWeakRefs((PyObject *)self);
353 Py_CLEAR(self->raw);
354 if (self->buffer) {
355 PyMem_Free(self->buffer);
356 self->buffer = NULL;
357 }
Georg Brandldfd73442009-04-05 11:47:34 +0000358#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000359 if (self->lock) {
360 PyThread_free_lock(self->lock);
361 self->lock = NULL;
362 }
Georg Brandldfd73442009-04-05 11:47:34 +0000363#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000364 Py_CLEAR(self->dict);
365 Py_TYPE(self)->tp_free((PyObject *)self);
366}
367
368static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000369buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000370{
371 Py_VISIT(self->raw);
372 Py_VISIT(self->dict);
373 return 0;
374}
375
376static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000377buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000378{
379 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
380 return -1;
381 self->ok = 0;
382 Py_CLEAR(self->raw);
383 Py_CLEAR(self->dict);
384 return 0;
385}
386
Antoine Pitroue033e062010-10-29 10:38:18 +0000387/* Because this can call arbitrary code, it shouldn't be called when
388 the refcount is 0 (that is, not directly from tp_dealloc unless
389 the refcount has been temporarily re-incremented). */
390PyObject *
391buffered_dealloc_warn(buffered *self, PyObject *source)
392{
393 if (self->ok && self->raw) {
394 PyObject *r;
395 r = PyObject_CallMethod(self->raw, "_dealloc_warn", "O", source);
396 if (r)
397 Py_DECREF(r);
398 else
399 PyErr_Clear();
400 }
401 Py_RETURN_NONE;
402}
403
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000404/*
405 * _BufferedIOMixin methods
406 * This is not a class, just a collection of methods that will be reused
407 * by BufferedReader and BufferedWriter
408 */
409
410/* Flush and close */
411
412static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000413buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000414{
415 CHECK_INITIALIZED(self)
416 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
417}
418
419static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000420buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000421{
422 int closed;
423 PyObject *res;
424 CHECK_INITIALIZED_INT(self)
425 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
426 if (res == NULL)
427 return -1;
428 closed = PyObject_IsTrue(res);
429 Py_DECREF(res);
430 return closed;
431}
432
433static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000434buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000435{
436 CHECK_INITIALIZED(self)
437 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
438}
439
440static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000441buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000442{
443 PyObject *res = NULL;
444 int r;
445
446 CHECK_INITIALIZED(self)
447 ENTER_BUFFERED(self)
448
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000449 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000450 if (r < 0)
451 goto end;
452 if (r > 0) {
453 res = Py_None;
454 Py_INCREF(res);
455 goto end;
456 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000457
458 if (self->deallocating) {
459 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
460 if (r)
461 Py_DECREF(r);
462 else
463 PyErr_Clear();
464 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000465 /* flush() will most probably re-take the lock, so drop it first */
466 LEAVE_BUFFERED(self)
467 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
468 ENTER_BUFFERED(self)
469 if (res == NULL) {
Antoine Pitrou6be88762010-05-03 16:48:20 +0000470 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000471 }
472 Py_XDECREF(res);
473
474 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
475
476end:
477 LEAVE_BUFFERED(self)
478 return res;
479}
480
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000481/* detach */
482
483static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000484buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000485{
486 PyObject *raw, *res;
487 CHECK_INITIALIZED(self)
488 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
489 if (res == NULL)
490 return NULL;
491 Py_DECREF(res);
492 raw = self->raw;
493 self->raw = NULL;
494 self->detached = 1;
495 self->ok = 0;
496 return raw;
497}
498
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000499/* Inquiries */
500
501static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000502buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000503{
504 CHECK_INITIALIZED(self)
505 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
506}
507
508static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000509buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000510{
511 CHECK_INITIALIZED(self)
512 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
513}
514
515static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000516buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000517{
518 CHECK_INITIALIZED(self)
519 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
520}
521
522static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000523buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000524{
525 CHECK_INITIALIZED(self)
526 return PyObject_GetAttrString(self->raw, "name");
527}
528
529static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000530buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000531{
532 CHECK_INITIALIZED(self)
533 return PyObject_GetAttrString(self->raw, "mode");
534}
535
536/* Lower-level APIs */
537
538static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000539buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000540{
541 CHECK_INITIALIZED(self)
542 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
543}
544
545static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000546buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000547{
548 CHECK_INITIALIZED(self)
549 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
550}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000551
552
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000553/* Forward decls */
554static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000555_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000556static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000557_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000558static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000559_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000560static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000561_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000562static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000563_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000564static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000565_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000566static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000567_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000568static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000569_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000570
571
572/*
573 * Helpers
574 */
575
576/* Returns the address of the `written` member if a BlockingIOError was
577 raised, NULL otherwise. The error is always re-raised. */
578static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000579_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000580{
581 PyObject *t, *v, *tb;
582 PyBlockingIOErrorObject *err;
583
584 PyErr_Fetch(&t, &v, &tb);
585 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
586 PyErr_Restore(t, v, tb);
587 return NULL;
588 }
589 err = (PyBlockingIOErrorObject *) v;
590 /* TODO: sanity check (err->written >= 0) */
591 PyErr_Restore(t, v, tb);
592 return &err->written;
593}
594
595static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000596_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000597{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000598 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000599 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000600 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
601 if (res == NULL)
602 return -1;
603 n = PyNumber_AsOff_t(res, PyExc_ValueError);
604 Py_DECREF(res);
605 if (n < 0) {
606 if (!PyErr_Occurred())
607 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000608 "Raw stream returned invalid position %" PY_PRIdOFF,
609 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000610 return -1;
611 }
612 self->abs_pos = n;
613 return n;
614}
615
616static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000617_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000618{
619 PyObject *res, *posobj, *whenceobj;
620 Py_off_t n;
621
622 posobj = PyLong_FromOff_t(target);
623 if (posobj == NULL)
624 return -1;
625 whenceobj = PyLong_FromLong(whence);
626 if (whenceobj == NULL) {
627 Py_DECREF(posobj);
628 return -1;
629 }
630 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
631 posobj, whenceobj, NULL);
632 Py_DECREF(posobj);
633 Py_DECREF(whenceobj);
634 if (res == NULL)
635 return -1;
636 n = PyNumber_AsOff_t(res, PyExc_ValueError);
637 Py_DECREF(res);
638 if (n < 0) {
639 if (!PyErr_Occurred())
640 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000641 "Raw stream returned invalid position %" PY_PRIdOFF,
642 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000643 return -1;
644 }
645 self->abs_pos = n;
646 return n;
647}
648
649static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000650_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000651{
652 Py_ssize_t n;
653 if (self->buffer_size <= 0) {
654 PyErr_SetString(PyExc_ValueError,
655 "buffer size must be strictly positive");
656 return -1;
657 }
658 if (self->buffer)
659 PyMem_Free(self->buffer);
660 self->buffer = PyMem_Malloc(self->buffer_size);
661 if (self->buffer == NULL) {
662 PyErr_NoMemory();
663 return -1;
664 }
Georg Brandldfd73442009-04-05 11:47:34 +0000665#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000666 if (self->lock)
667 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000668 self->lock = PyThread_allocate_lock();
669 if (self->lock == NULL) {
670 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
671 return -1;
672 }
Georg Brandldfd73442009-04-05 11:47:34 +0000673#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000674 /* Find out whether buffer_size is a power of 2 */
675 /* XXX is this optimization useful? */
676 for (n = self->buffer_size - 1; n & 1; n >>= 1)
677 ;
678 if (n == 0)
679 self->buffer_mask = self->buffer_size - 1;
680 else
681 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000682 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000683 PyErr_Clear();
684 return 0;
685}
686
687/*
688 * Shared methods and wrappers
689 */
690
691static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000692buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000693{
694 PyObject *res;
695
696 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000697 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000698
699 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000700 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000701 if (res != NULL && self->readable) {
702 /* Rewind the raw stream so that its position corresponds to
703 the current logical position. */
704 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000705 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000706 if (n == -1)
707 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000708 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000709 }
710 LEAVE_BUFFERED(self)
711
712 return res;
713}
714
715static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000716buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000717{
718 Py_ssize_t n = 0;
719 PyObject *res = NULL;
720
721 CHECK_INITIALIZED(self)
722 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
723 return NULL;
724 }
725
726 ENTER_BUFFERED(self)
727
728 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000729 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000730 if (res == NULL)
731 goto end;
732 Py_CLEAR(res);
733 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000734 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000735
736end:
737 LEAVE_BUFFERED(self)
738 return res;
739}
740
741static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000742buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000743{
744 Py_ssize_t n = -1;
745 PyObject *res;
746
747 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000748 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000749 return NULL;
750 }
751 if (n < -1) {
752 PyErr_SetString(PyExc_ValueError,
753 "read length must be positive or -1");
754 return NULL;
755 }
756
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000757 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000758
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000759 if (n == -1) {
760 /* The number of bytes is unspecified, read until the end of stream */
761 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000762 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000763 LEAVE_BUFFERED(self)
764 }
765 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000766 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000767 if (res == Py_None) {
768 Py_DECREF(res);
769 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000770 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000771 LEAVE_BUFFERED(self)
772 }
773 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000774
775 return res;
776}
777
778static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000779buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000780{
781 Py_ssize_t n, have, r;
782 PyObject *res = NULL;
783
784 CHECK_INITIALIZED(self)
785 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
786 return NULL;
787 }
788
789 if (n < 0) {
790 PyErr_SetString(PyExc_ValueError,
791 "read length must be positive");
792 return NULL;
793 }
794 if (n == 0)
795 return PyBytes_FromStringAndSize(NULL, 0);
796
797 ENTER_BUFFERED(self)
798
799 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000800 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000801 if (res == NULL)
802 goto end;
803 Py_CLEAR(res);
804 }
805
806 /* Return up to n bytes. If at least one byte is buffered, we
807 only return buffered bytes. Otherwise, we do one raw read. */
808
809 /* XXX: this mimicks the io.py implementation but is probably wrong.
810 If we need to read from the raw stream, then we could actually read
811 all `n` bytes asked by the caller (and possibly more, so as to fill
812 our buffer for the next reads). */
813
814 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
815 if (have > 0) {
816 if (n > have)
817 n = have;
818 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
819 if (res == NULL)
820 goto end;
821 self->pos += n;
822 goto end;
823 }
824
825 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000826 _bufferedreader_reset_buf(self);
827 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000828 if (r == -1)
829 goto end;
830 if (r == -2)
831 r = 0;
832 if (n > r)
833 n = r;
834 res = PyBytes_FromStringAndSize(self->buffer, n);
835 if (res == NULL)
836 goto end;
837 self->pos = n;
838
839end:
840 LEAVE_BUFFERED(self)
841 return res;
842}
843
844static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000845buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000846{
847 PyObject *res = NULL;
848
849 CHECK_INITIALIZED(self)
850
851 /* TODO: use raw.readinto() instead! */
852 if (self->writable) {
853 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000854 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000855 LEAVE_BUFFERED(self)
856 if (res == NULL)
857 goto end;
858 Py_DECREF(res);
859 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000860 res = bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000861
862end:
863 return res;
864}
865
866static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000867_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000868{
869 PyObject *res = NULL;
870 PyObject *chunks = NULL;
871 Py_ssize_t n, written = 0;
872 const char *start, *s, *end;
873
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000874 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000875
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000876 /* First, try to find a line in the buffer. This can run unlocked because
877 the calls to the C API are simple enough that they can't trigger
878 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000879 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
880 if (limit >= 0 && n > limit)
881 n = limit;
882 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000883 s = memchr(start, '\n', n);
884 if (s != NULL) {
885 res = PyBytes_FromStringAndSize(start, s - start + 1);
886 if (res != NULL)
887 self->pos += s - start + 1;
888 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000889 }
890 if (n == limit) {
891 res = PyBytes_FromStringAndSize(start, n);
892 if (res != NULL)
893 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000894 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000895 }
896
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000897 ENTER_BUFFERED(self)
898
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000899 /* Now we try to get some more from the raw stream */
900 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000901 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000902 if (res == NULL)
903 goto end;
904 Py_CLEAR(res);
905 }
906 chunks = PyList_New(0);
907 if (chunks == NULL)
908 goto end;
909 if (n > 0) {
910 res = PyBytes_FromStringAndSize(start, n);
911 if (res == NULL)
912 goto end;
913 if (PyList_Append(chunks, res) < 0) {
914 Py_CLEAR(res);
915 goto end;
916 }
917 Py_CLEAR(res);
918 written += n;
919 if (limit >= 0)
920 limit -= n;
921 }
922
923 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000924 _bufferedreader_reset_buf(self);
925 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000926 if (n == -1)
927 goto end;
928 if (n <= 0)
929 break;
930 if (limit >= 0 && n > limit)
931 n = limit;
932 start = self->buffer;
933 end = start + n;
934 s = start;
935 while (s < end) {
936 if (*s++ == '\n') {
937 res = PyBytes_FromStringAndSize(start, s - start);
938 if (res == NULL)
939 goto end;
940 self->pos = s - start;
941 goto found;
942 }
943 }
944 res = PyBytes_FromStringAndSize(start, n);
945 if (res == NULL)
946 goto end;
947 if (n == limit) {
948 self->pos = n;
949 break;
950 }
951 if (PyList_Append(chunks, res) < 0) {
952 Py_CLEAR(res);
953 goto end;
954 }
955 Py_CLEAR(res);
956 written += n;
957 if (limit >= 0)
958 limit -= n;
959 }
960found:
961 if (res != NULL && PyList_Append(chunks, res) < 0) {
962 Py_CLEAR(res);
963 goto end;
964 }
965 Py_CLEAR(res);
966 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
967
968end:
969 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000970end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000971 Py_XDECREF(chunks);
972 return res;
973}
974
975static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000976buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000977{
978 Py_ssize_t limit = -1;
979
980 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000981 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000982 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000983 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000984}
985
986
987static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000988buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000989{
990 Py_off_t pos;
991
992 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000993 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000994 if (pos == -1)
995 return NULL;
996 pos -= RAW_OFFSET(self);
997 /* TODO: sanity check (pos >= 0) */
998 return PyLong_FromOff_t(pos);
999}
1000
1001static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001002buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001003{
1004 Py_off_t target, n;
1005 int whence = 0;
1006 PyObject *targetobj, *res = NULL;
1007
1008 CHECK_INITIALIZED(self)
1009 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1010 return NULL;
1011 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001012 if (whence < 0 || whence > 2) {
1013 PyErr_Format(PyExc_ValueError,
1014 "whence must be between 0 and 2, not %d", whence);
1015 return NULL;
1016 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001017
1018 CHECK_CLOSED(self, "seek of closed file")
1019
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001020 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1021 if (target == -1 && PyErr_Occurred())
1022 return NULL;
1023
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001024 if (whence != 2 && self->readable) {
1025 Py_off_t current, avail;
1026 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001027 so as to return quickly if possible. Also, we needn't take the
1028 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001029 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001030 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1031 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001032 current = RAW_TELL(self);
1033 avail = READAHEAD(self);
1034 if (avail > 0) {
1035 Py_off_t offset;
1036 if (whence == 0)
1037 offset = target - (current - RAW_OFFSET(self));
1038 else
1039 offset = target;
1040 if (offset >= -self->pos && offset <= avail) {
1041 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001042 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001043 }
1044 }
1045 }
1046
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001047 ENTER_BUFFERED(self)
1048
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001049 /* Fallback: invoke raw seek() method and clear buffer */
1050 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001051 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001052 if (res == NULL)
1053 goto end;
1054 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001055 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001056 }
1057
1058 /* TODO: align on block boundary and read buffer if needed? */
1059 if (whence == 1)
1060 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001061 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001062 if (n == -1)
1063 goto end;
1064 self->raw_pos = -1;
1065 res = PyLong_FromOff_t(n);
1066 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001067 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001068
1069end:
1070 LEAVE_BUFFERED(self)
1071 return res;
1072}
1073
1074static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001075buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001076{
1077 PyObject *pos = Py_None;
1078 PyObject *res = NULL;
1079
1080 CHECK_INITIALIZED(self)
1081 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1082 return NULL;
1083 }
1084
1085 ENTER_BUFFERED(self)
1086
1087 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001088 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001089 if (res == NULL)
1090 goto end;
1091 Py_CLEAR(res);
1092 }
1093 if (self->readable) {
1094 if (pos == Py_None) {
1095 /* Rewind the raw stream so that its position corresponds to
1096 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001097 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001098 goto end;
1099 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001100 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001101 }
1102 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1103 if (res == NULL)
1104 goto end;
1105 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001106 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001107 PyErr_Clear();
1108
1109end:
1110 LEAVE_BUFFERED(self)
1111 return res;
1112}
1113
1114static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001115buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001116{
1117 PyObject *line;
1118 PyTypeObject *tp;
1119
1120 CHECK_INITIALIZED(self);
1121
1122 tp = Py_TYPE(self);
1123 if (tp == &PyBufferedReader_Type ||
1124 tp == &PyBufferedRandom_Type) {
1125 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001126 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001127 }
1128 else {
1129 line = PyObject_CallMethodObjArgs((PyObject *)self,
1130 _PyIO_str_readline, NULL);
1131 if (line && !PyBytes_Check(line)) {
1132 PyErr_Format(PyExc_IOError,
1133 "readline() should have returned a bytes object, "
1134 "not '%.200s'", Py_TYPE(line)->tp_name);
1135 Py_DECREF(line);
1136 return NULL;
1137 }
1138 }
1139
1140 if (line == NULL)
1141 return NULL;
1142
1143 if (PyBytes_GET_SIZE(line) == 0) {
1144 /* Reached EOF or would have blocked */
1145 Py_DECREF(line);
1146 return NULL;
1147 }
1148
1149 return line;
1150}
1151
Antoine Pitrou716c4442009-05-23 19:04:03 +00001152static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001153buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001154{
1155 PyObject *nameobj, *res;
1156
1157 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1158 if (nameobj == NULL) {
1159 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1160 PyErr_Clear();
1161 else
1162 return NULL;
1163 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1164 }
1165 else {
1166 res = PyUnicode_FromFormat("<%s name=%R>",
1167 Py_TYPE(self)->tp_name, nameobj);
1168 Py_DECREF(nameobj);
1169 }
1170 return res;
1171}
1172
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001173/*
1174 * class BufferedReader
1175 */
1176
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001177PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001178 "Create a new buffered reader using the given readable raw IO object.");
1179
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001180static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001181{
1182 self->read_end = -1;
1183}
1184
1185static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001186bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001187{
1188 char *kwlist[] = {"raw", "buffer_size", NULL};
1189 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1190 PyObject *raw;
1191
1192 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001193 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001194
1195 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1196 &raw, &buffer_size)) {
1197 return -1;
1198 }
1199
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001200 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001201 return -1;
1202
1203 Py_CLEAR(self->raw);
1204 Py_INCREF(raw);
1205 self->raw = raw;
1206 self->buffer_size = buffer_size;
1207 self->readable = 1;
1208 self->writable = 0;
1209
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001210 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001211 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001212 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001213
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001214 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1215 Py_TYPE(raw) == &PyFileIO_Type);
1216
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001217 self->ok = 1;
1218 return 0;
1219}
1220
1221static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001222_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001223{
1224 Py_buffer buf;
1225 PyObject *memobj, *res;
1226 Py_ssize_t n;
1227 /* NOTE: the buffer needn't be released as its object is NULL. */
1228 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1229 return -1;
1230 memobj = PyMemoryView_FromBuffer(&buf);
1231 if (memobj == NULL)
1232 return -1;
1233 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1234 Py_DECREF(memobj);
1235 if (res == NULL)
1236 return -1;
1237 if (res == Py_None) {
1238 /* Non-blocking stream would have blocked. Special return code! */
1239 Py_DECREF(res);
1240 return -2;
1241 }
1242 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1243 Py_DECREF(res);
1244 if (n < 0 || n > len) {
1245 PyErr_Format(PyExc_IOError,
1246 "raw readinto() returned invalid length %zd "
1247 "(should have been between 0 and %zd)", n, len);
1248 return -1;
1249 }
1250 if (n > 0 && self->abs_pos != -1)
1251 self->abs_pos += n;
1252 return n;
1253}
1254
1255static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001256_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001257{
1258 Py_ssize_t start, len, n;
1259 if (VALID_READ_BUFFER(self))
1260 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1261 else
1262 start = 0;
1263 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001264 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001265 if (n <= 0)
1266 return n;
1267 self->read_end = start + n;
1268 self->raw_pos = start + n;
1269 return n;
1270}
1271
1272static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001273_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001274{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001275 Py_ssize_t current_size;
1276 PyObject *res, *data = NULL;
1277 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001278
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001279 if (chunks == NULL)
1280 return NULL;
1281
1282 /* First copy what we have in the current buffer. */
1283 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1284 if (current_size) {
1285 data = PyBytes_FromStringAndSize(
1286 self->buffer + self->pos, current_size);
1287 if (data == NULL) {
1288 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001289 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001290 }
1291 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001292 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001293 /* We're going past the buffer's bounds, flush it */
1294 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001295 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001296 if (res == NULL) {
1297 Py_DECREF(chunks);
1298 return NULL;
1299 }
1300 Py_CLEAR(res);
1301 }
1302 while (1) {
1303 if (data) {
1304 if (PyList_Append(chunks, data) < 0) {
1305 Py_DECREF(data);
1306 Py_DECREF(chunks);
1307 return NULL;
1308 }
1309 Py_DECREF(data);
1310 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001311
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001312 /* Read until EOF or until read() would block. */
1313 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1314 if (data == NULL) {
1315 Py_DECREF(chunks);
1316 return NULL;
1317 }
1318 if (data != Py_None && !PyBytes_Check(data)) {
1319 Py_DECREF(data);
1320 Py_DECREF(chunks);
1321 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1322 return NULL;
1323 }
1324 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1325 if (current_size == 0) {
1326 Py_DECREF(chunks);
1327 return data;
1328 }
1329 else {
1330 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1331 Py_DECREF(data);
1332 Py_DECREF(chunks);
1333 return res;
1334 }
1335 }
1336 current_size += PyBytes_GET_SIZE(data);
1337 if (self->abs_pos != -1)
1338 self->abs_pos += PyBytes_GET_SIZE(data);
1339 }
1340}
1341
1342/* Read n bytes from the buffer if it can, otherwise return None.
1343 This function is simple enough that it can run unlocked. */
1344static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001345_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001346{
1347 Py_ssize_t current_size;
1348
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001349 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1350 if (n <= current_size) {
1351 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001352 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1353 if (res != NULL)
1354 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001355 return res;
1356 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001357 Py_RETURN_NONE;
1358}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001359
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001360/* Generic read function: read from the stream until enough bytes are read,
1361 * or until an EOF occurs or until read() would block.
1362 */
1363static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001364_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001365{
1366 PyObject *res = NULL;
1367 Py_ssize_t current_size, remaining, written;
1368 char *out;
1369
1370 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1371 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001372 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001373
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001374 res = PyBytes_FromStringAndSize(NULL, n);
1375 if (res == NULL)
1376 goto error;
1377 out = PyBytes_AS_STRING(res);
1378 remaining = n;
1379 written = 0;
1380 if (current_size > 0) {
1381 memcpy(out, self->buffer + self->pos, current_size);
1382 remaining -= current_size;
1383 written += current_size;
1384 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001385 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001386 while (remaining > 0) {
1387 /* We want to read a whole block at the end into buffer.
1388 If we had readv() we could do this in one pass. */
1389 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1390 if (r == 0)
1391 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001392 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001393 if (r == -1)
1394 goto error;
1395 if (r == 0 || r == -2) {
1396 /* EOF occurred or read() would block. */
1397 if (r == 0 || written > 0) {
1398 if (_PyBytes_Resize(&res, written))
1399 goto error;
1400 return res;
1401 }
1402 Py_DECREF(res);
1403 Py_INCREF(Py_None);
1404 return Py_None;
1405 }
1406 remaining -= r;
1407 written += r;
1408 }
1409 assert(remaining <= self->buffer_size);
1410 self->pos = 0;
1411 self->raw_pos = 0;
1412 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001413 /* NOTE: when the read is satisfied, we avoid issuing any additional
1414 reads, which could block indefinitely (e.g. on a socket).
1415 See issue #9550. */
1416 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001417 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001418 if (r == -1)
1419 goto error;
1420 if (r == 0 || r == -2) {
1421 /* EOF occurred or read() would block. */
1422 if (r == 0 || written > 0) {
1423 if (_PyBytes_Resize(&res, written))
1424 goto error;
1425 return res;
1426 }
1427 Py_DECREF(res);
1428 Py_INCREF(Py_None);
1429 return Py_None;
1430 }
1431 if (remaining > r) {
1432 memcpy(out + written, self->buffer + self->pos, r);
1433 written += r;
1434 self->pos += r;
1435 remaining -= r;
1436 }
1437 else if (remaining > 0) {
1438 memcpy(out + written, self->buffer + self->pos, remaining);
1439 written += remaining;
1440 self->pos += remaining;
1441 remaining = 0;
1442 }
1443 if (remaining == 0)
1444 break;
1445 }
1446
1447 return res;
1448
1449error:
1450 Py_XDECREF(res);
1451 return NULL;
1452}
1453
1454static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001455_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001456{
1457 Py_ssize_t have, r;
1458
1459 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1460 /* Constraints:
1461 1. we don't want to advance the file position.
1462 2. we don't want to lose block alignment, so we can't shift the buffer
1463 to make some place.
1464 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1465 */
1466 if (have > 0) {
1467 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1468 }
1469
1470 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001471 _bufferedreader_reset_buf(self);
1472 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001473 if (r == -1)
1474 return NULL;
1475 if (r == -2)
1476 r = 0;
1477 self->pos = 0;
1478 return PyBytes_FromStringAndSize(self->buffer, r);
1479}
1480
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001481static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001482 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001483 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1484 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1485 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1486 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1487 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1488 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1489 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1490 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001491 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001492
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001493 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1494 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1495 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1496 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1497 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1498 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1499 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001500 {NULL, NULL}
1501};
1502
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001503static PyMemberDef bufferedreader_members[] = {
1504 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001505 {NULL}
1506};
1507
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001508static PyGetSetDef bufferedreader_getset[] = {
1509 {"closed", (getter)buffered_closed_get, NULL, NULL},
1510 {"name", (getter)buffered_name_get, NULL, NULL},
1511 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001512 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001513};
1514
1515
1516PyTypeObject PyBufferedReader_Type = {
1517 PyVarObject_HEAD_INIT(NULL, 0)
1518 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001519 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001520 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001521 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001522 0, /*tp_print*/
1523 0, /*tp_getattr*/
1524 0, /*tp_setattr*/
1525 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001526 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001527 0, /*tp_as_number*/
1528 0, /*tp_as_sequence*/
1529 0, /*tp_as_mapping*/
1530 0, /*tp_hash */
1531 0, /*tp_call*/
1532 0, /*tp_str*/
1533 0, /*tp_getattro*/
1534 0, /*tp_setattro*/
1535 0, /*tp_as_buffer*/
1536 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1537 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001538 bufferedreader_doc, /* tp_doc */
1539 (traverseproc)buffered_traverse, /* tp_traverse */
1540 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001541 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001542 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001543 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001544 (iternextfunc)buffered_iternext, /* tp_iternext */
1545 bufferedreader_methods, /* tp_methods */
1546 bufferedreader_members, /* tp_members */
1547 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001548 0, /* tp_base */
1549 0, /* tp_dict */
1550 0, /* tp_descr_get */
1551 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001552 offsetof(buffered, dict), /* tp_dictoffset */
1553 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001554 0, /* tp_alloc */
1555 PyType_GenericNew, /* tp_new */
1556};
1557
1558
Benjamin Peterson59406a92009-03-26 17:10:29 +00001559
1560static int
1561complain_about_max_buffer_size(void)
1562{
1563 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1564 "max_buffer_size is deprecated", 1) < 0)
1565 return 0;
1566 return 1;
1567}
1568
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001569/*
1570 * class BufferedWriter
1571 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001572PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001573 "A buffer for a writeable sequential RawIO object.\n"
1574 "\n"
1575 "The constructor creates a BufferedWriter for the given writeable raw\n"
1576 "stream. If the buffer_size is not given, it defaults to\n"
1577 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1578 );
1579
1580static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001581_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001582{
1583 self->write_pos = 0;
1584 self->write_end = -1;
1585}
1586
1587static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001588bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001589{
1590 /* TODO: properly deprecate max_buffer_size */
1591 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1592 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001593 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001594 PyObject *raw;
1595
1596 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001597 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001598
1599 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1600 &raw, &buffer_size, &max_buffer_size)) {
1601 return -1;
1602 }
1603
Benjamin Peterson59406a92009-03-26 17:10:29 +00001604 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1605 return -1;
1606
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001607 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001608 return -1;
1609
1610 Py_CLEAR(self->raw);
1611 Py_INCREF(raw);
1612 self->raw = raw;
1613 self->readable = 0;
1614 self->writable = 1;
1615
1616 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001617 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001618 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001619 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001620 self->pos = 0;
1621
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001622 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1623 Py_TYPE(raw) == &PyFileIO_Type);
1624
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001625 self->ok = 1;
1626 return 0;
1627}
1628
1629static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001630_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001631{
1632 Py_buffer buf;
1633 PyObject *memobj, *res;
1634 Py_ssize_t n;
1635 /* NOTE: the buffer needn't be released as its object is NULL. */
1636 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1637 return -1;
1638 memobj = PyMemoryView_FromBuffer(&buf);
1639 if (memobj == NULL)
1640 return -1;
1641 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1642 Py_DECREF(memobj);
1643 if (res == NULL)
1644 return -1;
1645 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1646 Py_DECREF(res);
1647 if (n < 0 || n > len) {
1648 PyErr_Format(PyExc_IOError,
1649 "raw write() returned invalid length %zd "
1650 "(should have been between 0 and %zd)", n, len);
1651 return -1;
1652 }
1653 if (n > 0 && self->abs_pos != -1)
1654 self->abs_pos += n;
1655 return n;
1656}
1657
1658/* `restore_pos` is 1 if we need to restore the raw stream position at
1659 the end, 0 otherwise. */
1660static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001661_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001662{
1663 Py_ssize_t written = 0;
1664 Py_off_t n, rewind;
1665
1666 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1667 goto end;
1668 /* First, rewind */
1669 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1670 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001671 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001672 if (n < 0) {
1673 goto error;
1674 }
1675 self->raw_pos -= rewind;
1676 }
1677 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001678 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001679 self->buffer + self->write_pos,
1680 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1681 Py_off_t, Py_ssize_t));
1682 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001683 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001684 if (w == NULL)
1685 goto error;
1686 self->write_pos += *w;
1687 self->raw_pos = self->write_pos;
1688 written += *w;
1689 *w = written;
1690 /* Already re-raised */
1691 goto error;
1692 }
1693 self->write_pos += n;
1694 self->raw_pos = self->write_pos;
1695 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001696 /* Partial writes can return successfully when interrupted by a
1697 signal (see write(2)). We must run signal handlers before
1698 blocking another time, possibly indefinitely. */
1699 if (PyErr_CheckSignals() < 0)
1700 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001701 }
1702
1703 if (restore_pos) {
1704 Py_off_t forward = rewind - written;
1705 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001706 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001707 if (n < 0) {
1708 goto error;
1709 }
1710 self->raw_pos += forward;
1711 }
1712 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001713 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001714
1715end:
1716 Py_RETURN_NONE;
1717
1718error:
1719 return NULL;
1720}
1721
1722static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001723bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001724{
1725 PyObject *res = NULL;
1726 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001727 Py_ssize_t written, avail, remaining;
1728 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001729
1730 CHECK_INITIALIZED(self)
1731 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1732 return NULL;
1733 }
1734
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001735 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001736 PyErr_SetString(PyExc_ValueError, "write to closed file");
1737 PyBuffer_Release(&buf);
1738 return NULL;
1739 }
1740
1741 ENTER_BUFFERED(self)
1742
1743 /* Fast path: the data to write can be fully buffered. */
1744 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1745 self->pos = 0;
1746 self->raw_pos = 0;
1747 }
1748 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1749 if (buf.len <= avail) {
1750 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1751 if (!VALID_WRITE_BUFFER(self)) {
1752 self->write_pos = self->pos;
1753 }
1754 ADJUST_POSITION(self, self->pos + buf.len);
1755 if (self->pos > self->write_end)
1756 self->write_end = self->pos;
1757 written = buf.len;
1758 goto end;
1759 }
1760
1761 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001762 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001763 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001764 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001765 if (w == NULL)
1766 goto error;
1767 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001768 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001769 /* Make some place by shifting the buffer. */
1770 assert(VALID_WRITE_BUFFER(self));
1771 memmove(self->buffer, self->buffer + self->write_pos,
1772 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1773 Py_off_t, Py_ssize_t));
1774 self->write_end -= self->write_pos;
1775 self->raw_pos -= self->write_pos;
1776 self->pos -= self->write_pos;
1777 self->write_pos = 0;
1778 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1779 Py_off_t, Py_ssize_t);
1780 if (buf.len <= avail) {
1781 /* Everything can be buffered */
1782 PyErr_Clear();
1783 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1784 self->write_end += buf.len;
1785 written = buf.len;
1786 goto end;
1787 }
1788 /* Buffer as much as possible. */
1789 memcpy(self->buffer + self->write_end, buf.buf, avail);
1790 self->write_end += avail;
1791 /* Already re-raised */
1792 *w = avail;
1793 goto error;
1794 }
1795 Py_CLEAR(res);
1796
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001797 /* Adjust the raw stream position if it is away from the logical stream
1798 position. This happens if the read buffer has been filled but not
1799 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1800 the raw stream by itself).
1801 Fixes issue #6629.
1802 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001803 offset = RAW_OFFSET(self);
1804 if (offset != 0) {
1805 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001806 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001807 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001808 }
1809
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001810 /* Then write buf itself. At this point the buffer has been emptied. */
1811 remaining = buf.len;
1812 written = 0;
1813 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001814 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001815 self, (char *) buf.buf + written, buf.len - written);
1816 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001817 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001818 if (w == NULL)
1819 goto error;
1820 written += *w;
1821 remaining -= *w;
1822 if (remaining > self->buffer_size) {
1823 /* Can't buffer everything, still buffer as much as possible */
1824 memcpy(self->buffer,
1825 (char *) buf.buf + written, self->buffer_size);
1826 self->raw_pos = 0;
1827 ADJUST_POSITION(self, self->buffer_size);
1828 self->write_end = self->buffer_size;
1829 *w = written + self->buffer_size;
1830 /* Already re-raised */
1831 goto error;
1832 }
1833 PyErr_Clear();
1834 break;
1835 }
1836 written += n;
1837 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001838 /* Partial writes can return successfully when interrupted by a
1839 signal (see write(2)). We must run signal handlers before
1840 blocking another time, possibly indefinitely. */
1841 if (PyErr_CheckSignals() < 0)
1842 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001843 }
1844 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001845 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001846 if (remaining > 0) {
1847 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1848 written += remaining;
1849 }
1850 self->write_pos = 0;
1851 /* TODO: sanity check (remaining >= 0) */
1852 self->write_end = remaining;
1853 ADJUST_POSITION(self, remaining);
1854 self->raw_pos = 0;
1855
1856end:
1857 res = PyLong_FromSsize_t(written);
1858
1859error:
1860 LEAVE_BUFFERED(self)
1861 PyBuffer_Release(&buf);
1862 return res;
1863}
1864
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001865static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001866 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001867 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1868 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1869 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1870 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1871 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1872 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1873 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001874 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001875
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001876 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1877 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1878 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1879 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1880 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001881 {NULL, NULL}
1882};
1883
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001884static PyMemberDef bufferedwriter_members[] = {
1885 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001886 {NULL}
1887};
1888
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001889static PyGetSetDef bufferedwriter_getset[] = {
1890 {"closed", (getter)buffered_closed_get, NULL, NULL},
1891 {"name", (getter)buffered_name_get, NULL, NULL},
1892 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001893 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001894};
1895
1896
1897PyTypeObject PyBufferedWriter_Type = {
1898 PyVarObject_HEAD_INIT(NULL, 0)
1899 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001900 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001901 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001902 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001903 0, /*tp_print*/
1904 0, /*tp_getattr*/
1905 0, /*tp_setattr*/
1906 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001907 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001908 0, /*tp_as_number*/
1909 0, /*tp_as_sequence*/
1910 0, /*tp_as_mapping*/
1911 0, /*tp_hash */
1912 0, /*tp_call*/
1913 0, /*tp_str*/
1914 0, /*tp_getattro*/
1915 0, /*tp_setattro*/
1916 0, /*tp_as_buffer*/
1917 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1918 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001919 bufferedwriter_doc, /* tp_doc */
1920 (traverseproc)buffered_traverse, /* tp_traverse */
1921 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001922 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001923 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001924 0, /* tp_iter */
1925 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001926 bufferedwriter_methods, /* tp_methods */
1927 bufferedwriter_members, /* tp_members */
1928 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001929 0, /* tp_base */
1930 0, /* tp_dict */
1931 0, /* tp_descr_get */
1932 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001933 offsetof(buffered, dict), /* tp_dictoffset */
1934 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001935 0, /* tp_alloc */
1936 PyType_GenericNew, /* tp_new */
1937};
1938
1939
1940
1941/*
1942 * BufferedRWPair
1943 */
1944
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001945PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001946 "A buffered reader and writer object together.\n"
1947 "\n"
1948 "A buffered reader object and buffered writer object put together to\n"
1949 "form a sequential IO object that can read and write. This is typically\n"
1950 "used with a socket or two-way pipe.\n"
1951 "\n"
1952 "reader and writer are RawIOBase objects that are readable and\n"
1953 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001954 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001955 );
1956
1957/* XXX The usefulness of this (compared to having two separate IO objects) is
1958 * questionable.
1959 */
1960
1961typedef struct {
1962 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001963 buffered *reader;
1964 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001965 PyObject *dict;
1966 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001967} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001968
1969static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001970bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001971{
1972 PyObject *reader, *writer;
1973 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001974 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001975
1976 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1977 &buffer_size, &max_buffer_size)) {
1978 return -1;
1979 }
1980
Benjamin Peterson59406a92009-03-26 17:10:29 +00001981 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1982 return -1;
1983
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001984 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001985 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001986 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001987 return -1;
1988
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001989 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001990 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001991 if (self->reader == NULL)
1992 return -1;
1993
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001994 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001995 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001996 if (self->writer == NULL) {
1997 Py_CLEAR(self->reader);
1998 return -1;
1999 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002000
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002001 return 0;
2002}
2003
2004static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002005bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002006{
2007 Py_VISIT(self->dict);
2008 return 0;
2009}
2010
2011static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002012bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002013{
2014 Py_CLEAR(self->reader);
2015 Py_CLEAR(self->writer);
2016 Py_CLEAR(self->dict);
2017 return 0;
2018}
2019
2020static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002021bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002022{
2023 _PyObject_GC_UNTRACK(self);
2024 Py_CLEAR(self->reader);
2025 Py_CLEAR(self->writer);
2026 Py_CLEAR(self->dict);
2027 Py_TYPE(self)->tp_free((PyObject *) self);
2028}
2029
2030static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002031_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002032{
2033 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2034 PyObject *ret;
2035
2036 if (func == NULL) {
2037 PyErr_SetString(PyExc_AttributeError, name);
2038 return NULL;
2039 }
2040
2041 ret = PyObject_CallObject(func, args);
2042 Py_DECREF(func);
2043 return ret;
2044}
2045
2046static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002047bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002048{
2049 return _forward_call(self->reader, "read", args);
2050}
2051
2052static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002053bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002054{
2055 return _forward_call(self->reader, "peek", args);
2056}
2057
2058static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002059bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002060{
2061 return _forward_call(self->reader, "read1", args);
2062}
2063
2064static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002065bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002066{
2067 return _forward_call(self->reader, "readinto", args);
2068}
2069
2070static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002071bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002072{
2073 return _forward_call(self->writer, "write", args);
2074}
2075
2076static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002077bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002078{
2079 return _forward_call(self->writer, "flush", args);
2080}
2081
2082static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002083bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002084{
2085 return _forward_call(self->reader, "readable", args);
2086}
2087
2088static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002089bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002090{
2091 return _forward_call(self->writer, "writable", args);
2092}
2093
2094static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002095bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002096{
2097 PyObject *ret = _forward_call(self->writer, "close", args);
2098 if (ret == NULL)
2099 return NULL;
2100 Py_DECREF(ret);
2101
2102 return _forward_call(self->reader, "close", args);
2103}
2104
2105static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002106bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002107{
2108 PyObject *ret = _forward_call(self->writer, "isatty", args);
2109
2110 if (ret != Py_False) {
2111 /* either True or exception */
2112 return ret;
2113 }
2114 Py_DECREF(ret);
2115
2116 return _forward_call(self->reader, "isatty", args);
2117}
2118
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002119static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002120bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002121{
2122 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2123}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002124
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002125static PyMethodDef bufferedrwpair_methods[] = {
2126 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2127 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2128 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2129 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002130
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002131 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2132 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002133
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002134 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2135 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002136
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002137 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2138 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002139
2140 {NULL, NULL}
2141};
2142
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002143static PyGetSetDef bufferedrwpair_getset[] = {
2144 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002145 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002146};
2147
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002148PyTypeObject PyBufferedRWPair_Type = {
2149 PyVarObject_HEAD_INIT(NULL, 0)
2150 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002151 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002152 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002153 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002154 0, /*tp_print*/
2155 0, /*tp_getattr*/
2156 0, /*tp_setattr*/
2157 0, /*tp_compare */
2158 0, /*tp_repr*/
2159 0, /*tp_as_number*/
2160 0, /*tp_as_sequence*/
2161 0, /*tp_as_mapping*/
2162 0, /*tp_hash */
2163 0, /*tp_call*/
2164 0, /*tp_str*/
2165 0, /*tp_getattro*/
2166 0, /*tp_setattro*/
2167 0, /*tp_as_buffer*/
2168 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2169 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002170 bufferedrwpair_doc, /* tp_doc */
2171 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2172 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002173 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002174 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002175 0, /* tp_iter */
2176 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002177 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002178 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002179 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002180 0, /* tp_base */
2181 0, /* tp_dict */
2182 0, /* tp_descr_get */
2183 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002184 offsetof(rwpair, dict), /* tp_dictoffset */
2185 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002186 0, /* tp_alloc */
2187 PyType_GenericNew, /* tp_new */
2188};
2189
2190
2191
2192/*
2193 * BufferedRandom
2194 */
2195
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002196PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002197 "A buffered interface to random access streams.\n"
2198 "\n"
2199 "The constructor creates a reader and writer for a seekable stream,\n"
2200 "raw, given in the first argument. If the buffer_size is omitted it\n"
2201 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2202 );
2203
2204static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002205bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002206{
2207 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2208 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002209 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002210 PyObject *raw;
2211
2212 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002213 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002214
2215 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2216 &raw, &buffer_size, &max_buffer_size)) {
2217 return -1;
2218 }
2219
Benjamin Peterson59406a92009-03-26 17:10:29 +00002220 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2221 return -1;
2222
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002223 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002224 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002225 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002226 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002227 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002228 return -1;
2229
2230 Py_CLEAR(self->raw);
2231 Py_INCREF(raw);
2232 self->raw = raw;
2233 self->buffer_size = buffer_size;
2234 self->readable = 1;
2235 self->writable = 1;
2236
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002237 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002238 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002239 _bufferedreader_reset_buf(self);
2240 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002241 self->pos = 0;
2242
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002243 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2244 Py_TYPE(raw) == &PyFileIO_Type);
2245
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002246 self->ok = 1;
2247 return 0;
2248}
2249
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002250static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002251 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002252 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2253 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2254 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2255 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2256 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2257 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2258 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002259 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002260
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002261 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002262
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002263 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2264 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2265 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2266 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2267 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2268 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2269 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2270 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2271 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002272 {NULL, NULL}
2273};
2274
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002275static PyMemberDef bufferedrandom_members[] = {
2276 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002277 {NULL}
2278};
2279
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002280static PyGetSetDef bufferedrandom_getset[] = {
2281 {"closed", (getter)buffered_closed_get, NULL, NULL},
2282 {"name", (getter)buffered_name_get, NULL, NULL},
2283 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002284 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002285};
2286
2287
2288PyTypeObject PyBufferedRandom_Type = {
2289 PyVarObject_HEAD_INIT(NULL, 0)
2290 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002291 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002292 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002293 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002294 0, /*tp_print*/
2295 0, /*tp_getattr*/
2296 0, /*tp_setattr*/
2297 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002298 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002299 0, /*tp_as_number*/
2300 0, /*tp_as_sequence*/
2301 0, /*tp_as_mapping*/
2302 0, /*tp_hash */
2303 0, /*tp_call*/
2304 0, /*tp_str*/
2305 0, /*tp_getattro*/
2306 0, /*tp_setattro*/
2307 0, /*tp_as_buffer*/
2308 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2309 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002310 bufferedrandom_doc, /* tp_doc */
2311 (traverseproc)buffered_traverse, /* tp_traverse */
2312 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002313 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002314 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002315 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002316 (iternextfunc)buffered_iternext, /* tp_iternext */
2317 bufferedrandom_methods, /* tp_methods */
2318 bufferedrandom_members, /* tp_members */
2319 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002320 0, /* tp_base */
2321 0, /*tp_dict*/
2322 0, /* tp_descr_get */
2323 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002324 offsetof(buffered, dict), /*tp_dictoffset*/
2325 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002326 0, /* tp_alloc */
2327 PyType_GenericNew, /* tp_new */
2328};