blob: 611dc8ce6d5f478c7d61189a4dcfd619da310a68 [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 Pitrou711af3a2009-04-11 15:39:24 +0000200
201 /* True if this is a vanilla Buffered object (rather than a user derived
202 class) *and* the raw stream is a vanilla FileIO object. */
203 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000204
205 /* Absolute position inside the raw stream (-1 if unknown). */
206 Py_off_t abs_pos;
207
208 /* A static buffer of size `buffer_size` */
209 char *buffer;
210 /* Current logical position in the buffer. */
211 Py_off_t pos;
212 /* Position of the raw stream in the buffer. */
213 Py_off_t raw_pos;
214
215 /* Just after the last buffered byte in the buffer, or -1 if the buffer
216 isn't ready for reading. */
217 Py_off_t read_end;
218
219 /* Just after the last byte actually written */
220 Py_off_t write_pos;
221 /* Just after the last byte waiting to be written, or -1 if the buffer
222 isn't ready for writing. */
223 Py_off_t write_end;
224
Georg Brandldfd73442009-04-05 11:47:34 +0000225#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000226 PyThread_type_lock lock;
Georg Brandldfd73442009-04-05 11:47:34 +0000227#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000228
229 Py_ssize_t buffer_size;
230 Py_ssize_t buffer_mask;
231
232 PyObject *dict;
233 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000234} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000235
236/*
237 Implementation notes:
238
239 * BufferedReader, BufferedWriter and BufferedRandom try to share most
240 methods (this is helped by the members `readable` and `writable`, which
241 are initialized in the respective constructors)
242 * They also share a single buffer for reading and writing. This enables
243 interleaved reads and writes without flushing. It also makes the logic
244 a bit trickier to get right.
245 * The absolute position of the raw stream is cached, if possible, in the
246 `abs_pos` member. It must be updated every time an operation is done
247 on the raw stream. If not sure, it can be reinitialized by calling
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000248 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000249 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000250 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
251 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000252
253 NOTE: we should try to maintain block alignment of reads and writes to the
254 raw stream (according to the buffer size), but for now it is only done
255 in read() and friends.
256
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000257*/
258
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000259/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000260
Georg Brandldfd73442009-04-05 11:47:34 +0000261#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000262#define ENTER_BUFFERED(self) \
263 Py_BEGIN_ALLOW_THREADS \
264 PyThread_acquire_lock(self->lock, 1); \
265 Py_END_ALLOW_THREADS
266
267#define LEAVE_BUFFERED(self) \
268 PyThread_release_lock(self->lock);
Georg Brandldfd73442009-04-05 11:47:34 +0000269#else
270#define ENTER_BUFFERED(self)
271#define LEAVE_BUFFERED(self)
272#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000273
274#define CHECK_INITIALIZED(self) \
275 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000276 if (self->detached) { \
277 PyErr_SetString(PyExc_ValueError, \
278 "raw stream has been detached"); \
279 } else { \
280 PyErr_SetString(PyExc_ValueError, \
281 "I/O operation on uninitialized object"); \
282 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000283 return NULL; \
284 }
285
286#define CHECK_INITIALIZED_INT(self) \
287 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000288 if (self->detached) { \
289 PyErr_SetString(PyExc_ValueError, \
290 "raw stream has been detached"); \
291 } else { \
292 PyErr_SetString(PyExc_ValueError, \
293 "I/O operation on uninitialized object"); \
294 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000295 return -1; \
296 }
297
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000298#define IS_CLOSED(self) \
299 (self->fast_closed_checks \
300 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000301 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000302
303#define CHECK_CLOSED(self, error_msg) \
304 if (IS_CLOSED(self)) { \
305 PyErr_SetString(PyExc_ValueError, error_msg); \
306 return NULL; \
307 }
308
309
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000310#define VALID_READ_BUFFER(self) \
311 (self->readable && self->read_end != -1)
312
313#define VALID_WRITE_BUFFER(self) \
314 (self->writable && self->write_end != -1)
315
316#define ADJUST_POSITION(self, _new_pos) \
317 do { \
318 self->pos = _new_pos; \
319 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
320 self->read_end = self->pos; \
321 } while(0)
322
323#define READAHEAD(self) \
324 ((self->readable && VALID_READ_BUFFER(self)) \
325 ? (self->read_end - self->pos) : 0)
326
327#define RAW_OFFSET(self) \
328 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
329 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
330
331#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000332 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000333
334#define MINUS_LAST_BLOCK(self, size) \
335 (self->buffer_mask ? \
336 (size & ~self->buffer_mask) : \
337 (self->buffer_size * (size / self->buffer_size)))
338
339
340static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000341buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000342{
343 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
344 return;
345 _PyObject_GC_UNTRACK(self);
346 self->ok = 0;
347 if (self->weakreflist != NULL)
348 PyObject_ClearWeakRefs((PyObject *)self);
349 Py_CLEAR(self->raw);
350 if (self->buffer) {
351 PyMem_Free(self->buffer);
352 self->buffer = NULL;
353 }
Georg Brandldfd73442009-04-05 11:47:34 +0000354#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000355 if (self->lock) {
356 PyThread_free_lock(self->lock);
357 self->lock = NULL;
358 }
Georg Brandldfd73442009-04-05 11:47:34 +0000359#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000360 Py_CLEAR(self->dict);
361 Py_TYPE(self)->tp_free((PyObject *)self);
362}
363
364static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000365buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000366{
367 Py_VISIT(self->raw);
368 Py_VISIT(self->dict);
369 return 0;
370}
371
372static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000373buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000374{
375 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
376 return -1;
377 self->ok = 0;
378 Py_CLEAR(self->raw);
379 Py_CLEAR(self->dict);
380 return 0;
381}
382
383/*
384 * _BufferedIOMixin methods
385 * This is not a class, just a collection of methods that will be reused
386 * by BufferedReader and BufferedWriter
387 */
388
389/* Flush and close */
390
391static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000392buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000393{
394 CHECK_INITIALIZED(self)
395 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
396}
397
398static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000399buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000400{
401 int closed;
402 PyObject *res;
403 CHECK_INITIALIZED_INT(self)
404 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
405 if (res == NULL)
406 return -1;
407 closed = PyObject_IsTrue(res);
408 Py_DECREF(res);
409 return closed;
410}
411
412static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000413buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000414{
415 CHECK_INITIALIZED(self)
416 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
417}
418
419static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000420buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000421{
422 PyObject *res = NULL;
423 int r;
424
425 CHECK_INITIALIZED(self)
426 ENTER_BUFFERED(self)
427
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000428 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000429 if (r < 0)
430 goto end;
431 if (r > 0) {
432 res = Py_None;
433 Py_INCREF(res);
434 goto end;
435 }
436 /* flush() will most probably re-take the lock, so drop it first */
437 LEAVE_BUFFERED(self)
438 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
439 ENTER_BUFFERED(self)
440 if (res == NULL) {
Antoine Pitroufaf90072010-05-03 16:58:19 +0000441 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000442 }
443 Py_XDECREF(res);
444
445 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
446
447end:
448 LEAVE_BUFFERED(self)
449 return res;
450}
451
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000452/* detach */
453
454static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000455buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000456{
457 PyObject *raw, *res;
458 CHECK_INITIALIZED(self)
459 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
460 if (res == NULL)
461 return NULL;
462 Py_DECREF(res);
463 raw = self->raw;
464 self->raw = NULL;
465 self->detached = 1;
466 self->ok = 0;
467 return raw;
468}
469
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000470/* Inquiries */
471
472static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000473buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000474{
475 CHECK_INITIALIZED(self)
476 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
477}
478
479static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000480buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000481{
482 CHECK_INITIALIZED(self)
483 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
484}
485
486static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000487buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000488{
489 CHECK_INITIALIZED(self)
490 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
491}
492
493static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000494buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000495{
496 CHECK_INITIALIZED(self)
497 return PyObject_GetAttrString(self->raw, "name");
498}
499
500static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000501buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000502{
503 CHECK_INITIALIZED(self)
504 return PyObject_GetAttrString(self->raw, "mode");
505}
506
507/* Lower-level APIs */
508
509static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000510buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000511{
512 CHECK_INITIALIZED(self)
513 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
514}
515
516static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000517buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000518{
519 CHECK_INITIALIZED(self)
520 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
521}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000522
523
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000524/* Forward decls */
525static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000526_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000527static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000528_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000529static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000530_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000531static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000532_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000533static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000534_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000535static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000536_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000537static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000538_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000539static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000540_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000541
542
543/*
544 * Helpers
545 */
546
547/* Returns the address of the `written` member if a BlockingIOError was
548 raised, NULL otherwise. The error is always re-raised. */
549static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000550_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000551{
552 PyObject *t, *v, *tb;
553 PyBlockingIOErrorObject *err;
554
555 PyErr_Fetch(&t, &v, &tb);
556 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
557 PyErr_Restore(t, v, tb);
558 return NULL;
559 }
560 err = (PyBlockingIOErrorObject *) v;
561 /* TODO: sanity check (err->written >= 0) */
562 PyErr_Restore(t, v, tb);
563 return &err->written;
564}
565
566static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000567_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000568{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000569 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000570 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000571 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
572 if (res == NULL)
573 return -1;
574 n = PyNumber_AsOff_t(res, PyExc_ValueError);
575 Py_DECREF(res);
576 if (n < 0) {
577 if (!PyErr_Occurred())
578 PyErr_Format(PyExc_IOError,
Mark Dickinson00de1bd2009-10-29 10:01:23 +0000579 "Raw stream returned invalid position %zd", n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000580 return -1;
581 }
582 self->abs_pos = n;
583 return n;
584}
585
586static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000587_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000588{
589 PyObject *res, *posobj, *whenceobj;
590 Py_off_t n;
591
592 posobj = PyLong_FromOff_t(target);
593 if (posobj == NULL)
594 return -1;
595 whenceobj = PyLong_FromLong(whence);
596 if (whenceobj == NULL) {
597 Py_DECREF(posobj);
598 return -1;
599 }
600 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
601 posobj, whenceobj, NULL);
602 Py_DECREF(posobj);
603 Py_DECREF(whenceobj);
604 if (res == NULL)
605 return -1;
606 n = PyNumber_AsOff_t(res, PyExc_ValueError);
607 Py_DECREF(res);
608 if (n < 0) {
609 if (!PyErr_Occurred())
610 PyErr_Format(PyExc_IOError,
Mark Dickinson00de1bd2009-10-29 10:01:23 +0000611 "Raw stream returned invalid position %zd", n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000612 return -1;
613 }
614 self->abs_pos = n;
615 return n;
616}
617
618static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000619_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000620{
621 Py_ssize_t n;
622 if (self->buffer_size <= 0) {
623 PyErr_SetString(PyExc_ValueError,
624 "buffer size must be strictly positive");
625 return -1;
626 }
627 if (self->buffer)
628 PyMem_Free(self->buffer);
629 self->buffer = PyMem_Malloc(self->buffer_size);
630 if (self->buffer == NULL) {
631 PyErr_NoMemory();
632 return -1;
633 }
Georg Brandldfd73442009-04-05 11:47:34 +0000634#ifdef WITH_THREAD
Antoine Pitrouf6df1ee2010-08-01 16:57:42 +0000635 if (self->lock)
636 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000637 self->lock = PyThread_allocate_lock();
638 if (self->lock == NULL) {
639 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
640 return -1;
641 }
Georg Brandldfd73442009-04-05 11:47:34 +0000642#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000643 /* Find out whether buffer_size is a power of 2 */
644 /* XXX is this optimization useful? */
645 for (n = self->buffer_size - 1; n & 1; n >>= 1)
646 ;
647 if (n == 0)
648 self->buffer_mask = self->buffer_size - 1;
649 else
650 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000651 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000652 PyErr_Clear();
653 return 0;
654}
655
656/*
657 * Shared methods and wrappers
658 */
659
660static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000661buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000662{
663 PyObject *res;
664
665 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000666 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000667
668 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000669 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000670 if (res != NULL && self->readable) {
671 /* Rewind the raw stream so that its position corresponds to
672 the current logical position. */
673 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000674 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000675 if (n == -1)
676 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000677 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000678 }
679 LEAVE_BUFFERED(self)
680
681 return res;
682}
683
684static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000685buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000686{
687 Py_ssize_t n = 0;
688 PyObject *res = NULL;
689
690 CHECK_INITIALIZED(self)
691 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
692 return NULL;
693 }
694
695 ENTER_BUFFERED(self)
696
697 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000698 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000699 if (res == NULL)
700 goto end;
701 Py_CLEAR(res);
702 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000703 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000704
705end:
706 LEAVE_BUFFERED(self)
707 return res;
708}
709
710static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000711buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000712{
713 Py_ssize_t n = -1;
714 PyObject *res;
715
716 CHECK_INITIALIZED(self)
Benjamin Peterson6b59f772009-12-13 19:30:15 +0000717 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000718 return NULL;
719 }
720 if (n < -1) {
721 PyErr_SetString(PyExc_ValueError,
722 "read length must be positive or -1");
723 return NULL;
724 }
725
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000726 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000727
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000728 if (n == -1) {
729 /* The number of bytes is unspecified, read until the end of stream */
730 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000731 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000732 LEAVE_BUFFERED(self)
733 }
734 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000735 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000736 if (res == Py_None) {
737 Py_DECREF(res);
738 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000739 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000740 LEAVE_BUFFERED(self)
741 }
742 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000743
744 return res;
745}
746
747static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000748buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000749{
750 Py_ssize_t n, have, r;
751 PyObject *res = NULL;
752
753 CHECK_INITIALIZED(self)
754 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
755 return NULL;
756 }
757
758 if (n < 0) {
759 PyErr_SetString(PyExc_ValueError,
760 "read length must be positive");
761 return NULL;
762 }
763 if (n == 0)
764 return PyBytes_FromStringAndSize(NULL, 0);
765
766 ENTER_BUFFERED(self)
767
768 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000769 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000770 if (res == NULL)
771 goto end;
772 Py_CLEAR(res);
773 }
774
775 /* Return up to n bytes. If at least one byte is buffered, we
776 only return buffered bytes. Otherwise, we do one raw read. */
777
778 /* XXX: this mimicks the io.py implementation but is probably wrong.
779 If we need to read from the raw stream, then we could actually read
780 all `n` bytes asked by the caller (and possibly more, so as to fill
781 our buffer for the next reads). */
782
783 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
784 if (have > 0) {
785 if (n > have)
786 n = have;
787 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
788 if (res == NULL)
789 goto end;
790 self->pos += n;
791 goto end;
792 }
793
794 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000795 _bufferedreader_reset_buf(self);
796 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000797 if (r == -1)
798 goto end;
799 if (r == -2)
800 r = 0;
801 if (n > r)
802 n = r;
803 res = PyBytes_FromStringAndSize(self->buffer, n);
804 if (res == NULL)
805 goto end;
806 self->pos = n;
807
808end:
809 LEAVE_BUFFERED(self)
810 return res;
811}
812
813static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000814buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000815{
816 PyObject *res = NULL;
817
818 CHECK_INITIALIZED(self)
819
820 /* TODO: use raw.readinto() instead! */
821 if (self->writable) {
822 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000823 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000824 LEAVE_BUFFERED(self)
825 if (res == NULL)
826 goto end;
827 Py_DECREF(res);
828 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000829 res = bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000830
831end:
832 return res;
833}
834
835static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000836_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000837{
838 PyObject *res = NULL;
839 PyObject *chunks = NULL;
840 Py_ssize_t n, written = 0;
841 const char *start, *s, *end;
842
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000843 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000844
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000845 /* First, try to find a line in the buffer. This can run unlocked because
846 the calls to the C API are simple enough that they can't trigger
847 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000848 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
849 if (limit >= 0 && n > limit)
850 n = limit;
851 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000852 s = memchr(start, '\n', n);
853 if (s != NULL) {
854 res = PyBytes_FromStringAndSize(start, s - start + 1);
855 if (res != NULL)
856 self->pos += s - start + 1;
857 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000858 }
859 if (n == limit) {
860 res = PyBytes_FromStringAndSize(start, n);
861 if (res != NULL)
862 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000863 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000864 }
865
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000866 ENTER_BUFFERED(self)
867
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000868 /* Now we try to get some more from the raw stream */
869 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000870 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000871 if (res == NULL)
872 goto end;
873 Py_CLEAR(res);
874 }
875 chunks = PyList_New(0);
876 if (chunks == NULL)
877 goto end;
878 if (n > 0) {
879 res = PyBytes_FromStringAndSize(start, n);
880 if (res == NULL)
881 goto end;
882 if (PyList_Append(chunks, res) < 0) {
883 Py_CLEAR(res);
884 goto end;
885 }
886 Py_CLEAR(res);
887 written += n;
888 if (limit >= 0)
889 limit -= n;
890 }
891
892 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000893 _bufferedreader_reset_buf(self);
894 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000895 if (n == -1)
896 goto end;
897 if (n <= 0)
898 break;
899 if (limit >= 0 && n > limit)
900 n = limit;
901 start = self->buffer;
902 end = start + n;
903 s = start;
904 while (s < end) {
905 if (*s++ == '\n') {
906 res = PyBytes_FromStringAndSize(start, s - start);
907 if (res == NULL)
908 goto end;
909 self->pos = s - start;
910 goto found;
911 }
912 }
913 res = PyBytes_FromStringAndSize(start, n);
914 if (res == NULL)
915 goto end;
916 if (n == limit) {
917 self->pos = n;
918 break;
919 }
920 if (PyList_Append(chunks, res) < 0) {
921 Py_CLEAR(res);
922 goto end;
923 }
924 Py_CLEAR(res);
925 written += n;
926 if (limit >= 0)
927 limit -= n;
928 }
929found:
930 if (res != NULL && PyList_Append(chunks, res) < 0) {
931 Py_CLEAR(res);
932 goto end;
933 }
934 Py_CLEAR(res);
935 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
936
937end:
938 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000939end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000940 Py_XDECREF(chunks);
941 return res;
942}
943
944static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000945buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000946{
947 Py_ssize_t limit = -1;
948
949 CHECK_INITIALIZED(self)
Benjamin Peterson6b59f772009-12-13 19:30:15 +0000950 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000951 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000952 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000953}
954
955
956static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000957buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000958{
959 Py_off_t pos;
960
961 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000962 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000963 if (pos == -1)
964 return NULL;
965 pos -= RAW_OFFSET(self);
966 /* TODO: sanity check (pos >= 0) */
967 return PyLong_FromOff_t(pos);
968}
969
970static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000971buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000972{
973 Py_off_t target, n;
974 int whence = 0;
975 PyObject *targetobj, *res = NULL;
976
977 CHECK_INITIALIZED(self)
978 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
979 return NULL;
980 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000981 if (whence < 0 || whence > 2) {
982 PyErr_Format(PyExc_ValueError,
983 "whence must be between 0 and 2, not %d", whence);
984 return NULL;
985 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000986
987 CHECK_CLOSED(self, "seek of closed file")
988
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000989 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
990 if (target == -1 && PyErr_Occurred())
991 return NULL;
992
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000993 if (whence != 2 && self->readable) {
994 Py_off_t current, avail;
995 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000996 so as to return quickly if possible. Also, we needn't take the
997 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000998 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000999 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1000 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001001 current = RAW_TELL(self);
1002 avail = READAHEAD(self);
1003 if (avail > 0) {
1004 Py_off_t offset;
1005 if (whence == 0)
1006 offset = target - (current - RAW_OFFSET(self));
1007 else
1008 offset = target;
1009 if (offset >= -self->pos && offset <= avail) {
1010 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001011 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001012 }
1013 }
1014 }
1015
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001016 ENTER_BUFFERED(self)
1017
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001018 /* Fallback: invoke raw seek() method and clear buffer */
1019 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001020 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001021 if (res == NULL)
1022 goto end;
1023 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001024 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001025 }
1026
1027 /* TODO: align on block boundary and read buffer if needed? */
1028 if (whence == 1)
1029 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001030 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001031 if (n == -1)
1032 goto end;
1033 self->raw_pos = -1;
1034 res = PyLong_FromOff_t(n);
1035 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001036 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001037
1038end:
1039 LEAVE_BUFFERED(self)
1040 return res;
1041}
1042
1043static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001044buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001045{
1046 PyObject *pos = Py_None;
1047 PyObject *res = NULL;
1048
1049 CHECK_INITIALIZED(self)
1050 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1051 return NULL;
1052 }
1053
1054 ENTER_BUFFERED(self)
1055
1056 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001057 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001058 if (res == NULL)
1059 goto end;
1060 Py_CLEAR(res);
1061 }
1062 if (self->readable) {
1063 if (pos == Py_None) {
1064 /* Rewind the raw stream so that its position corresponds to
1065 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001066 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001067 goto end;
1068 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001069 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001070 }
1071 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1072 if (res == NULL)
1073 goto end;
1074 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001075 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001076 PyErr_Clear();
1077
1078end:
1079 LEAVE_BUFFERED(self)
1080 return res;
1081}
1082
1083static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001084buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001085{
1086 PyObject *line;
1087 PyTypeObject *tp;
1088
1089 CHECK_INITIALIZED(self);
1090
1091 tp = Py_TYPE(self);
1092 if (tp == &PyBufferedReader_Type ||
1093 tp == &PyBufferedRandom_Type) {
1094 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001095 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001096 }
1097 else {
1098 line = PyObject_CallMethodObjArgs((PyObject *)self,
1099 _PyIO_str_readline, NULL);
1100 if (line && !PyBytes_Check(line)) {
1101 PyErr_Format(PyExc_IOError,
1102 "readline() should have returned a bytes object, "
1103 "not '%.200s'", Py_TYPE(line)->tp_name);
1104 Py_DECREF(line);
1105 return NULL;
1106 }
1107 }
1108
1109 if (line == NULL)
1110 return NULL;
1111
1112 if (PyBytes_GET_SIZE(line) == 0) {
1113 /* Reached EOF or would have blocked */
1114 Py_DECREF(line);
1115 return NULL;
1116 }
1117
1118 return line;
1119}
1120
Antoine Pitrou716c4442009-05-23 19:04:03 +00001121static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001122buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001123{
1124 PyObject *nameobj, *res;
1125
1126 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1127 if (nameobj == NULL) {
1128 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1129 PyErr_Clear();
1130 else
1131 return NULL;
1132 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1133 }
1134 else {
1135 res = PyUnicode_FromFormat("<%s name=%R>",
1136 Py_TYPE(self)->tp_name, nameobj);
1137 Py_DECREF(nameobj);
1138 }
1139 return res;
1140}
1141
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001142/*
1143 * class BufferedReader
1144 */
1145
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001146PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001147 "Create a new buffered reader using the given readable raw IO object.");
1148
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001149static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001150{
1151 self->read_end = -1;
1152}
1153
1154static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001155bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001156{
1157 char *kwlist[] = {"raw", "buffer_size", NULL};
1158 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1159 PyObject *raw;
1160
1161 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001162 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001163
1164 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1165 &raw, &buffer_size)) {
1166 return -1;
1167 }
1168
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001169 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001170 return -1;
1171
1172 Py_CLEAR(self->raw);
1173 Py_INCREF(raw);
1174 self->raw = raw;
1175 self->buffer_size = buffer_size;
1176 self->readable = 1;
1177 self->writable = 0;
1178
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001179 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001180 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001181 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001182
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001183 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1184 Py_TYPE(raw) == &PyFileIO_Type);
1185
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001186 self->ok = 1;
1187 return 0;
1188}
1189
1190static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001191_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001192{
1193 Py_buffer buf;
1194 PyObject *memobj, *res;
1195 Py_ssize_t n;
1196 /* NOTE: the buffer needn't be released as its object is NULL. */
1197 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1198 return -1;
1199 memobj = PyMemoryView_FromBuffer(&buf);
1200 if (memobj == NULL)
1201 return -1;
1202 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1203 Py_DECREF(memobj);
1204 if (res == NULL)
1205 return -1;
1206 if (res == Py_None) {
1207 /* Non-blocking stream would have blocked. Special return code! */
1208 Py_DECREF(res);
1209 return -2;
1210 }
1211 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1212 Py_DECREF(res);
1213 if (n < 0 || n > len) {
1214 PyErr_Format(PyExc_IOError,
1215 "raw readinto() returned invalid length %zd "
1216 "(should have been between 0 and %zd)", n, len);
1217 return -1;
1218 }
1219 if (n > 0 && self->abs_pos != -1)
1220 self->abs_pos += n;
1221 return n;
1222}
1223
1224static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001225_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001226{
1227 Py_ssize_t start, len, n;
1228 if (VALID_READ_BUFFER(self))
1229 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1230 else
1231 start = 0;
1232 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001233 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001234 if (n <= 0)
1235 return n;
1236 self->read_end = start + n;
1237 self->raw_pos = start + n;
1238 return n;
1239}
1240
1241static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001242_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001243{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001244 Py_ssize_t current_size;
1245 PyObject *res, *data = NULL;
1246 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001247
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001248 if (chunks == NULL)
1249 return NULL;
1250
1251 /* First copy what we have in the current buffer. */
1252 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1253 if (current_size) {
1254 data = PyBytes_FromStringAndSize(
1255 self->buffer + self->pos, current_size);
1256 if (data == NULL) {
1257 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001258 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001259 }
1260 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001261 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001262 /* We're going past the buffer's bounds, flush it */
1263 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001264 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001265 if (res == NULL) {
1266 Py_DECREF(chunks);
1267 return NULL;
1268 }
1269 Py_CLEAR(res);
1270 }
1271 while (1) {
1272 if (data) {
1273 if (PyList_Append(chunks, data) < 0) {
1274 Py_DECREF(data);
1275 Py_DECREF(chunks);
1276 return NULL;
1277 }
1278 Py_DECREF(data);
1279 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001280
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001281 /* Read until EOF or until read() would block. */
1282 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1283 if (data == NULL) {
1284 Py_DECREF(chunks);
1285 return NULL;
1286 }
1287 if (data != Py_None && !PyBytes_Check(data)) {
1288 Py_DECREF(data);
1289 Py_DECREF(chunks);
1290 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1291 return NULL;
1292 }
1293 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1294 if (current_size == 0) {
1295 Py_DECREF(chunks);
1296 return data;
1297 }
1298 else {
1299 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1300 Py_DECREF(data);
1301 Py_DECREF(chunks);
1302 return res;
1303 }
1304 }
1305 current_size += PyBytes_GET_SIZE(data);
1306 if (self->abs_pos != -1)
1307 self->abs_pos += PyBytes_GET_SIZE(data);
1308 }
1309}
1310
1311/* Read n bytes from the buffer if it can, otherwise return None.
1312 This function is simple enough that it can run unlocked. */
1313static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001314_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001315{
1316 Py_ssize_t current_size;
1317
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001318 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1319 if (n <= current_size) {
1320 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001321 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1322 if (res != NULL)
1323 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001324 return res;
1325 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001326 Py_RETURN_NONE;
1327}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001328
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001329/* Generic read function: read from the stream until enough bytes are read,
1330 * or until an EOF occurs or until read() would block.
1331 */
1332static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001333_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001334{
1335 PyObject *res = NULL;
1336 Py_ssize_t current_size, remaining, written;
1337 char *out;
1338
1339 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1340 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001341 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001342
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001343 res = PyBytes_FromStringAndSize(NULL, n);
1344 if (res == NULL)
1345 goto error;
1346 out = PyBytes_AS_STRING(res);
1347 remaining = n;
1348 written = 0;
1349 if (current_size > 0) {
1350 memcpy(out, self->buffer + self->pos, current_size);
1351 remaining -= current_size;
1352 written += current_size;
1353 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001354 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001355 while (remaining > 0) {
1356 /* We want to read a whole block at the end into buffer.
1357 If we had readv() we could do this in one pass. */
1358 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1359 if (r == 0)
1360 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001361 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001362 if (r == -1)
1363 goto error;
1364 if (r == 0 || r == -2) {
1365 /* EOF occurred or read() would block. */
1366 if (r == 0 || written > 0) {
1367 if (_PyBytes_Resize(&res, written))
1368 goto error;
1369 return res;
1370 }
1371 Py_DECREF(res);
1372 Py_INCREF(Py_None);
1373 return Py_None;
1374 }
1375 remaining -= r;
1376 written += r;
1377 }
1378 assert(remaining <= self->buffer_size);
1379 self->pos = 0;
1380 self->raw_pos = 0;
1381 self->read_end = 0;
Antoine Pitrou00091ca2010-08-11 13:38:10 +00001382 /* NOTE: when the read is satisfied, we avoid issuing any additional
1383 reads, which could block indefinitely (e.g. on a socket).
1384 See issue #9550. */
1385 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001386 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001387 if (r == -1)
1388 goto error;
1389 if (r == 0 || r == -2) {
1390 /* EOF occurred or read() would block. */
1391 if (r == 0 || written > 0) {
1392 if (_PyBytes_Resize(&res, written))
1393 goto error;
1394 return res;
1395 }
1396 Py_DECREF(res);
1397 Py_INCREF(Py_None);
1398 return Py_None;
1399 }
1400 if (remaining > r) {
1401 memcpy(out + written, self->buffer + self->pos, r);
1402 written += r;
1403 self->pos += r;
1404 remaining -= r;
1405 }
1406 else if (remaining > 0) {
1407 memcpy(out + written, self->buffer + self->pos, remaining);
1408 written += remaining;
1409 self->pos += remaining;
1410 remaining = 0;
1411 }
1412 if (remaining == 0)
1413 break;
1414 }
1415
1416 return res;
1417
1418error:
1419 Py_XDECREF(res);
1420 return NULL;
1421}
1422
1423static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001424_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001425{
1426 Py_ssize_t have, r;
1427
1428 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1429 /* Constraints:
1430 1. we don't want to advance the file position.
1431 2. we don't want to lose block alignment, so we can't shift the buffer
1432 to make some place.
1433 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1434 */
1435 if (have > 0) {
1436 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1437 }
1438
1439 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001440 _bufferedreader_reset_buf(self);
1441 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001442 if (r == -1)
1443 return NULL;
1444 if (r == -2)
1445 r = 0;
1446 self->pos = 0;
1447 return PyBytes_FromStringAndSize(self->buffer, r);
1448}
1449
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001450static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001451 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001452 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1453 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1454 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1455 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1456 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1457 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1458 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1459 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001460
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001461 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1462 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1463 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1464 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1465 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1466 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1467 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001468 {NULL, NULL}
1469};
1470
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001471static PyMemberDef bufferedreader_members[] = {
1472 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001473 {NULL}
1474};
1475
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001476static PyGetSetDef bufferedreader_getset[] = {
1477 {"closed", (getter)buffered_closed_get, NULL, NULL},
1478 {"name", (getter)buffered_name_get, NULL, NULL},
1479 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001480 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001481};
1482
1483
1484PyTypeObject PyBufferedReader_Type = {
1485 PyVarObject_HEAD_INIT(NULL, 0)
1486 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001487 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001488 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001489 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001490 0, /*tp_print*/
1491 0, /*tp_getattr*/
1492 0, /*tp_setattr*/
1493 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001494 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001495 0, /*tp_as_number*/
1496 0, /*tp_as_sequence*/
1497 0, /*tp_as_mapping*/
1498 0, /*tp_hash */
1499 0, /*tp_call*/
1500 0, /*tp_str*/
1501 0, /*tp_getattro*/
1502 0, /*tp_setattro*/
1503 0, /*tp_as_buffer*/
1504 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1505 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001506 bufferedreader_doc, /* tp_doc */
1507 (traverseproc)buffered_traverse, /* tp_traverse */
1508 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001509 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001510 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001511 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001512 (iternextfunc)buffered_iternext, /* tp_iternext */
1513 bufferedreader_methods, /* tp_methods */
1514 bufferedreader_members, /* tp_members */
1515 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001516 0, /* tp_base */
1517 0, /* tp_dict */
1518 0, /* tp_descr_get */
1519 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001520 offsetof(buffered, dict), /* tp_dictoffset */
1521 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001522 0, /* tp_alloc */
1523 PyType_GenericNew, /* tp_new */
1524};
1525
1526
Benjamin Peterson59406a92009-03-26 17:10:29 +00001527
1528static int
1529complain_about_max_buffer_size(void)
1530{
1531 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1532 "max_buffer_size is deprecated", 1) < 0)
1533 return 0;
1534 return 1;
1535}
1536
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001537/*
1538 * class BufferedWriter
1539 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001540PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001541 "A buffer for a writeable sequential RawIO object.\n"
1542 "\n"
1543 "The constructor creates a BufferedWriter for the given writeable raw\n"
1544 "stream. If the buffer_size is not given, it defaults to\n"
1545 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1546 );
1547
1548static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001549_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001550{
1551 self->write_pos = 0;
1552 self->write_end = -1;
1553}
1554
1555static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001556bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001557{
1558 /* TODO: properly deprecate max_buffer_size */
1559 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1560 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001561 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001562 PyObject *raw;
1563
1564 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001565 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001566
1567 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1568 &raw, &buffer_size, &max_buffer_size)) {
1569 return -1;
1570 }
1571
Benjamin Peterson59406a92009-03-26 17:10:29 +00001572 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1573 return -1;
1574
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001575 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001576 return -1;
1577
1578 Py_CLEAR(self->raw);
1579 Py_INCREF(raw);
1580 self->raw = raw;
1581 self->readable = 0;
1582 self->writable = 1;
1583
1584 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001585 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001586 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001587 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001588 self->pos = 0;
1589
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001590 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1591 Py_TYPE(raw) == &PyFileIO_Type);
1592
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001593 self->ok = 1;
1594 return 0;
1595}
1596
1597static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001598_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001599{
1600 Py_buffer buf;
1601 PyObject *memobj, *res;
1602 Py_ssize_t n;
1603 /* NOTE: the buffer needn't be released as its object is NULL. */
1604 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1605 return -1;
1606 memobj = PyMemoryView_FromBuffer(&buf);
1607 if (memobj == NULL)
1608 return -1;
1609 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1610 Py_DECREF(memobj);
1611 if (res == NULL)
1612 return -1;
1613 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1614 Py_DECREF(res);
1615 if (n < 0 || n > len) {
1616 PyErr_Format(PyExc_IOError,
1617 "raw write() returned invalid length %zd "
1618 "(should have been between 0 and %zd)", n, len);
1619 return -1;
1620 }
1621 if (n > 0 && self->abs_pos != -1)
1622 self->abs_pos += n;
1623 return n;
1624}
1625
1626/* `restore_pos` is 1 if we need to restore the raw stream position at
1627 the end, 0 otherwise. */
1628static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001629_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001630{
1631 Py_ssize_t written = 0;
1632 Py_off_t n, rewind;
1633
1634 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1635 goto end;
1636 /* First, rewind */
1637 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1638 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001639 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001640 if (n < 0) {
1641 goto error;
1642 }
1643 self->raw_pos -= rewind;
1644 }
1645 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001646 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001647 self->buffer + self->write_pos,
1648 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1649 Py_off_t, Py_ssize_t));
1650 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001651 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001652 if (w == NULL)
1653 goto error;
1654 self->write_pos += *w;
1655 self->raw_pos = self->write_pos;
1656 written += *w;
1657 *w = written;
1658 /* Already re-raised */
1659 goto error;
1660 }
1661 self->write_pos += n;
1662 self->raw_pos = self->write_pos;
1663 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitrou16b11de2010-08-21 19:17:57 +00001664 /* Partial writes can return successfully when interrupted by a
1665 signal (see write(2)). We must run signal handlers before
1666 blocking another time, possibly indefinitely. */
1667 if (PyErr_CheckSignals() < 0)
1668 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001669 }
1670
1671 if (restore_pos) {
1672 Py_off_t forward = rewind - written;
1673 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001674 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001675 if (n < 0) {
1676 goto error;
1677 }
1678 self->raw_pos += forward;
1679 }
1680 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001681 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001682
1683end:
1684 Py_RETURN_NONE;
1685
1686error:
1687 return NULL;
1688}
1689
1690static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001691bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001692{
1693 PyObject *res = NULL;
1694 Py_buffer buf;
1695 Py_ssize_t written, avail, remaining, n;
1696
1697 CHECK_INITIALIZED(self)
1698 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1699 return NULL;
1700 }
1701
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001702 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001703 PyErr_SetString(PyExc_ValueError, "write to closed file");
1704 PyBuffer_Release(&buf);
1705 return NULL;
1706 }
1707
1708 ENTER_BUFFERED(self)
1709
1710 /* Fast path: the data to write can be fully buffered. */
1711 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1712 self->pos = 0;
1713 self->raw_pos = 0;
1714 }
1715 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1716 if (buf.len <= avail) {
1717 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1718 if (!VALID_WRITE_BUFFER(self)) {
1719 self->write_pos = self->pos;
1720 }
1721 ADJUST_POSITION(self, self->pos + buf.len);
1722 if (self->pos > self->write_end)
1723 self->write_end = self->pos;
1724 written = buf.len;
1725 goto end;
1726 }
1727
1728 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001729 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001730 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001731 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001732 if (w == NULL)
1733 goto error;
1734 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001735 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001736 /* Make some place by shifting the buffer. */
1737 assert(VALID_WRITE_BUFFER(self));
1738 memmove(self->buffer, self->buffer + self->write_pos,
1739 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1740 Py_off_t, Py_ssize_t));
1741 self->write_end -= self->write_pos;
1742 self->raw_pos -= self->write_pos;
1743 self->pos -= self->write_pos;
1744 self->write_pos = 0;
1745 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1746 Py_off_t, Py_ssize_t);
1747 if (buf.len <= avail) {
1748 /* Everything can be buffered */
1749 PyErr_Clear();
1750 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1751 self->write_end += buf.len;
1752 written = buf.len;
1753 goto end;
1754 }
1755 /* Buffer as much as possible. */
1756 memcpy(self->buffer + self->write_end, buf.buf, avail);
1757 self->write_end += avail;
1758 /* Already re-raised */
1759 *w = avail;
1760 goto error;
1761 }
1762 Py_CLEAR(res);
1763
Antoine Pitrou0473e562009-08-06 20:52:43 +00001764 /* Adjust the raw stream position if it is away from the logical stream
1765 position. This happens if the read buffer has been filled but not
1766 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1767 the raw stream by itself).
1768 Fixes issue #6629.
1769 */
1770 n = RAW_OFFSET(self);
1771 if (n != 0) {
1772 if (_buffered_raw_seek(self, -n, 1) < 0)
1773 goto error;
1774 self->raw_pos -= n;
1775 }
1776
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001777 /* Then write buf itself. At this point the buffer has been emptied. */
1778 remaining = buf.len;
1779 written = 0;
1780 while (remaining > self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001781 n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001782 self, (char *) buf.buf + written, buf.len - written);
1783 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001784 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001785 if (w == NULL)
1786 goto error;
1787 written += *w;
1788 remaining -= *w;
1789 if (remaining > self->buffer_size) {
1790 /* Can't buffer everything, still buffer as much as possible */
1791 memcpy(self->buffer,
1792 (char *) buf.buf + written, self->buffer_size);
1793 self->raw_pos = 0;
1794 ADJUST_POSITION(self, self->buffer_size);
1795 self->write_end = self->buffer_size;
1796 *w = written + self->buffer_size;
1797 /* Already re-raised */
1798 goto error;
1799 }
1800 PyErr_Clear();
1801 break;
1802 }
1803 written += n;
1804 remaining -= n;
Antoine Pitrou16b11de2010-08-21 19:17:57 +00001805 /* Partial writes can return successfully when interrupted by a
1806 signal (see write(2)). We must run signal handlers before
1807 blocking another time, possibly indefinitely. */
1808 if (PyErr_CheckSignals() < 0)
1809 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001810 }
1811 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001812 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001813 if (remaining > 0) {
1814 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1815 written += remaining;
1816 }
1817 self->write_pos = 0;
1818 /* TODO: sanity check (remaining >= 0) */
1819 self->write_end = remaining;
1820 ADJUST_POSITION(self, remaining);
1821 self->raw_pos = 0;
1822
1823end:
1824 res = PyLong_FromSsize_t(written);
1825
1826error:
1827 LEAVE_BUFFERED(self)
1828 PyBuffer_Release(&buf);
1829 return res;
1830}
1831
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001832static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001833 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001834 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1835 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1836 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1837 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1838 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1839 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1840 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001841
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001842 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1843 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1844 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1845 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1846 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001847 {NULL, NULL}
1848};
1849
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001850static PyMemberDef bufferedwriter_members[] = {
1851 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001852 {NULL}
1853};
1854
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001855static PyGetSetDef bufferedwriter_getset[] = {
1856 {"closed", (getter)buffered_closed_get, NULL, NULL},
1857 {"name", (getter)buffered_name_get, NULL, NULL},
1858 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001859 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001860};
1861
1862
1863PyTypeObject PyBufferedWriter_Type = {
1864 PyVarObject_HEAD_INIT(NULL, 0)
1865 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001866 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001867 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001868 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001869 0, /*tp_print*/
1870 0, /*tp_getattr*/
1871 0, /*tp_setattr*/
1872 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001873 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001874 0, /*tp_as_number*/
1875 0, /*tp_as_sequence*/
1876 0, /*tp_as_mapping*/
1877 0, /*tp_hash */
1878 0, /*tp_call*/
1879 0, /*tp_str*/
1880 0, /*tp_getattro*/
1881 0, /*tp_setattro*/
1882 0, /*tp_as_buffer*/
1883 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1884 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001885 bufferedwriter_doc, /* tp_doc */
1886 (traverseproc)buffered_traverse, /* tp_traverse */
1887 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001888 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001889 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001890 0, /* tp_iter */
1891 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001892 bufferedwriter_methods, /* tp_methods */
1893 bufferedwriter_members, /* tp_members */
1894 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001895 0, /* tp_base */
1896 0, /* tp_dict */
1897 0, /* tp_descr_get */
1898 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001899 offsetof(buffered, dict), /* tp_dictoffset */
1900 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001901 0, /* tp_alloc */
1902 PyType_GenericNew, /* tp_new */
1903};
1904
1905
1906
1907/*
1908 * BufferedRWPair
1909 */
1910
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001911PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001912 "A buffered reader and writer object together.\n"
1913 "\n"
1914 "A buffered reader object and buffered writer object put together to\n"
1915 "form a sequential IO object that can read and write. This is typically\n"
1916 "used with a socket or two-way pipe.\n"
1917 "\n"
1918 "reader and writer are RawIOBase objects that are readable and\n"
1919 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001920 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001921 );
1922
1923/* XXX The usefulness of this (compared to having two separate IO objects) is
1924 * questionable.
1925 */
1926
1927typedef struct {
1928 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001929 buffered *reader;
1930 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001931 PyObject *dict;
1932 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001933} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001934
1935static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001936bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001937{
1938 PyObject *reader, *writer;
1939 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001940 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001941
1942 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1943 &buffer_size, &max_buffer_size)) {
1944 return -1;
1945 }
1946
Benjamin Peterson59406a92009-03-26 17:10:29 +00001947 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1948 return -1;
1949
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001950 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001951 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001952 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001953 return -1;
1954
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001955 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001956 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001957 if (self->reader == NULL)
1958 return -1;
1959
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001960 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001961 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001962 if (self->writer == NULL) {
1963 Py_CLEAR(self->reader);
1964 return -1;
1965 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001966
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001967 return 0;
1968}
1969
1970static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001971bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001972{
1973 Py_VISIT(self->dict);
1974 return 0;
1975}
1976
1977static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001978bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001979{
1980 Py_CLEAR(self->reader);
1981 Py_CLEAR(self->writer);
1982 Py_CLEAR(self->dict);
1983 return 0;
1984}
1985
1986static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001987bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001988{
1989 _PyObject_GC_UNTRACK(self);
1990 Py_CLEAR(self->reader);
1991 Py_CLEAR(self->writer);
1992 Py_CLEAR(self->dict);
1993 Py_TYPE(self)->tp_free((PyObject *) self);
1994}
1995
1996static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001997_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001998{
1999 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2000 PyObject *ret;
2001
2002 if (func == NULL) {
2003 PyErr_SetString(PyExc_AttributeError, name);
2004 return NULL;
2005 }
2006
2007 ret = PyObject_CallObject(func, args);
2008 Py_DECREF(func);
2009 return ret;
2010}
2011
2012static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002013bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002014{
2015 return _forward_call(self->reader, "read", args);
2016}
2017
2018static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002019bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002020{
2021 return _forward_call(self->reader, "peek", args);
2022}
2023
2024static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002025bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002026{
2027 return _forward_call(self->reader, "read1", args);
2028}
2029
2030static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002031bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002032{
2033 return _forward_call(self->reader, "readinto", args);
2034}
2035
2036static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002037bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002038{
2039 return _forward_call(self->writer, "write", args);
2040}
2041
2042static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002043bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002044{
2045 return _forward_call(self->writer, "flush", args);
2046}
2047
2048static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002049bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002050{
2051 return _forward_call(self->reader, "readable", args);
2052}
2053
2054static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002055bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002056{
2057 return _forward_call(self->writer, "writable", args);
2058}
2059
2060static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002061bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002062{
2063 PyObject *ret = _forward_call(self->writer, "close", args);
2064 if (ret == NULL)
2065 return NULL;
2066 Py_DECREF(ret);
2067
2068 return _forward_call(self->reader, "close", args);
2069}
2070
2071static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002072bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002073{
2074 PyObject *ret = _forward_call(self->writer, "isatty", args);
2075
2076 if (ret != Py_False) {
2077 /* either True or exception */
2078 return ret;
2079 }
2080 Py_DECREF(ret);
2081
2082 return _forward_call(self->reader, "isatty", args);
2083}
2084
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002085static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002086bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002087{
2088 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2089}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002090
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002091static PyMethodDef bufferedrwpair_methods[] = {
2092 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2093 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2094 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2095 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002096
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002097 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2098 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002099
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002100 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2101 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002102
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002103 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2104 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002105
2106 {NULL, NULL}
2107};
2108
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002109static PyGetSetDef bufferedrwpair_getset[] = {
2110 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002111 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002112};
2113
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002114PyTypeObject PyBufferedRWPair_Type = {
2115 PyVarObject_HEAD_INIT(NULL, 0)
2116 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002117 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002118 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002119 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002120 0, /*tp_print*/
2121 0, /*tp_getattr*/
2122 0, /*tp_setattr*/
2123 0, /*tp_compare */
2124 0, /*tp_repr*/
2125 0, /*tp_as_number*/
2126 0, /*tp_as_sequence*/
2127 0, /*tp_as_mapping*/
2128 0, /*tp_hash */
2129 0, /*tp_call*/
2130 0, /*tp_str*/
2131 0, /*tp_getattro*/
2132 0, /*tp_setattro*/
2133 0, /*tp_as_buffer*/
2134 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2135 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002136 bufferedrwpair_doc, /* tp_doc */
2137 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2138 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002139 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002140 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002141 0, /* tp_iter */
2142 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002143 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002144 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002145 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002146 0, /* tp_base */
2147 0, /* tp_dict */
2148 0, /* tp_descr_get */
2149 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002150 offsetof(rwpair, dict), /* tp_dictoffset */
2151 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002152 0, /* tp_alloc */
2153 PyType_GenericNew, /* tp_new */
2154};
2155
2156
2157
2158/*
2159 * BufferedRandom
2160 */
2161
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002162PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002163 "A buffered interface to random access streams.\n"
2164 "\n"
2165 "The constructor creates a reader and writer for a seekable stream,\n"
2166 "raw, given in the first argument. If the buffer_size is omitted it\n"
2167 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2168 );
2169
2170static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002171bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002172{
2173 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2174 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002175 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002176 PyObject *raw;
2177
2178 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002179 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002180
2181 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2182 &raw, &buffer_size, &max_buffer_size)) {
2183 return -1;
2184 }
2185
Benjamin Peterson59406a92009-03-26 17:10:29 +00002186 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2187 return -1;
2188
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002189 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002190 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002191 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002192 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002193 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002194 return -1;
2195
2196 Py_CLEAR(self->raw);
2197 Py_INCREF(raw);
2198 self->raw = raw;
2199 self->buffer_size = buffer_size;
2200 self->readable = 1;
2201 self->writable = 1;
2202
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002203 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002204 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002205 _bufferedreader_reset_buf(self);
2206 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002207 self->pos = 0;
2208
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002209 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2210 Py_TYPE(raw) == &PyFileIO_Type);
2211
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002212 self->ok = 1;
2213 return 0;
2214}
2215
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002216static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002217 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002218 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2219 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2220 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2221 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2222 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2223 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2224 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002225
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002226 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002227
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002228 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2229 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2230 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2231 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2232 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2233 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2234 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2235 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2236 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002237 {NULL, NULL}
2238};
2239
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002240static PyMemberDef bufferedrandom_members[] = {
2241 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002242 {NULL}
2243};
2244
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002245static PyGetSetDef bufferedrandom_getset[] = {
2246 {"closed", (getter)buffered_closed_get, NULL, NULL},
2247 {"name", (getter)buffered_name_get, NULL, NULL},
2248 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002249 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002250};
2251
2252
2253PyTypeObject PyBufferedRandom_Type = {
2254 PyVarObject_HEAD_INIT(NULL, 0)
2255 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002256 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002257 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002258 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002259 0, /*tp_print*/
2260 0, /*tp_getattr*/
2261 0, /*tp_setattr*/
2262 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002263 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002264 0, /*tp_as_number*/
2265 0, /*tp_as_sequence*/
2266 0, /*tp_as_mapping*/
2267 0, /*tp_hash */
2268 0, /*tp_call*/
2269 0, /*tp_str*/
2270 0, /*tp_getattro*/
2271 0, /*tp_setattro*/
2272 0, /*tp_as_buffer*/
2273 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2274 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002275 bufferedrandom_doc, /* tp_doc */
2276 (traverseproc)buffered_traverse, /* tp_traverse */
2277 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002278 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002279 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002280 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002281 (iternextfunc)buffered_iternext, /* tp_iternext */
2282 bufferedrandom_methods, /* tp_methods */
2283 bufferedrandom_members, /* tp_members */
2284 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002285 0, /* tp_base */
2286 0, /*tp_dict*/
2287 0, /* tp_descr_get */
2288 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002289 offsetof(buffered, dict), /*tp_dictoffset*/
2290 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002291 0, /* tp_alloc */
2292 PyType_GenericNew, /* tp_new */
2293};
2294