blob: e3deb10087babe15f7a9209c438ad543d346d191 [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 Dickinson65768482009-10-27 18:43:44 +0000583 "Raw stream returned invalid position %" PY_PRIdOFF,
Mark Dickinson121fbe42009-10-27 21:51:51 +0000584 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000585 return -1;
586 }
587 self->abs_pos = n;
588 return n;
589}
590
591static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000592_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000593{
594 PyObject *res, *posobj, *whenceobj;
595 Py_off_t n;
596
597 posobj = PyLong_FromOff_t(target);
598 if (posobj == NULL)
599 return -1;
600 whenceobj = PyLong_FromLong(whence);
601 if (whenceobj == NULL) {
602 Py_DECREF(posobj);
603 return -1;
604 }
605 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
606 posobj, whenceobj, NULL);
607 Py_DECREF(posobj);
608 Py_DECREF(whenceobj);
609 if (res == NULL)
610 return -1;
611 n = PyNumber_AsOff_t(res, PyExc_ValueError);
612 Py_DECREF(res);
613 if (n < 0) {
614 if (!PyErr_Occurred())
615 PyErr_Format(PyExc_IOError,
Mark Dickinson65768482009-10-27 18:43:44 +0000616 "Raw stream returned invalid position %" PY_PRIdOFF,
Mark Dickinson121fbe42009-10-27 21:51:51 +0000617 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000618 return -1;
619 }
620 self->abs_pos = n;
621 return n;
622}
623
624static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000625_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000626{
627 Py_ssize_t n;
628 if (self->buffer_size <= 0) {
629 PyErr_SetString(PyExc_ValueError,
630 "buffer size must be strictly positive");
631 return -1;
632 }
633 if (self->buffer)
634 PyMem_Free(self->buffer);
635 self->buffer = PyMem_Malloc(self->buffer_size);
636 if (self->buffer == NULL) {
637 PyErr_NoMemory();
638 return -1;
639 }
Georg Brandldfd73442009-04-05 11:47:34 +0000640#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000641 self->lock = PyThread_allocate_lock();
642 if (self->lock == NULL) {
643 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
644 return -1;
645 }
Georg Brandldfd73442009-04-05 11:47:34 +0000646#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000647 /* Find out whether buffer_size is a power of 2 */
648 /* XXX is this optimization useful? */
649 for (n = self->buffer_size - 1; n & 1; n >>= 1)
650 ;
651 if (n == 0)
652 self->buffer_mask = self->buffer_size - 1;
653 else
654 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000655 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000656 PyErr_Clear();
657 return 0;
658}
659
660/*
661 * Shared methods and wrappers
662 */
663
664static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000665buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000666{
667 PyObject *res;
668
669 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000670 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000671
672 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000673 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000674 if (res != NULL && self->readable) {
675 /* Rewind the raw stream so that its position corresponds to
676 the current logical position. */
677 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000678 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000679 if (n == -1)
680 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000681 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000682 }
683 LEAVE_BUFFERED(self)
684
685 return res;
686}
687
688static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000689buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000690{
691 Py_ssize_t n = 0;
692 PyObject *res = NULL;
693
694 CHECK_INITIALIZED(self)
695 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
696 return NULL;
697 }
698
699 ENTER_BUFFERED(self)
700
701 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000702 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000703 if (res == NULL)
704 goto end;
705 Py_CLEAR(res);
706 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000707 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000708
709end:
710 LEAVE_BUFFERED(self)
711 return res;
712}
713
714static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000715buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000716{
717 Py_ssize_t n = -1;
718 PyObject *res;
719
720 CHECK_INITIALIZED(self)
721 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
722 return NULL;
723 }
724 if (n < -1) {
725 PyErr_SetString(PyExc_ValueError,
726 "read length must be positive or -1");
727 return NULL;
728 }
729
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000730 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000731
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000732 if (n == -1) {
733 /* The number of bytes is unspecified, read until the end of stream */
734 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000735 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000736 LEAVE_BUFFERED(self)
737 }
738 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000739 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000740 if (res == Py_None) {
741 Py_DECREF(res);
742 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000743 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000744 LEAVE_BUFFERED(self)
745 }
746 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000747
748 return res;
749}
750
751static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000752buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000753{
754 Py_ssize_t n, have, r;
755 PyObject *res = NULL;
756
757 CHECK_INITIALIZED(self)
758 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
759 return NULL;
760 }
761
762 if (n < 0) {
763 PyErr_SetString(PyExc_ValueError,
764 "read length must be positive");
765 return NULL;
766 }
767 if (n == 0)
768 return PyBytes_FromStringAndSize(NULL, 0);
769
770 ENTER_BUFFERED(self)
771
772 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000773 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000774 if (res == NULL)
775 goto end;
776 Py_CLEAR(res);
777 }
778
779 /* Return up to n bytes. If at least one byte is buffered, we
780 only return buffered bytes. Otherwise, we do one raw read. */
781
782 /* XXX: this mimicks the io.py implementation but is probably wrong.
783 If we need to read from the raw stream, then we could actually read
784 all `n` bytes asked by the caller (and possibly more, so as to fill
785 our buffer for the next reads). */
786
787 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
788 if (have > 0) {
789 if (n > have)
790 n = have;
791 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
792 if (res == NULL)
793 goto end;
794 self->pos += n;
795 goto end;
796 }
797
798 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000799 _bufferedreader_reset_buf(self);
800 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000801 if (r == -1)
802 goto end;
803 if (r == -2)
804 r = 0;
805 if (n > r)
806 n = r;
807 res = PyBytes_FromStringAndSize(self->buffer, n);
808 if (res == NULL)
809 goto end;
810 self->pos = n;
811
812end:
813 LEAVE_BUFFERED(self)
814 return res;
815}
816
817static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000818buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000819{
820 PyObject *res = NULL;
821
822 CHECK_INITIALIZED(self)
823
824 /* TODO: use raw.readinto() instead! */
825 if (self->writable) {
826 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000827 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000828 LEAVE_BUFFERED(self)
829 if (res == NULL)
830 goto end;
831 Py_DECREF(res);
832 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000833 res = bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000834
835end:
836 return res;
837}
838
839static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000840_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000841{
842 PyObject *res = NULL;
843 PyObject *chunks = NULL;
844 Py_ssize_t n, written = 0;
845 const char *start, *s, *end;
846
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000847 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000848
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000849 /* First, try to find a line in the buffer. This can run unlocked because
850 the calls to the C API are simple enough that they can't trigger
851 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000852 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
853 if (limit >= 0 && n > limit)
854 n = limit;
855 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000856 s = memchr(start, '\n', n);
857 if (s != NULL) {
858 res = PyBytes_FromStringAndSize(start, s - start + 1);
859 if (res != NULL)
860 self->pos += s - start + 1;
861 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000862 }
863 if (n == limit) {
864 res = PyBytes_FromStringAndSize(start, n);
865 if (res != NULL)
866 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000867 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000868 }
869
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000870 ENTER_BUFFERED(self)
871
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000872 /* Now we try to get some more from the raw stream */
873 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000874 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000875 if (res == NULL)
876 goto end;
877 Py_CLEAR(res);
878 }
879 chunks = PyList_New(0);
880 if (chunks == NULL)
881 goto end;
882 if (n > 0) {
883 res = PyBytes_FromStringAndSize(start, n);
884 if (res == NULL)
885 goto end;
886 if (PyList_Append(chunks, res) < 0) {
887 Py_CLEAR(res);
888 goto end;
889 }
890 Py_CLEAR(res);
891 written += n;
892 if (limit >= 0)
893 limit -= n;
894 }
895
896 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000897 _bufferedreader_reset_buf(self);
898 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000899 if (n == -1)
900 goto end;
901 if (n <= 0)
902 break;
903 if (limit >= 0 && n > limit)
904 n = limit;
905 start = self->buffer;
906 end = start + n;
907 s = start;
908 while (s < end) {
909 if (*s++ == '\n') {
910 res = PyBytes_FromStringAndSize(start, s - start);
911 if (res == NULL)
912 goto end;
913 self->pos = s - start;
914 goto found;
915 }
916 }
917 res = PyBytes_FromStringAndSize(start, n);
918 if (res == NULL)
919 goto end;
920 if (n == limit) {
921 self->pos = n;
922 break;
923 }
924 if (PyList_Append(chunks, res) < 0) {
925 Py_CLEAR(res);
926 goto end;
927 }
928 Py_CLEAR(res);
929 written += n;
930 if (limit >= 0)
931 limit -= n;
932 }
933found:
934 if (res != NULL && PyList_Append(chunks, res) < 0) {
935 Py_CLEAR(res);
936 goto end;
937 }
938 Py_CLEAR(res);
939 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
940
941end:
942 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000943end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000944 Py_XDECREF(chunks);
945 return res;
946}
947
948static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000949buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000950{
951 Py_ssize_t limit = -1;
952
953 CHECK_INITIALIZED(self)
954
955 if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
956 return NULL;
957 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000958 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000959}
960
961
962static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000963buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000964{
965 Py_off_t pos;
966
967 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000968 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000969 if (pos == -1)
970 return NULL;
971 pos -= RAW_OFFSET(self);
972 /* TODO: sanity check (pos >= 0) */
973 return PyLong_FromOff_t(pos);
974}
975
976static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000977buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000978{
979 Py_off_t target, n;
980 int whence = 0;
981 PyObject *targetobj, *res = NULL;
982
983 CHECK_INITIALIZED(self)
984 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
985 return NULL;
986 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000987 if (whence < 0 || whence > 2) {
988 PyErr_Format(PyExc_ValueError,
989 "whence must be between 0 and 2, not %d", whence);
990 return NULL;
991 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000992
993 CHECK_CLOSED(self, "seek of closed file")
994
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000995 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
996 if (target == -1 && PyErr_Occurred())
997 return NULL;
998
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000999 if (whence != 2 && self->readable) {
1000 Py_off_t current, avail;
1001 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001002 so as to return quickly if possible. Also, we needn't take the
1003 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001004 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001005 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1006 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001007 current = RAW_TELL(self);
1008 avail = READAHEAD(self);
1009 if (avail > 0) {
1010 Py_off_t offset;
1011 if (whence == 0)
1012 offset = target - (current - RAW_OFFSET(self));
1013 else
1014 offset = target;
1015 if (offset >= -self->pos && offset <= avail) {
1016 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001017 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001018 }
1019 }
1020 }
1021
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001022 ENTER_BUFFERED(self)
1023
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001024 /* Fallback: invoke raw seek() method and clear buffer */
1025 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001026 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001027 if (res == NULL)
1028 goto end;
1029 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001030 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001031 }
1032
1033 /* TODO: align on block boundary and read buffer if needed? */
1034 if (whence == 1)
1035 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001036 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001037 if (n == -1)
1038 goto end;
1039 self->raw_pos = -1;
1040 res = PyLong_FromOff_t(n);
1041 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001042 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001043
1044end:
1045 LEAVE_BUFFERED(self)
1046 return res;
1047}
1048
1049static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001050buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001051{
1052 PyObject *pos = Py_None;
1053 PyObject *res = NULL;
1054
1055 CHECK_INITIALIZED(self)
1056 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1057 return NULL;
1058 }
1059
1060 ENTER_BUFFERED(self)
1061
1062 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001063 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001064 if (res == NULL)
1065 goto end;
1066 Py_CLEAR(res);
1067 }
1068 if (self->readable) {
1069 if (pos == Py_None) {
1070 /* Rewind the raw stream so that its position corresponds to
1071 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001072 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001073 goto end;
1074 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001075 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001076 }
1077 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1078 if (res == NULL)
1079 goto end;
1080 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001081 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001082 PyErr_Clear();
1083
1084end:
1085 LEAVE_BUFFERED(self)
1086 return res;
1087}
1088
1089static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001090buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001091{
1092 PyObject *line;
1093 PyTypeObject *tp;
1094
1095 CHECK_INITIALIZED(self);
1096
1097 tp = Py_TYPE(self);
1098 if (tp == &PyBufferedReader_Type ||
1099 tp == &PyBufferedRandom_Type) {
1100 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001101 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001102 }
1103 else {
1104 line = PyObject_CallMethodObjArgs((PyObject *)self,
1105 _PyIO_str_readline, NULL);
1106 if (line && !PyBytes_Check(line)) {
1107 PyErr_Format(PyExc_IOError,
1108 "readline() should have returned a bytes object, "
1109 "not '%.200s'", Py_TYPE(line)->tp_name);
1110 Py_DECREF(line);
1111 return NULL;
1112 }
1113 }
1114
1115 if (line == NULL)
1116 return NULL;
1117
1118 if (PyBytes_GET_SIZE(line) == 0) {
1119 /* Reached EOF or would have blocked */
1120 Py_DECREF(line);
1121 return NULL;
1122 }
1123
1124 return line;
1125}
1126
Antoine Pitrou716c4442009-05-23 19:04:03 +00001127static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001128buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001129{
1130 PyObject *nameobj, *res;
1131
1132 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1133 if (nameobj == NULL) {
1134 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1135 PyErr_Clear();
1136 else
1137 return NULL;
1138 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1139 }
1140 else {
1141 res = PyUnicode_FromFormat("<%s name=%R>",
1142 Py_TYPE(self)->tp_name, nameobj);
1143 Py_DECREF(nameobj);
1144 }
1145 return res;
1146}
1147
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001148/*
1149 * class BufferedReader
1150 */
1151
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001152PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001153 "Create a new buffered reader using the given readable raw IO object.");
1154
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001155static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001156{
1157 self->read_end = -1;
1158}
1159
1160static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001161bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001162{
1163 char *kwlist[] = {"raw", "buffer_size", NULL};
1164 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1165 PyObject *raw;
1166
1167 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001168 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001169
1170 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1171 &raw, &buffer_size)) {
1172 return -1;
1173 }
1174
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001175 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001176 return -1;
1177
1178 Py_CLEAR(self->raw);
1179 Py_INCREF(raw);
1180 self->raw = raw;
1181 self->buffer_size = buffer_size;
1182 self->readable = 1;
1183 self->writable = 0;
1184
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001185 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001186 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001187 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001188
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001189 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1190 Py_TYPE(raw) == &PyFileIO_Type);
1191
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001192 self->ok = 1;
1193 return 0;
1194}
1195
1196static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001197_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001198{
1199 Py_buffer buf;
1200 PyObject *memobj, *res;
1201 Py_ssize_t n;
1202 /* NOTE: the buffer needn't be released as its object is NULL. */
1203 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1204 return -1;
1205 memobj = PyMemoryView_FromBuffer(&buf);
1206 if (memobj == NULL)
1207 return -1;
1208 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1209 Py_DECREF(memobj);
1210 if (res == NULL)
1211 return -1;
1212 if (res == Py_None) {
1213 /* Non-blocking stream would have blocked. Special return code! */
1214 Py_DECREF(res);
1215 return -2;
1216 }
1217 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1218 Py_DECREF(res);
1219 if (n < 0 || n > len) {
1220 PyErr_Format(PyExc_IOError,
1221 "raw readinto() returned invalid length %zd "
1222 "(should have been between 0 and %zd)", n, len);
1223 return -1;
1224 }
1225 if (n > 0 && self->abs_pos != -1)
1226 self->abs_pos += n;
1227 return n;
1228}
1229
1230static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001231_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001232{
1233 Py_ssize_t start, len, n;
1234 if (VALID_READ_BUFFER(self))
1235 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1236 else
1237 start = 0;
1238 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001239 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001240 if (n <= 0)
1241 return n;
1242 self->read_end = start + n;
1243 self->raw_pos = start + n;
1244 return n;
1245}
1246
1247static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001248_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001249{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001250 Py_ssize_t current_size;
1251 PyObject *res, *data = NULL;
1252 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001253
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001254 if (chunks == NULL)
1255 return NULL;
1256
1257 /* First copy what we have in the current buffer. */
1258 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1259 if (current_size) {
1260 data = PyBytes_FromStringAndSize(
1261 self->buffer + self->pos, current_size);
1262 if (data == NULL) {
1263 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001264 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001265 }
1266 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001267 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001268 /* We're going past the buffer's bounds, flush it */
1269 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001270 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001271 if (res == NULL) {
1272 Py_DECREF(chunks);
1273 return NULL;
1274 }
1275 Py_CLEAR(res);
1276 }
1277 while (1) {
1278 if (data) {
1279 if (PyList_Append(chunks, data) < 0) {
1280 Py_DECREF(data);
1281 Py_DECREF(chunks);
1282 return NULL;
1283 }
1284 Py_DECREF(data);
1285 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001286
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001287 /* Read until EOF or until read() would block. */
1288 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1289 if (data == NULL) {
1290 Py_DECREF(chunks);
1291 return NULL;
1292 }
1293 if (data != Py_None && !PyBytes_Check(data)) {
1294 Py_DECREF(data);
1295 Py_DECREF(chunks);
1296 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1297 return NULL;
1298 }
1299 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1300 if (current_size == 0) {
1301 Py_DECREF(chunks);
1302 return data;
1303 }
1304 else {
1305 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1306 Py_DECREF(data);
1307 Py_DECREF(chunks);
1308 return res;
1309 }
1310 }
1311 current_size += PyBytes_GET_SIZE(data);
1312 if (self->abs_pos != -1)
1313 self->abs_pos += PyBytes_GET_SIZE(data);
1314 }
1315}
1316
1317/* Read n bytes from the buffer if it can, otherwise return None.
1318 This function is simple enough that it can run unlocked. */
1319static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001320_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001321{
1322 Py_ssize_t current_size;
1323
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001324 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1325 if (n <= current_size) {
1326 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001327 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1328 if (res != NULL)
1329 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001330 return res;
1331 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001332 Py_RETURN_NONE;
1333}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001334
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001335/* Generic read function: read from the stream until enough bytes are read,
1336 * or until an EOF occurs or until read() would block.
1337 */
1338static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001339_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001340{
1341 PyObject *res = NULL;
1342 Py_ssize_t current_size, remaining, written;
1343 char *out;
1344
1345 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1346 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001347 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001348
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001349 res = PyBytes_FromStringAndSize(NULL, n);
1350 if (res == NULL)
1351 goto error;
1352 out = PyBytes_AS_STRING(res);
1353 remaining = n;
1354 written = 0;
1355 if (current_size > 0) {
1356 memcpy(out, self->buffer + self->pos, current_size);
1357 remaining -= current_size;
1358 written += current_size;
1359 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001360 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001361 while (remaining > 0) {
1362 /* We want to read a whole block at the end into buffer.
1363 If we had readv() we could do this in one pass. */
1364 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1365 if (r == 0)
1366 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001367 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001368 if (r == -1)
1369 goto error;
1370 if (r == 0 || r == -2) {
1371 /* EOF occurred or read() would block. */
1372 if (r == 0 || written > 0) {
1373 if (_PyBytes_Resize(&res, written))
1374 goto error;
1375 return res;
1376 }
1377 Py_DECREF(res);
1378 Py_INCREF(Py_None);
1379 return Py_None;
1380 }
1381 remaining -= r;
1382 written += r;
1383 }
1384 assert(remaining <= self->buffer_size);
1385 self->pos = 0;
1386 self->raw_pos = 0;
1387 self->read_end = 0;
1388 while (self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001389 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001390 if (r == -1)
1391 goto error;
1392 if (r == 0 || r == -2) {
1393 /* EOF occurred or read() would block. */
1394 if (r == 0 || written > 0) {
1395 if (_PyBytes_Resize(&res, written))
1396 goto error;
1397 return res;
1398 }
1399 Py_DECREF(res);
1400 Py_INCREF(Py_None);
1401 return Py_None;
1402 }
1403 if (remaining > r) {
1404 memcpy(out + written, self->buffer + self->pos, r);
1405 written += r;
1406 self->pos += r;
1407 remaining -= r;
1408 }
1409 else if (remaining > 0) {
1410 memcpy(out + written, self->buffer + self->pos, remaining);
1411 written += remaining;
1412 self->pos += remaining;
1413 remaining = 0;
1414 }
1415 if (remaining == 0)
1416 break;
1417 }
1418
1419 return res;
1420
1421error:
1422 Py_XDECREF(res);
1423 return NULL;
1424}
1425
1426static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001427_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001428{
1429 Py_ssize_t have, r;
1430
1431 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1432 /* Constraints:
1433 1. we don't want to advance the file position.
1434 2. we don't want to lose block alignment, so we can't shift the buffer
1435 to make some place.
1436 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1437 */
1438 if (have > 0) {
1439 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1440 }
1441
1442 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001443 _bufferedreader_reset_buf(self);
1444 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001445 if (r == -1)
1446 return NULL;
1447 if (r == -2)
1448 r = 0;
1449 self->pos = 0;
1450 return PyBytes_FromStringAndSize(self->buffer, r);
1451}
1452
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001453static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001454 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001455 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1456 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1457 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1458 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1459 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1460 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1461 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1462 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001463
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001464 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1465 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1466 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1467 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1468 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1469 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1470 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001471 {NULL, NULL}
1472};
1473
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001474static PyMemberDef bufferedreader_members[] = {
1475 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001476 {NULL}
1477};
1478
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001479static PyGetSetDef bufferedreader_getset[] = {
1480 {"closed", (getter)buffered_closed_get, NULL, NULL},
1481 {"name", (getter)buffered_name_get, NULL, NULL},
1482 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001483 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001484};
1485
1486
1487PyTypeObject PyBufferedReader_Type = {
1488 PyVarObject_HEAD_INIT(NULL, 0)
1489 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001490 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001491 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001492 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001493 0, /*tp_print*/
1494 0, /*tp_getattr*/
1495 0, /*tp_setattr*/
1496 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001497 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001498 0, /*tp_as_number*/
1499 0, /*tp_as_sequence*/
1500 0, /*tp_as_mapping*/
1501 0, /*tp_hash */
1502 0, /*tp_call*/
1503 0, /*tp_str*/
1504 0, /*tp_getattro*/
1505 0, /*tp_setattro*/
1506 0, /*tp_as_buffer*/
1507 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1508 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001509 bufferedreader_doc, /* tp_doc */
1510 (traverseproc)buffered_traverse, /* tp_traverse */
1511 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001512 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001513 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001514 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001515 (iternextfunc)buffered_iternext, /* tp_iternext */
1516 bufferedreader_methods, /* tp_methods */
1517 bufferedreader_members, /* tp_members */
1518 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001519 0, /* tp_base */
1520 0, /* tp_dict */
1521 0, /* tp_descr_get */
1522 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001523 offsetof(buffered, dict), /* tp_dictoffset */
1524 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001525 0, /* tp_alloc */
1526 PyType_GenericNew, /* tp_new */
1527};
1528
1529
Benjamin Peterson59406a92009-03-26 17:10:29 +00001530
1531static int
1532complain_about_max_buffer_size(void)
1533{
1534 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1535 "max_buffer_size is deprecated", 1) < 0)
1536 return 0;
1537 return 1;
1538}
1539
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001540/*
1541 * class BufferedWriter
1542 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001543PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001544 "A buffer for a writeable sequential RawIO object.\n"
1545 "\n"
1546 "The constructor creates a BufferedWriter for the given writeable raw\n"
1547 "stream. If the buffer_size is not given, it defaults to\n"
1548 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1549 );
1550
1551static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001552_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001553{
1554 self->write_pos = 0;
1555 self->write_end = -1;
1556}
1557
1558static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001559bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001560{
1561 /* TODO: properly deprecate max_buffer_size */
1562 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1563 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001564 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001565 PyObject *raw;
1566
1567 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001568 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001569
1570 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1571 &raw, &buffer_size, &max_buffer_size)) {
1572 return -1;
1573 }
1574
Benjamin Peterson59406a92009-03-26 17:10:29 +00001575 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1576 return -1;
1577
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001578 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001579 return -1;
1580
1581 Py_CLEAR(self->raw);
1582 Py_INCREF(raw);
1583 self->raw = raw;
1584 self->readable = 0;
1585 self->writable = 1;
1586
1587 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001588 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001589 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001590 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001591 self->pos = 0;
1592
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001593 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1594 Py_TYPE(raw) == &PyFileIO_Type);
1595
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001596 self->ok = 1;
1597 return 0;
1598}
1599
1600static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001601_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001602{
1603 Py_buffer buf;
1604 PyObject *memobj, *res;
1605 Py_ssize_t n;
1606 /* NOTE: the buffer needn't be released as its object is NULL. */
1607 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1608 return -1;
1609 memobj = PyMemoryView_FromBuffer(&buf);
1610 if (memobj == NULL)
1611 return -1;
1612 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1613 Py_DECREF(memobj);
1614 if (res == NULL)
1615 return -1;
1616 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1617 Py_DECREF(res);
1618 if (n < 0 || n > len) {
1619 PyErr_Format(PyExc_IOError,
1620 "raw write() returned invalid length %zd "
1621 "(should have been between 0 and %zd)", n, len);
1622 return -1;
1623 }
1624 if (n > 0 && self->abs_pos != -1)
1625 self->abs_pos += n;
1626 return n;
1627}
1628
1629/* `restore_pos` is 1 if we need to restore the raw stream position at
1630 the end, 0 otherwise. */
1631static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001632_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001633{
1634 Py_ssize_t written = 0;
1635 Py_off_t n, rewind;
1636
1637 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1638 goto end;
1639 /* First, rewind */
1640 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1641 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001642 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001643 if (n < 0) {
1644 goto error;
1645 }
1646 self->raw_pos -= rewind;
1647 }
1648 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001649 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001650 self->buffer + self->write_pos,
1651 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1652 Py_off_t, Py_ssize_t));
1653 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001654 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001655 if (w == NULL)
1656 goto error;
1657 self->write_pos += *w;
1658 self->raw_pos = self->write_pos;
1659 written += *w;
1660 *w = written;
1661 /* Already re-raised */
1662 goto error;
1663 }
1664 self->write_pos += n;
1665 self->raw_pos = self->write_pos;
1666 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1667 }
1668
1669 if (restore_pos) {
1670 Py_off_t forward = rewind - written;
1671 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001672 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001673 if (n < 0) {
1674 goto error;
1675 }
1676 self->raw_pos += forward;
1677 }
1678 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001679 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001680
1681end:
1682 Py_RETURN_NONE;
1683
1684error:
1685 return NULL;
1686}
1687
1688static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001689bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001690{
1691 PyObject *res = NULL;
1692 Py_buffer buf;
1693 Py_ssize_t written, avail, remaining, n;
1694
1695 CHECK_INITIALIZED(self)
1696 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1697 return NULL;
1698 }
1699
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001700 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001701 PyErr_SetString(PyExc_ValueError, "write to closed file");
1702 PyBuffer_Release(&buf);
1703 return NULL;
1704 }
1705
1706 ENTER_BUFFERED(self)
1707
1708 /* Fast path: the data to write can be fully buffered. */
1709 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1710 self->pos = 0;
1711 self->raw_pos = 0;
1712 }
1713 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1714 if (buf.len <= avail) {
1715 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1716 if (!VALID_WRITE_BUFFER(self)) {
1717 self->write_pos = self->pos;
1718 }
1719 ADJUST_POSITION(self, self->pos + buf.len);
1720 if (self->pos > self->write_end)
1721 self->write_end = self->pos;
1722 written = buf.len;
1723 goto end;
1724 }
1725
1726 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001727 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001728 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001729 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001730 if (w == NULL)
1731 goto error;
1732 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001733 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001734 /* Make some place by shifting the buffer. */
1735 assert(VALID_WRITE_BUFFER(self));
1736 memmove(self->buffer, self->buffer + self->write_pos,
1737 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1738 Py_off_t, Py_ssize_t));
1739 self->write_end -= self->write_pos;
1740 self->raw_pos -= self->write_pos;
1741 self->pos -= self->write_pos;
1742 self->write_pos = 0;
1743 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1744 Py_off_t, Py_ssize_t);
1745 if (buf.len <= avail) {
1746 /* Everything can be buffered */
1747 PyErr_Clear();
1748 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1749 self->write_end += buf.len;
1750 written = buf.len;
1751 goto end;
1752 }
1753 /* Buffer as much as possible. */
1754 memcpy(self->buffer + self->write_end, buf.buf, avail);
1755 self->write_end += avail;
1756 /* Already re-raised */
1757 *w = avail;
1758 goto error;
1759 }
1760 Py_CLEAR(res);
1761
Antoine Pitrou0473e562009-08-06 20:52:43 +00001762 /* Adjust the raw stream position if it is away from the logical stream
1763 position. This happens if the read buffer has been filled but not
1764 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1765 the raw stream by itself).
1766 Fixes issue #6629.
1767 */
1768 n = RAW_OFFSET(self);
1769 if (n != 0) {
1770 if (_buffered_raw_seek(self, -n, 1) < 0)
1771 goto error;
1772 self->raw_pos -= n;
1773 }
1774
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001775 /* Then write buf itself. At this point the buffer has been emptied. */
1776 remaining = buf.len;
1777 written = 0;
1778 while (remaining > self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001779 n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001780 self, (char *) buf.buf + written, buf.len - written);
1781 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001782 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001783 if (w == NULL)
1784 goto error;
1785 written += *w;
1786 remaining -= *w;
1787 if (remaining > self->buffer_size) {
1788 /* Can't buffer everything, still buffer as much as possible */
1789 memcpy(self->buffer,
1790 (char *) buf.buf + written, self->buffer_size);
1791 self->raw_pos = 0;
1792 ADJUST_POSITION(self, self->buffer_size);
1793 self->write_end = self->buffer_size;
1794 *w = written + self->buffer_size;
1795 /* Already re-raised */
1796 goto error;
1797 }
1798 PyErr_Clear();
1799 break;
1800 }
1801 written += n;
1802 remaining -= n;
1803 }
1804 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001805 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001806 if (remaining > 0) {
1807 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1808 written += remaining;
1809 }
1810 self->write_pos = 0;
1811 /* TODO: sanity check (remaining >= 0) */
1812 self->write_end = remaining;
1813 ADJUST_POSITION(self, remaining);
1814 self->raw_pos = 0;
1815
1816end:
1817 res = PyLong_FromSsize_t(written);
1818
1819error:
1820 LEAVE_BUFFERED(self)
1821 PyBuffer_Release(&buf);
1822 return res;
1823}
1824
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001825static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001826 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001827 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1828 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1829 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1830 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1831 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1832 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1833 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001834
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001835 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1836 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1837 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1838 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1839 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001840 {NULL, NULL}
1841};
1842
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001843static PyMemberDef bufferedwriter_members[] = {
1844 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001845 {NULL}
1846};
1847
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001848static PyGetSetDef bufferedwriter_getset[] = {
1849 {"closed", (getter)buffered_closed_get, NULL, NULL},
1850 {"name", (getter)buffered_name_get, NULL, NULL},
1851 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001852 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001853};
1854
1855
1856PyTypeObject PyBufferedWriter_Type = {
1857 PyVarObject_HEAD_INIT(NULL, 0)
1858 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001859 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001860 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001861 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001862 0, /*tp_print*/
1863 0, /*tp_getattr*/
1864 0, /*tp_setattr*/
1865 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001866 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001867 0, /*tp_as_number*/
1868 0, /*tp_as_sequence*/
1869 0, /*tp_as_mapping*/
1870 0, /*tp_hash */
1871 0, /*tp_call*/
1872 0, /*tp_str*/
1873 0, /*tp_getattro*/
1874 0, /*tp_setattro*/
1875 0, /*tp_as_buffer*/
1876 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1877 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001878 bufferedwriter_doc, /* tp_doc */
1879 (traverseproc)buffered_traverse, /* tp_traverse */
1880 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001881 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001882 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001883 0, /* tp_iter */
1884 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001885 bufferedwriter_methods, /* tp_methods */
1886 bufferedwriter_members, /* tp_members */
1887 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001888 0, /* tp_base */
1889 0, /* tp_dict */
1890 0, /* tp_descr_get */
1891 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001892 offsetof(buffered, dict), /* tp_dictoffset */
1893 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001894 0, /* tp_alloc */
1895 PyType_GenericNew, /* tp_new */
1896};
1897
1898
1899
1900/*
1901 * BufferedRWPair
1902 */
1903
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001904PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001905 "A buffered reader and writer object together.\n"
1906 "\n"
1907 "A buffered reader object and buffered writer object put together to\n"
1908 "form a sequential IO object that can read and write. This is typically\n"
1909 "used with a socket or two-way pipe.\n"
1910 "\n"
1911 "reader and writer are RawIOBase objects that are readable and\n"
1912 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001913 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001914 );
1915
1916/* XXX The usefulness of this (compared to having two separate IO objects) is
1917 * questionable.
1918 */
1919
1920typedef struct {
1921 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001922 buffered *reader;
1923 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001924 PyObject *dict;
1925 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001926} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001927
1928static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001929bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001930{
1931 PyObject *reader, *writer;
1932 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001933 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001934
1935 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1936 &buffer_size, &max_buffer_size)) {
1937 return -1;
1938 }
1939
Benjamin Peterson59406a92009-03-26 17:10:29 +00001940 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1941 return -1;
1942
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001943 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001944 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001945 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001946 return -1;
1947
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001948 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001949 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001950 if (self->reader == NULL)
1951 return -1;
1952
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001953 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001954 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001955 if (self->writer == NULL) {
1956 Py_CLEAR(self->reader);
1957 return -1;
1958 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001959
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001960 return 0;
1961}
1962
1963static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001964bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001965{
1966 Py_VISIT(self->dict);
1967 return 0;
1968}
1969
1970static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001971bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001972{
1973 Py_CLEAR(self->reader);
1974 Py_CLEAR(self->writer);
1975 Py_CLEAR(self->dict);
1976 return 0;
1977}
1978
1979static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001980bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001981{
1982 _PyObject_GC_UNTRACK(self);
1983 Py_CLEAR(self->reader);
1984 Py_CLEAR(self->writer);
1985 Py_CLEAR(self->dict);
1986 Py_TYPE(self)->tp_free((PyObject *) self);
1987}
1988
1989static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001990_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001991{
1992 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1993 PyObject *ret;
1994
1995 if (func == NULL) {
1996 PyErr_SetString(PyExc_AttributeError, name);
1997 return NULL;
1998 }
1999
2000 ret = PyObject_CallObject(func, args);
2001 Py_DECREF(func);
2002 return ret;
2003}
2004
2005static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002006bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002007{
2008 return _forward_call(self->reader, "read", args);
2009}
2010
2011static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002012bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002013{
2014 return _forward_call(self->reader, "peek", args);
2015}
2016
2017static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002018bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002019{
2020 return _forward_call(self->reader, "read1", args);
2021}
2022
2023static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002024bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002025{
2026 return _forward_call(self->reader, "readinto", args);
2027}
2028
2029static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002030bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002031{
2032 return _forward_call(self->writer, "write", args);
2033}
2034
2035static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002036bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002037{
2038 return _forward_call(self->writer, "flush", args);
2039}
2040
2041static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002042bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002043{
2044 return _forward_call(self->reader, "readable", args);
2045}
2046
2047static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002048bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002049{
2050 return _forward_call(self->writer, "writable", args);
2051}
2052
2053static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002054bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002055{
2056 PyObject *ret = _forward_call(self->writer, "close", args);
2057 if (ret == NULL)
2058 return NULL;
2059 Py_DECREF(ret);
2060
2061 return _forward_call(self->reader, "close", args);
2062}
2063
2064static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002065bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002066{
2067 PyObject *ret = _forward_call(self->writer, "isatty", args);
2068
2069 if (ret != Py_False) {
2070 /* either True or exception */
2071 return ret;
2072 }
2073 Py_DECREF(ret);
2074
2075 return _forward_call(self->reader, "isatty", args);
2076}
2077
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002078static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002079bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002080{
2081 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2082}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002083
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002084static PyMethodDef bufferedrwpair_methods[] = {
2085 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2086 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2087 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2088 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002089
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002090 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2091 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002092
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002093 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2094 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002095
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002096 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2097 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002098
2099 {NULL, NULL}
2100};
2101
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002102static PyGetSetDef bufferedrwpair_getset[] = {
2103 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002104 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002105};
2106
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002107PyTypeObject PyBufferedRWPair_Type = {
2108 PyVarObject_HEAD_INIT(NULL, 0)
2109 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002110 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002111 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002112 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002113 0, /*tp_print*/
2114 0, /*tp_getattr*/
2115 0, /*tp_setattr*/
2116 0, /*tp_compare */
2117 0, /*tp_repr*/
2118 0, /*tp_as_number*/
2119 0, /*tp_as_sequence*/
2120 0, /*tp_as_mapping*/
2121 0, /*tp_hash */
2122 0, /*tp_call*/
2123 0, /*tp_str*/
2124 0, /*tp_getattro*/
2125 0, /*tp_setattro*/
2126 0, /*tp_as_buffer*/
2127 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2128 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002129 bufferedrwpair_doc, /* tp_doc */
2130 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2131 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002132 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002133 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002134 0, /* tp_iter */
2135 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002136 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002137 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002138 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002139 0, /* tp_base */
2140 0, /* tp_dict */
2141 0, /* tp_descr_get */
2142 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002143 offsetof(rwpair, dict), /* tp_dictoffset */
2144 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002145 0, /* tp_alloc */
2146 PyType_GenericNew, /* tp_new */
2147};
2148
2149
2150
2151/*
2152 * BufferedRandom
2153 */
2154
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002155PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002156 "A buffered interface to random access streams.\n"
2157 "\n"
2158 "The constructor creates a reader and writer for a seekable stream,\n"
2159 "raw, given in the first argument. If the buffer_size is omitted it\n"
2160 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2161 );
2162
2163static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002164bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002165{
2166 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2167 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002168 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002169 PyObject *raw;
2170
2171 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002172 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002173
2174 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2175 &raw, &buffer_size, &max_buffer_size)) {
2176 return -1;
2177 }
2178
Benjamin Peterson59406a92009-03-26 17:10:29 +00002179 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2180 return -1;
2181
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002182 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002183 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002184 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002185 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002186 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002187 return -1;
2188
2189 Py_CLEAR(self->raw);
2190 Py_INCREF(raw);
2191 self->raw = raw;
2192 self->buffer_size = buffer_size;
2193 self->readable = 1;
2194 self->writable = 1;
2195
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002196 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002197 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002198 _bufferedreader_reset_buf(self);
2199 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002200 self->pos = 0;
2201
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002202 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2203 Py_TYPE(raw) == &PyFileIO_Type);
2204
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002205 self->ok = 1;
2206 return 0;
2207}
2208
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002209static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002210 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002211 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2212 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2213 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2214 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2215 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2216 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2217 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002218
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002219 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002220
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002221 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2222 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2223 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2224 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2225 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2226 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2227 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2228 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2229 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002230 {NULL, NULL}
2231};
2232
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002233static PyMemberDef bufferedrandom_members[] = {
2234 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002235 {NULL}
2236};
2237
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002238static PyGetSetDef bufferedrandom_getset[] = {
2239 {"closed", (getter)buffered_closed_get, NULL, NULL},
2240 {"name", (getter)buffered_name_get, NULL, NULL},
2241 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002242 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002243};
2244
2245
2246PyTypeObject PyBufferedRandom_Type = {
2247 PyVarObject_HEAD_INIT(NULL, 0)
2248 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002249 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002250 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002251 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002252 0, /*tp_print*/
2253 0, /*tp_getattr*/
2254 0, /*tp_setattr*/
2255 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002256 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002257 0, /*tp_as_number*/
2258 0, /*tp_as_sequence*/
2259 0, /*tp_as_mapping*/
2260 0, /*tp_hash */
2261 0, /*tp_call*/
2262 0, /*tp_str*/
2263 0, /*tp_getattro*/
2264 0, /*tp_setattro*/
2265 0, /*tp_as_buffer*/
2266 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2267 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002268 bufferedrandom_doc, /* tp_doc */
2269 (traverseproc)buffered_traverse, /* tp_traverse */
2270 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002271 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002272 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002273 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002274 (iternextfunc)buffered_iternext, /* tp_iternext */
2275 bufferedrandom_methods, /* tp_methods */
2276 bufferedrandom_members, /* tp_members */
2277 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002278 0, /* tp_base */
2279 0, /*tp_dict*/
2280 0, /* tp_descr_get */
2281 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002282 offsetof(buffered, dict), /*tp_dictoffset*/
2283 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002284 0, /* tp_alloc */
2285 PyType_GenericNew, /* tp_new */
2286};
2287