blob: 3dec67b5c6b92059b2d910ee3843512e477d96ee [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) {
441 /* If flush() fails, just give up */
442 if (PyErr_ExceptionMatches(PyExc_IOError))
443 PyErr_Clear();
444 else
445 goto end;
446 }
447 Py_XDECREF(res);
448
449 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
450
451end:
452 LEAVE_BUFFERED(self)
453 return res;
454}
455
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000456/* detach */
457
458static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000459buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000460{
461 PyObject *raw, *res;
462 CHECK_INITIALIZED(self)
463 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
464 if (res == NULL)
465 return NULL;
466 Py_DECREF(res);
467 raw = self->raw;
468 self->raw = NULL;
469 self->detached = 1;
470 self->ok = 0;
471 return raw;
472}
473
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000474/* Inquiries */
475
476static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000477buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000478{
479 CHECK_INITIALIZED(self)
480 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
481}
482
483static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000484buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000485{
486 CHECK_INITIALIZED(self)
487 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
488}
489
490static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000491buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000492{
493 CHECK_INITIALIZED(self)
494 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
495}
496
497static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000498buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000499{
500 CHECK_INITIALIZED(self)
501 return PyObject_GetAttrString(self->raw, "name");
502}
503
504static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000505buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000506{
507 CHECK_INITIALIZED(self)
508 return PyObject_GetAttrString(self->raw, "mode");
509}
510
511/* Lower-level APIs */
512
513static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000514buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000515{
516 CHECK_INITIALIZED(self)
517 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
518}
519
520static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000521buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000522{
523 CHECK_INITIALIZED(self)
524 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
525}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000526
527
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000528/* Forward decls */
529static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000530_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000531static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000532_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000533static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000534_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000535static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000536_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000537static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000538_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000539static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000540_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000541static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000542_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000543static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000544_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000545
546
547/*
548 * Helpers
549 */
550
551/* Returns the address of the `written` member if a BlockingIOError was
552 raised, NULL otherwise. The error is always re-raised. */
553static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000554_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000555{
556 PyObject *t, *v, *tb;
557 PyBlockingIOErrorObject *err;
558
559 PyErr_Fetch(&t, &v, &tb);
560 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
561 PyErr_Restore(t, v, tb);
562 return NULL;
563 }
564 err = (PyBlockingIOErrorObject *) v;
565 /* TODO: sanity check (err->written >= 0) */
566 PyErr_Restore(t, v, tb);
567 return &err->written;
568}
569
570static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000571_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000572{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000573 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000574 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000575 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
576 if (res == NULL)
577 return -1;
578 n = PyNumber_AsOff_t(res, PyExc_ValueError);
579 Py_DECREF(res);
580 if (n < 0) {
581 if (!PyErr_Occurred())
582 PyErr_Format(PyExc_IOError,
Mark Dickinsoncb9285c2009-10-29 09:58:06 +0000583 "Raw stream returned invalid position %zd", n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000584 return -1;
585 }
586 self->abs_pos = n;
587 return n;
588}
589
590static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000591_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000592{
593 PyObject *res, *posobj, *whenceobj;
594 Py_off_t n;
595
596 posobj = PyLong_FromOff_t(target);
597 if (posobj == NULL)
598 return -1;
599 whenceobj = PyLong_FromLong(whence);
600 if (whenceobj == NULL) {
601 Py_DECREF(posobj);
602 return -1;
603 }
604 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
605 posobj, whenceobj, NULL);
606 Py_DECREF(posobj);
607 Py_DECREF(whenceobj);
608 if (res == NULL)
609 return -1;
610 n = PyNumber_AsOff_t(res, PyExc_ValueError);
611 Py_DECREF(res);
612 if (n < 0) {
613 if (!PyErr_Occurred())
614 PyErr_Format(PyExc_IOError,
Mark Dickinsoncb9285c2009-10-29 09:58:06 +0000615 "Raw stream returned invalid position %zd", n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000616 return -1;
617 }
618 self->abs_pos = n;
619 return n;
620}
621
622static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000623_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000624{
625 Py_ssize_t n;
626 if (self->buffer_size <= 0) {
627 PyErr_SetString(PyExc_ValueError,
628 "buffer size must be strictly positive");
629 return -1;
630 }
631 if (self->buffer)
632 PyMem_Free(self->buffer);
633 self->buffer = PyMem_Malloc(self->buffer_size);
634 if (self->buffer == NULL) {
635 PyErr_NoMemory();
636 return -1;
637 }
Georg Brandldfd73442009-04-05 11:47:34 +0000638#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000639 self->lock = PyThread_allocate_lock();
640 if (self->lock == NULL) {
641 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
642 return -1;
643 }
Georg Brandldfd73442009-04-05 11:47:34 +0000644#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000645 /* Find out whether buffer_size is a power of 2 */
646 /* XXX is this optimization useful? */
647 for (n = self->buffer_size - 1; n & 1; n >>= 1)
648 ;
649 if (n == 0)
650 self->buffer_mask = self->buffer_size - 1;
651 else
652 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000653 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000654 PyErr_Clear();
655 return 0;
656}
657
658/*
659 * Shared methods and wrappers
660 */
661
662static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000663buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000664{
665 PyObject *res;
666
667 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000668 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000669
670 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000671 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000672 if (res != NULL && self->readable) {
673 /* Rewind the raw stream so that its position corresponds to
674 the current logical position. */
675 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000676 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000677 if (n == -1)
678 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000679 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000680 }
681 LEAVE_BUFFERED(self)
682
683 return res;
684}
685
686static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000687buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000688{
689 Py_ssize_t n = 0;
690 PyObject *res = NULL;
691
692 CHECK_INITIALIZED(self)
693 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
694 return NULL;
695 }
696
697 ENTER_BUFFERED(self)
698
699 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000700 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000701 if (res == NULL)
702 goto end;
703 Py_CLEAR(res);
704 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000705 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000706
707end:
708 LEAVE_BUFFERED(self)
709 return res;
710}
711
712static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000713buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000714{
715 Py_ssize_t n = -1;
716 PyObject *res;
717
718 CHECK_INITIALIZED(self)
719 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
720 return NULL;
721 }
722 if (n < -1) {
723 PyErr_SetString(PyExc_ValueError,
724 "read length must be positive or -1");
725 return NULL;
726 }
727
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000728 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000729
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000730 if (n == -1) {
731 /* The number of bytes is unspecified, read until the end of stream */
732 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000733 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000734 LEAVE_BUFFERED(self)
735 }
736 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000737 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000738 if (res == Py_None) {
739 Py_DECREF(res);
740 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000741 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000742 LEAVE_BUFFERED(self)
743 }
744 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000745
746 return res;
747}
748
749static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000750buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000751{
752 Py_ssize_t n, have, r;
753 PyObject *res = NULL;
754
755 CHECK_INITIALIZED(self)
756 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
757 return NULL;
758 }
759
760 if (n < 0) {
761 PyErr_SetString(PyExc_ValueError,
762 "read length must be positive");
763 return NULL;
764 }
765 if (n == 0)
766 return PyBytes_FromStringAndSize(NULL, 0);
767
768 ENTER_BUFFERED(self)
769
770 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000771 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000772 if (res == NULL)
773 goto end;
774 Py_CLEAR(res);
775 }
776
777 /* Return up to n bytes. If at least one byte is buffered, we
778 only return buffered bytes. Otherwise, we do one raw read. */
779
780 /* XXX: this mimicks the io.py implementation but is probably wrong.
781 If we need to read from the raw stream, then we could actually read
782 all `n` bytes asked by the caller (and possibly more, so as to fill
783 our buffer for the next reads). */
784
785 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
786 if (have > 0) {
787 if (n > have)
788 n = have;
789 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
790 if (res == NULL)
791 goto end;
792 self->pos += n;
793 goto end;
794 }
795
796 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000797 _bufferedreader_reset_buf(self);
798 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000799 if (r == -1)
800 goto end;
801 if (r == -2)
802 r = 0;
803 if (n > r)
804 n = r;
805 res = PyBytes_FromStringAndSize(self->buffer, n);
806 if (res == NULL)
807 goto end;
808 self->pos = n;
809
810end:
811 LEAVE_BUFFERED(self)
812 return res;
813}
814
815static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000816buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000817{
818 PyObject *res = NULL;
819
820 CHECK_INITIALIZED(self)
821
822 /* TODO: use raw.readinto() instead! */
823 if (self->writable) {
824 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000825 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000826 LEAVE_BUFFERED(self)
827 if (res == NULL)
828 goto end;
829 Py_DECREF(res);
830 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000831 res = bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000832
833end:
834 return res;
835}
836
837static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000838_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000839{
840 PyObject *res = NULL;
841 PyObject *chunks = NULL;
842 Py_ssize_t n, written = 0;
843 const char *start, *s, *end;
844
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000845 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000846
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000847 /* First, try to find a line in the buffer. This can run unlocked because
848 the calls to the C API are simple enough that they can't trigger
849 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000850 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
851 if (limit >= 0 && n > limit)
852 n = limit;
853 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000854 s = memchr(start, '\n', n);
855 if (s != NULL) {
856 res = PyBytes_FromStringAndSize(start, s - start + 1);
857 if (res != NULL)
858 self->pos += s - start + 1;
859 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000860 }
861 if (n == limit) {
862 res = PyBytes_FromStringAndSize(start, n);
863 if (res != NULL)
864 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000865 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000866 }
867
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000868 ENTER_BUFFERED(self)
869
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000870 /* Now we try to get some more from the raw stream */
871 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000872 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000873 if (res == NULL)
874 goto end;
875 Py_CLEAR(res);
876 }
877 chunks = PyList_New(0);
878 if (chunks == NULL)
879 goto end;
880 if (n > 0) {
881 res = PyBytes_FromStringAndSize(start, n);
882 if (res == NULL)
883 goto end;
884 if (PyList_Append(chunks, res) < 0) {
885 Py_CLEAR(res);
886 goto end;
887 }
888 Py_CLEAR(res);
889 written += n;
890 if (limit >= 0)
891 limit -= n;
892 }
893
894 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000895 _bufferedreader_reset_buf(self);
896 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000897 if (n == -1)
898 goto end;
899 if (n <= 0)
900 break;
901 if (limit >= 0 && n > limit)
902 n = limit;
903 start = self->buffer;
904 end = start + n;
905 s = start;
906 while (s < end) {
907 if (*s++ == '\n') {
908 res = PyBytes_FromStringAndSize(start, s - start);
909 if (res == NULL)
910 goto end;
911 self->pos = s - start;
912 goto found;
913 }
914 }
915 res = PyBytes_FromStringAndSize(start, n);
916 if (res == NULL)
917 goto end;
918 if (n == limit) {
919 self->pos = n;
920 break;
921 }
922 if (PyList_Append(chunks, res) < 0) {
923 Py_CLEAR(res);
924 goto end;
925 }
926 Py_CLEAR(res);
927 written += n;
928 if (limit >= 0)
929 limit -= n;
930 }
931found:
932 if (res != NULL && PyList_Append(chunks, res) < 0) {
933 Py_CLEAR(res);
934 goto end;
935 }
936 Py_CLEAR(res);
937 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
938
939end:
940 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000941end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000942 Py_XDECREF(chunks);
943 return res;
944}
945
946static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000947buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000948{
949 Py_ssize_t limit = -1;
950
951 CHECK_INITIALIZED(self)
952
953 if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
954 return NULL;
955 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000956 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000957}
958
959
960static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000961buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000962{
963 Py_off_t pos;
964
965 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000966 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000967 if (pos == -1)
968 return NULL;
969 pos -= RAW_OFFSET(self);
970 /* TODO: sanity check (pos >= 0) */
971 return PyLong_FromOff_t(pos);
972}
973
974static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000975buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000976{
977 Py_off_t target, n;
978 int whence = 0;
979 PyObject *targetobj, *res = NULL;
980
981 CHECK_INITIALIZED(self)
982 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
983 return NULL;
984 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000985 if (whence < 0 || whence > 2) {
986 PyErr_Format(PyExc_ValueError,
987 "whence must be between 0 and 2, not %d", whence);
988 return NULL;
989 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000990
991 CHECK_CLOSED(self, "seek of closed file")
992
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000993 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
994 if (target == -1 && PyErr_Occurred())
995 return NULL;
996
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000997 if (whence != 2 && self->readable) {
998 Py_off_t current, avail;
999 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001000 so as to return quickly if possible. Also, we needn't take the
1001 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001002 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001003 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1004 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001005 current = RAW_TELL(self);
1006 avail = READAHEAD(self);
1007 if (avail > 0) {
1008 Py_off_t offset;
1009 if (whence == 0)
1010 offset = target - (current - RAW_OFFSET(self));
1011 else
1012 offset = target;
1013 if (offset >= -self->pos && offset <= avail) {
1014 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001015 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001016 }
1017 }
1018 }
1019
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001020 ENTER_BUFFERED(self)
1021
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001022 /* Fallback: invoke raw seek() method and clear buffer */
1023 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001024 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001025 if (res == NULL)
1026 goto end;
1027 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001028 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001029 }
1030
1031 /* TODO: align on block boundary and read buffer if needed? */
1032 if (whence == 1)
1033 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001034 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001035 if (n == -1)
1036 goto end;
1037 self->raw_pos = -1;
1038 res = PyLong_FromOff_t(n);
1039 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001040 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001041
1042end:
1043 LEAVE_BUFFERED(self)
1044 return res;
1045}
1046
1047static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001048buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001049{
1050 PyObject *pos = Py_None;
1051 PyObject *res = NULL;
1052
1053 CHECK_INITIALIZED(self)
1054 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1055 return NULL;
1056 }
1057
1058 ENTER_BUFFERED(self)
1059
1060 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001061 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001062 if (res == NULL)
1063 goto end;
1064 Py_CLEAR(res);
1065 }
1066 if (self->readable) {
1067 if (pos == Py_None) {
1068 /* Rewind the raw stream so that its position corresponds to
1069 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001070 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001071 goto end;
1072 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001073 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001074 }
1075 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1076 if (res == NULL)
1077 goto end;
1078 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001079 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001080 PyErr_Clear();
1081
1082end:
1083 LEAVE_BUFFERED(self)
1084 return res;
1085}
1086
1087static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001088buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001089{
1090 PyObject *line;
1091 PyTypeObject *tp;
1092
1093 CHECK_INITIALIZED(self);
1094
1095 tp = Py_TYPE(self);
1096 if (tp == &PyBufferedReader_Type ||
1097 tp == &PyBufferedRandom_Type) {
1098 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001099 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001100 }
1101 else {
1102 line = PyObject_CallMethodObjArgs((PyObject *)self,
1103 _PyIO_str_readline, NULL);
1104 if (line && !PyBytes_Check(line)) {
1105 PyErr_Format(PyExc_IOError,
1106 "readline() should have returned a bytes object, "
1107 "not '%.200s'", Py_TYPE(line)->tp_name);
1108 Py_DECREF(line);
1109 return NULL;
1110 }
1111 }
1112
1113 if (line == NULL)
1114 return NULL;
1115
1116 if (PyBytes_GET_SIZE(line) == 0) {
1117 /* Reached EOF or would have blocked */
1118 Py_DECREF(line);
1119 return NULL;
1120 }
1121
1122 return line;
1123}
1124
Antoine Pitrou716c4442009-05-23 19:04:03 +00001125static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001126buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001127{
1128 PyObject *nameobj, *res;
1129
1130 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1131 if (nameobj == NULL) {
1132 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1133 PyErr_Clear();
1134 else
1135 return NULL;
1136 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1137 }
1138 else {
1139 res = PyUnicode_FromFormat("<%s name=%R>",
1140 Py_TYPE(self)->tp_name, nameobj);
1141 Py_DECREF(nameobj);
1142 }
1143 return res;
1144}
1145
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001146/*
1147 * class BufferedReader
1148 */
1149
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001150PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001151 "Create a new buffered reader using the given readable raw IO object.");
1152
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001153static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001154{
1155 self->read_end = -1;
1156}
1157
1158static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001159bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001160{
1161 char *kwlist[] = {"raw", "buffer_size", NULL};
1162 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1163 PyObject *raw;
1164
1165 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001166 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001167
1168 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1169 &raw, &buffer_size)) {
1170 return -1;
1171 }
1172
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001173 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001174 return -1;
1175
1176 Py_CLEAR(self->raw);
1177 Py_INCREF(raw);
1178 self->raw = raw;
1179 self->buffer_size = buffer_size;
1180 self->readable = 1;
1181 self->writable = 0;
1182
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001183 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001184 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001185 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001186
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001187 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1188 Py_TYPE(raw) == &PyFileIO_Type);
1189
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001190 self->ok = 1;
1191 return 0;
1192}
1193
1194static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001195_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001196{
1197 Py_buffer buf;
1198 PyObject *memobj, *res;
1199 Py_ssize_t n;
1200 /* NOTE: the buffer needn't be released as its object is NULL. */
1201 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1202 return -1;
1203 memobj = PyMemoryView_FromBuffer(&buf);
1204 if (memobj == NULL)
1205 return -1;
1206 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1207 Py_DECREF(memobj);
1208 if (res == NULL)
1209 return -1;
1210 if (res == Py_None) {
1211 /* Non-blocking stream would have blocked. Special return code! */
1212 Py_DECREF(res);
1213 return -2;
1214 }
1215 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1216 Py_DECREF(res);
1217 if (n < 0 || n > len) {
1218 PyErr_Format(PyExc_IOError,
1219 "raw readinto() returned invalid length %zd "
1220 "(should have been between 0 and %zd)", n, len);
1221 return -1;
1222 }
1223 if (n > 0 && self->abs_pos != -1)
1224 self->abs_pos += n;
1225 return n;
1226}
1227
1228static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001229_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001230{
1231 Py_ssize_t start, len, n;
1232 if (VALID_READ_BUFFER(self))
1233 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1234 else
1235 start = 0;
1236 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001237 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001238 if (n <= 0)
1239 return n;
1240 self->read_end = start + n;
1241 self->raw_pos = start + n;
1242 return n;
1243}
1244
1245static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001246_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001247{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001248 Py_ssize_t current_size;
1249 PyObject *res, *data = NULL;
1250 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001251
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001252 if (chunks == NULL)
1253 return NULL;
1254
1255 /* First copy what we have in the current buffer. */
1256 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1257 if (current_size) {
1258 data = PyBytes_FromStringAndSize(
1259 self->buffer + self->pos, current_size);
1260 if (data == NULL) {
1261 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001262 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001263 }
1264 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001265 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001266 /* We're going past the buffer's bounds, flush it */
1267 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001268 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001269 if (res == NULL) {
1270 Py_DECREF(chunks);
1271 return NULL;
1272 }
1273 Py_CLEAR(res);
1274 }
1275 while (1) {
1276 if (data) {
1277 if (PyList_Append(chunks, data) < 0) {
1278 Py_DECREF(data);
1279 Py_DECREF(chunks);
1280 return NULL;
1281 }
1282 Py_DECREF(data);
1283 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001284
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001285 /* Read until EOF or until read() would block. */
1286 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1287 if (data == NULL) {
1288 Py_DECREF(chunks);
1289 return NULL;
1290 }
1291 if (data != Py_None && !PyBytes_Check(data)) {
1292 Py_DECREF(data);
1293 Py_DECREF(chunks);
1294 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1295 return NULL;
1296 }
1297 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1298 if (current_size == 0) {
1299 Py_DECREF(chunks);
1300 return data;
1301 }
1302 else {
1303 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1304 Py_DECREF(data);
1305 Py_DECREF(chunks);
1306 return res;
1307 }
1308 }
1309 current_size += PyBytes_GET_SIZE(data);
1310 if (self->abs_pos != -1)
1311 self->abs_pos += PyBytes_GET_SIZE(data);
1312 }
1313}
1314
1315/* Read n bytes from the buffer if it can, otherwise return None.
1316 This function is simple enough that it can run unlocked. */
1317static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001318_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001319{
1320 Py_ssize_t current_size;
1321
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001322 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1323 if (n <= current_size) {
1324 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001325 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1326 if (res != NULL)
1327 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001328 return res;
1329 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001330 Py_RETURN_NONE;
1331}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001332
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001333/* Generic read function: read from the stream until enough bytes are read,
1334 * or until an EOF occurs or until read() would block.
1335 */
1336static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001337_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001338{
1339 PyObject *res = NULL;
1340 Py_ssize_t current_size, remaining, written;
1341 char *out;
1342
1343 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1344 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001345 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001346
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001347 res = PyBytes_FromStringAndSize(NULL, n);
1348 if (res == NULL)
1349 goto error;
1350 out = PyBytes_AS_STRING(res);
1351 remaining = n;
1352 written = 0;
1353 if (current_size > 0) {
1354 memcpy(out, self->buffer + self->pos, current_size);
1355 remaining -= current_size;
1356 written += current_size;
1357 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001358 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001359 while (remaining > 0) {
1360 /* We want to read a whole block at the end into buffer.
1361 If we had readv() we could do this in one pass. */
1362 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1363 if (r == 0)
1364 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001365 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001366 if (r == -1)
1367 goto error;
1368 if (r == 0 || r == -2) {
1369 /* EOF occurred or read() would block. */
1370 if (r == 0 || written > 0) {
1371 if (_PyBytes_Resize(&res, written))
1372 goto error;
1373 return res;
1374 }
1375 Py_DECREF(res);
1376 Py_INCREF(Py_None);
1377 return Py_None;
1378 }
1379 remaining -= r;
1380 written += r;
1381 }
1382 assert(remaining <= self->buffer_size);
1383 self->pos = 0;
1384 self->raw_pos = 0;
1385 self->read_end = 0;
1386 while (self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001387 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001388 if (r == -1)
1389 goto error;
1390 if (r == 0 || r == -2) {
1391 /* EOF occurred or read() would block. */
1392 if (r == 0 || written > 0) {
1393 if (_PyBytes_Resize(&res, written))
1394 goto error;
1395 return res;
1396 }
1397 Py_DECREF(res);
1398 Py_INCREF(Py_None);
1399 return Py_None;
1400 }
1401 if (remaining > r) {
1402 memcpy(out + written, self->buffer + self->pos, r);
1403 written += r;
1404 self->pos += r;
1405 remaining -= r;
1406 }
1407 else if (remaining > 0) {
1408 memcpy(out + written, self->buffer + self->pos, remaining);
1409 written += remaining;
1410 self->pos += remaining;
1411 remaining = 0;
1412 }
1413 if (remaining == 0)
1414 break;
1415 }
1416
1417 return res;
1418
1419error:
1420 Py_XDECREF(res);
1421 return NULL;
1422}
1423
1424static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001425_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001426{
1427 Py_ssize_t have, r;
1428
1429 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1430 /* Constraints:
1431 1. we don't want to advance the file position.
1432 2. we don't want to lose block alignment, so we can't shift the buffer
1433 to make some place.
1434 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1435 */
1436 if (have > 0) {
1437 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1438 }
1439
1440 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001441 _bufferedreader_reset_buf(self);
1442 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001443 if (r == -1)
1444 return NULL;
1445 if (r == -2)
1446 r = 0;
1447 self->pos = 0;
1448 return PyBytes_FromStringAndSize(self->buffer, r);
1449}
1450
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001451static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001452 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001453 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1454 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1455 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1456 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1457 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1458 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1459 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1460 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001461
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001462 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1463 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1464 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1465 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1466 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1467 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1468 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001469 {NULL, NULL}
1470};
1471
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001472static PyMemberDef bufferedreader_members[] = {
1473 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001474 {NULL}
1475};
1476
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001477static PyGetSetDef bufferedreader_getset[] = {
1478 {"closed", (getter)buffered_closed_get, NULL, NULL},
1479 {"name", (getter)buffered_name_get, NULL, NULL},
1480 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001481 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001482};
1483
1484
1485PyTypeObject PyBufferedReader_Type = {
1486 PyVarObject_HEAD_INIT(NULL, 0)
1487 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001488 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001489 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001490 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001491 0, /*tp_print*/
1492 0, /*tp_getattr*/
1493 0, /*tp_setattr*/
1494 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001495 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001496 0, /*tp_as_number*/
1497 0, /*tp_as_sequence*/
1498 0, /*tp_as_mapping*/
1499 0, /*tp_hash */
1500 0, /*tp_call*/
1501 0, /*tp_str*/
1502 0, /*tp_getattro*/
1503 0, /*tp_setattro*/
1504 0, /*tp_as_buffer*/
1505 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1506 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001507 bufferedreader_doc, /* tp_doc */
1508 (traverseproc)buffered_traverse, /* tp_traverse */
1509 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001510 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001511 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001512 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001513 (iternextfunc)buffered_iternext, /* tp_iternext */
1514 bufferedreader_methods, /* tp_methods */
1515 bufferedreader_members, /* tp_members */
1516 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001517 0, /* tp_base */
1518 0, /* tp_dict */
1519 0, /* tp_descr_get */
1520 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001521 offsetof(buffered, dict), /* tp_dictoffset */
1522 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001523 0, /* tp_alloc */
1524 PyType_GenericNew, /* tp_new */
1525};
1526
1527
Benjamin Peterson59406a92009-03-26 17:10:29 +00001528
1529static int
1530complain_about_max_buffer_size(void)
1531{
1532 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1533 "max_buffer_size is deprecated", 1) < 0)
1534 return 0;
1535 return 1;
1536}
1537
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001538/*
1539 * class BufferedWriter
1540 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001541PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001542 "A buffer for a writeable sequential RawIO object.\n"
1543 "\n"
1544 "The constructor creates a BufferedWriter for the given writeable raw\n"
1545 "stream. If the buffer_size is not given, it defaults to\n"
1546 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1547 );
1548
1549static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001550_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001551{
1552 self->write_pos = 0;
1553 self->write_end = -1;
1554}
1555
1556static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001557bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001558{
1559 /* TODO: properly deprecate max_buffer_size */
1560 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1561 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001562 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001563 PyObject *raw;
1564
1565 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001566 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001567
1568 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1569 &raw, &buffer_size, &max_buffer_size)) {
1570 return -1;
1571 }
1572
Benjamin Peterson59406a92009-03-26 17:10:29 +00001573 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1574 return -1;
1575
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001576 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001577 return -1;
1578
1579 Py_CLEAR(self->raw);
1580 Py_INCREF(raw);
1581 self->raw = raw;
1582 self->readable = 0;
1583 self->writable = 1;
1584
1585 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001586 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001587 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001588 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001589 self->pos = 0;
1590
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001591 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1592 Py_TYPE(raw) == &PyFileIO_Type);
1593
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001594 self->ok = 1;
1595 return 0;
1596}
1597
1598static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001599_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001600{
1601 Py_buffer buf;
1602 PyObject *memobj, *res;
1603 Py_ssize_t n;
1604 /* NOTE: the buffer needn't be released as its object is NULL. */
1605 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1606 return -1;
1607 memobj = PyMemoryView_FromBuffer(&buf);
1608 if (memobj == NULL)
1609 return -1;
1610 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1611 Py_DECREF(memobj);
1612 if (res == NULL)
1613 return -1;
1614 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1615 Py_DECREF(res);
1616 if (n < 0 || n > len) {
1617 PyErr_Format(PyExc_IOError,
1618 "raw write() returned invalid length %zd "
1619 "(should have been between 0 and %zd)", n, len);
1620 return -1;
1621 }
1622 if (n > 0 && self->abs_pos != -1)
1623 self->abs_pos += n;
1624 return n;
1625}
1626
1627/* `restore_pos` is 1 if we need to restore the raw stream position at
1628 the end, 0 otherwise. */
1629static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001630_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001631{
1632 Py_ssize_t written = 0;
1633 Py_off_t n, rewind;
1634
1635 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1636 goto end;
1637 /* First, rewind */
1638 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1639 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001640 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001641 if (n < 0) {
1642 goto error;
1643 }
1644 self->raw_pos -= rewind;
1645 }
1646 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001647 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001648 self->buffer + self->write_pos,
1649 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1650 Py_off_t, Py_ssize_t));
1651 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001652 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001653 if (w == NULL)
1654 goto error;
1655 self->write_pos += *w;
1656 self->raw_pos = self->write_pos;
1657 written += *w;
1658 *w = written;
1659 /* Already re-raised */
1660 goto error;
1661 }
1662 self->write_pos += n;
1663 self->raw_pos = self->write_pos;
1664 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1665 }
1666
1667 if (restore_pos) {
1668 Py_off_t forward = rewind - written;
1669 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001670 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001671 if (n < 0) {
1672 goto error;
1673 }
1674 self->raw_pos += forward;
1675 }
1676 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001677 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001678
1679end:
1680 Py_RETURN_NONE;
1681
1682error:
1683 return NULL;
1684}
1685
1686static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001687bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001688{
1689 PyObject *res = NULL;
1690 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001691 Py_ssize_t written, avail, remaining;
1692 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001693
1694 CHECK_INITIALIZED(self)
1695 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1696 return NULL;
1697 }
1698
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001699 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001700 PyErr_SetString(PyExc_ValueError, "write to closed file");
1701 PyBuffer_Release(&buf);
1702 return NULL;
1703 }
1704
1705 ENTER_BUFFERED(self)
1706
1707 /* Fast path: the data to write can be fully buffered. */
1708 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1709 self->pos = 0;
1710 self->raw_pos = 0;
1711 }
1712 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1713 if (buf.len <= avail) {
1714 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1715 if (!VALID_WRITE_BUFFER(self)) {
1716 self->write_pos = self->pos;
1717 }
1718 ADJUST_POSITION(self, self->pos + buf.len);
1719 if (self->pos > self->write_end)
1720 self->write_end = self->pos;
1721 written = buf.len;
1722 goto end;
1723 }
1724
1725 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001726 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001727 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001728 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001729 if (w == NULL)
1730 goto error;
1731 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001732 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001733 /* Make some place by shifting the buffer. */
1734 assert(VALID_WRITE_BUFFER(self));
1735 memmove(self->buffer, self->buffer + self->write_pos,
1736 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1737 Py_off_t, Py_ssize_t));
1738 self->write_end -= self->write_pos;
1739 self->raw_pos -= self->write_pos;
1740 self->pos -= self->write_pos;
1741 self->write_pos = 0;
1742 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1743 Py_off_t, Py_ssize_t);
1744 if (buf.len <= avail) {
1745 /* Everything can be buffered */
1746 PyErr_Clear();
1747 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1748 self->write_end += buf.len;
1749 written = buf.len;
1750 goto end;
1751 }
1752 /* Buffer as much as possible. */
1753 memcpy(self->buffer + self->write_end, buf.buf, avail);
1754 self->write_end += avail;
1755 /* Already re-raised */
1756 *w = avail;
1757 goto error;
1758 }
1759 Py_CLEAR(res);
1760
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001761 /* Adjust the raw stream position if it is away from the logical stream
1762 position. This happens if the read buffer has been filled but not
1763 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1764 the raw stream by itself).
1765 Fixes issue #6629.
1766 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001767 offset = RAW_OFFSET(self);
1768 if (offset != 0) {
1769 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001770 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001771 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001772 }
1773
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001774 /* Then write buf itself. At this point the buffer has been emptied. */
1775 remaining = buf.len;
1776 written = 0;
1777 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001778 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001779 self, (char *) buf.buf + written, buf.len - written);
1780 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001781 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001782 if (w == NULL)
1783 goto error;
1784 written += *w;
1785 remaining -= *w;
1786 if (remaining > self->buffer_size) {
1787 /* Can't buffer everything, still buffer as much as possible */
1788 memcpy(self->buffer,
1789 (char *) buf.buf + written, self->buffer_size);
1790 self->raw_pos = 0;
1791 ADJUST_POSITION(self, self->buffer_size);
1792 self->write_end = self->buffer_size;
1793 *w = written + self->buffer_size;
1794 /* Already re-raised */
1795 goto error;
1796 }
1797 PyErr_Clear();
1798 break;
1799 }
1800 written += n;
1801 remaining -= n;
1802 }
1803 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001804 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001805 if (remaining > 0) {
1806 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1807 written += remaining;
1808 }
1809 self->write_pos = 0;
1810 /* TODO: sanity check (remaining >= 0) */
1811 self->write_end = remaining;
1812 ADJUST_POSITION(self, remaining);
1813 self->raw_pos = 0;
1814
1815end:
1816 res = PyLong_FromSsize_t(written);
1817
1818error:
1819 LEAVE_BUFFERED(self)
1820 PyBuffer_Release(&buf);
1821 return res;
1822}
1823
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001824static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001825 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001826 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1827 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1828 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1829 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1830 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1831 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1832 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001833
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001834 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1835 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1836 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1837 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1838 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001839 {NULL, NULL}
1840};
1841
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001842static PyMemberDef bufferedwriter_members[] = {
1843 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001844 {NULL}
1845};
1846
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001847static PyGetSetDef bufferedwriter_getset[] = {
1848 {"closed", (getter)buffered_closed_get, NULL, NULL},
1849 {"name", (getter)buffered_name_get, NULL, NULL},
1850 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001851 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001852};
1853
1854
1855PyTypeObject PyBufferedWriter_Type = {
1856 PyVarObject_HEAD_INIT(NULL, 0)
1857 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001858 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001859 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001860 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001861 0, /*tp_print*/
1862 0, /*tp_getattr*/
1863 0, /*tp_setattr*/
1864 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001865 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001866 0, /*tp_as_number*/
1867 0, /*tp_as_sequence*/
1868 0, /*tp_as_mapping*/
1869 0, /*tp_hash */
1870 0, /*tp_call*/
1871 0, /*tp_str*/
1872 0, /*tp_getattro*/
1873 0, /*tp_setattro*/
1874 0, /*tp_as_buffer*/
1875 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1876 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001877 bufferedwriter_doc, /* tp_doc */
1878 (traverseproc)buffered_traverse, /* tp_traverse */
1879 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001880 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001881 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001882 0, /* tp_iter */
1883 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001884 bufferedwriter_methods, /* tp_methods */
1885 bufferedwriter_members, /* tp_members */
1886 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001887 0, /* tp_base */
1888 0, /* tp_dict */
1889 0, /* tp_descr_get */
1890 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001891 offsetof(buffered, dict), /* tp_dictoffset */
1892 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001893 0, /* tp_alloc */
1894 PyType_GenericNew, /* tp_new */
1895};
1896
1897
1898
1899/*
1900 * BufferedRWPair
1901 */
1902
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001903PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001904 "A buffered reader and writer object together.\n"
1905 "\n"
1906 "A buffered reader object and buffered writer object put together to\n"
1907 "form a sequential IO object that can read and write. This is typically\n"
1908 "used with a socket or two-way pipe.\n"
1909 "\n"
1910 "reader and writer are RawIOBase objects that are readable and\n"
1911 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001912 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001913 );
1914
1915/* XXX The usefulness of this (compared to having two separate IO objects) is
1916 * questionable.
1917 */
1918
1919typedef struct {
1920 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001921 buffered *reader;
1922 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001923 PyObject *dict;
1924 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001925} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001926
1927static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001928bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001929{
1930 PyObject *reader, *writer;
1931 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001932 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001933
1934 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1935 &buffer_size, &max_buffer_size)) {
1936 return -1;
1937 }
1938
Benjamin Peterson59406a92009-03-26 17:10:29 +00001939 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1940 return -1;
1941
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001942 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001943 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001944 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001945 return -1;
1946
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001947 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001948 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001949 if (self->reader == NULL)
1950 return -1;
1951
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001952 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001953 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001954 if (self->writer == NULL) {
1955 Py_CLEAR(self->reader);
1956 return -1;
1957 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001958
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001959 return 0;
1960}
1961
1962static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001963bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001964{
1965 Py_VISIT(self->dict);
1966 return 0;
1967}
1968
1969static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001970bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001971{
1972 Py_CLEAR(self->reader);
1973 Py_CLEAR(self->writer);
1974 Py_CLEAR(self->dict);
1975 return 0;
1976}
1977
1978static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001979bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001980{
1981 _PyObject_GC_UNTRACK(self);
1982 Py_CLEAR(self->reader);
1983 Py_CLEAR(self->writer);
1984 Py_CLEAR(self->dict);
1985 Py_TYPE(self)->tp_free((PyObject *) self);
1986}
1987
1988static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001989_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001990{
1991 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1992 PyObject *ret;
1993
1994 if (func == NULL) {
1995 PyErr_SetString(PyExc_AttributeError, name);
1996 return NULL;
1997 }
1998
1999 ret = PyObject_CallObject(func, args);
2000 Py_DECREF(func);
2001 return ret;
2002}
2003
2004static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002005bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002006{
2007 return _forward_call(self->reader, "read", args);
2008}
2009
2010static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002011bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002012{
2013 return _forward_call(self->reader, "peek", args);
2014}
2015
2016static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002017bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002018{
2019 return _forward_call(self->reader, "read1", args);
2020}
2021
2022static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002023bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002024{
2025 return _forward_call(self->reader, "readinto", args);
2026}
2027
2028static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002029bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002030{
2031 return _forward_call(self->writer, "write", args);
2032}
2033
2034static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002035bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002036{
2037 return _forward_call(self->writer, "flush", args);
2038}
2039
2040static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002041bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002042{
2043 return _forward_call(self->reader, "readable", args);
2044}
2045
2046static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002047bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002048{
2049 return _forward_call(self->writer, "writable", args);
2050}
2051
2052static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002053bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002054{
2055 PyObject *ret = _forward_call(self->writer, "close", args);
2056 if (ret == NULL)
2057 return NULL;
2058 Py_DECREF(ret);
2059
2060 return _forward_call(self->reader, "close", args);
2061}
2062
2063static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002064bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002065{
2066 PyObject *ret = _forward_call(self->writer, "isatty", args);
2067
2068 if (ret != Py_False) {
2069 /* either True or exception */
2070 return ret;
2071 }
2072 Py_DECREF(ret);
2073
2074 return _forward_call(self->reader, "isatty", args);
2075}
2076
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002077static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002078bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002079{
2080 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2081}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002082
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002083static PyMethodDef bufferedrwpair_methods[] = {
2084 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2085 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2086 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2087 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002088
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002089 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2090 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002091
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002092 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2093 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002094
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002095 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2096 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002097
2098 {NULL, NULL}
2099};
2100
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002101static PyGetSetDef bufferedrwpair_getset[] = {
2102 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002103 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002104};
2105
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002106PyTypeObject PyBufferedRWPair_Type = {
2107 PyVarObject_HEAD_INIT(NULL, 0)
2108 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002109 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002110 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002111 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002112 0, /*tp_print*/
2113 0, /*tp_getattr*/
2114 0, /*tp_setattr*/
2115 0, /*tp_compare */
2116 0, /*tp_repr*/
2117 0, /*tp_as_number*/
2118 0, /*tp_as_sequence*/
2119 0, /*tp_as_mapping*/
2120 0, /*tp_hash */
2121 0, /*tp_call*/
2122 0, /*tp_str*/
2123 0, /*tp_getattro*/
2124 0, /*tp_setattro*/
2125 0, /*tp_as_buffer*/
2126 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2127 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002128 bufferedrwpair_doc, /* tp_doc */
2129 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2130 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002131 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002132 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002133 0, /* tp_iter */
2134 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002135 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002136 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002137 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002138 0, /* tp_base */
2139 0, /* tp_dict */
2140 0, /* tp_descr_get */
2141 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002142 offsetof(rwpair, dict), /* tp_dictoffset */
2143 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002144 0, /* tp_alloc */
2145 PyType_GenericNew, /* tp_new */
2146};
2147
2148
2149
2150/*
2151 * BufferedRandom
2152 */
2153
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002154PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002155 "A buffered interface to random access streams.\n"
2156 "\n"
2157 "The constructor creates a reader and writer for a seekable stream,\n"
2158 "raw, given in the first argument. If the buffer_size is omitted it\n"
2159 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2160 );
2161
2162static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002163bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002164{
2165 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2166 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002167 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002168 PyObject *raw;
2169
2170 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002171 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002172
2173 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2174 &raw, &buffer_size, &max_buffer_size)) {
2175 return -1;
2176 }
2177
Benjamin Peterson59406a92009-03-26 17:10:29 +00002178 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2179 return -1;
2180
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002181 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002182 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002183 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002184 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002185 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002186 return -1;
2187
2188 Py_CLEAR(self->raw);
2189 Py_INCREF(raw);
2190 self->raw = raw;
2191 self->buffer_size = buffer_size;
2192 self->readable = 1;
2193 self->writable = 1;
2194
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002195 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002196 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002197 _bufferedreader_reset_buf(self);
2198 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002199 self->pos = 0;
2200
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002201 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2202 Py_TYPE(raw) == &PyFileIO_Type);
2203
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002204 self->ok = 1;
2205 return 0;
2206}
2207
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002208static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002209 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002210 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2211 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2212 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2213 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2214 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2215 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2216 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002217
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002218 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002219
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002220 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2221 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2222 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2223 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2224 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2225 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2226 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2227 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2228 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002229 {NULL, NULL}
2230};
2231
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002232static PyMemberDef bufferedrandom_members[] = {
2233 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002234 {NULL}
2235};
2236
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002237static PyGetSetDef bufferedrandom_getset[] = {
2238 {"closed", (getter)buffered_closed_get, NULL, NULL},
2239 {"name", (getter)buffered_name_get, NULL, NULL},
2240 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002241 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002242};
2243
2244
2245PyTypeObject PyBufferedRandom_Type = {
2246 PyVarObject_HEAD_INIT(NULL, 0)
2247 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002248 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002249 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002250 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002251 0, /*tp_print*/
2252 0, /*tp_getattr*/
2253 0, /*tp_setattr*/
2254 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002255 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002256 0, /*tp_as_number*/
2257 0, /*tp_as_sequence*/
2258 0, /*tp_as_mapping*/
2259 0, /*tp_hash */
2260 0, /*tp_call*/
2261 0, /*tp_str*/
2262 0, /*tp_getattro*/
2263 0, /*tp_setattro*/
2264 0, /*tp_as_buffer*/
2265 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2266 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002267 bufferedrandom_doc, /* tp_doc */
2268 (traverseproc)buffered_traverse, /* tp_traverse */
2269 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002270 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002271 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002272 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002273 (iternextfunc)buffered_iternext, /* tp_iternext */
2274 bufferedrandom_methods, /* tp_methods */
2275 bufferedrandom_members, /* tp_members */
2276 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002277 0, /* tp_base */
2278 0, /*tp_dict*/
2279 0, /* tp_descr_get */
2280 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002281 offsetof(buffered, dict), /*tp_dictoffset*/
2282 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002283 0, /* tp_alloc */
2284 PyType_GenericNew, /* tp_new */
2285};
2286