blob: b21ea718130e12cc20ace0f3119c2c8048a06d7e [file] [log] [blame]
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001/*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
3
4 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
6
7 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8*/
9
10#define PY_SSIZE_T_CLEAN
11#include "Python.h"
12#include "structmember.h"
13#include "pythread.h"
14#include "_iomodule.h"
15
16/*
17 * BufferedIOBase class, inherits from IOBase.
18 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000019PyDoc_STRVAR(bufferediobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000020 "Base class for buffered IO objects.\n"
21 "\n"
22 "The main difference with RawIOBase is that the read() method\n"
23 "supports omitting the size argument, and does not have a default\n"
24 "implementation that defers to readinto().\n"
25 "\n"
26 "In addition, read(), readinto() and write() may raise\n"
27 "BlockingIOError if the underlying raw stream is in non-blocking\n"
28 "mode and not ready; unlike their raw counterparts, they will never\n"
29 "return None.\n"
30 "\n"
31 "A typical implementation should not inherit from a RawIOBase\n"
32 "implementation, but wrap one.\n"
33 );
34
35static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000036bufferediobase_readinto(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000037{
38 Py_buffer buf;
39 Py_ssize_t len;
40 PyObject *data;
41
42 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
43 return NULL;
44 }
45
46 data = PyObject_CallMethod(self, "read", "n", buf.len);
47 if (data == NULL)
48 goto error;
49
50 if (!PyBytes_Check(data)) {
51 Py_DECREF(data);
52 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
53 goto error;
54 }
55
56 len = Py_SIZE(data);
57 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
58
59 PyBuffer_Release(&buf);
60 Py_DECREF(data);
61
62 return PyLong_FromSsize_t(len);
63
64 error:
65 PyBuffer_Release(&buf);
66 return NULL;
67}
68
69static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000070bufferediobase_unsupported(const char *message)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000071{
72 PyErr_SetString(IO_STATE->unsupported_operation, message);
73 return NULL;
74}
75
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000076PyDoc_STRVAR(bufferediobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +000077 "Disconnect this buffer from its underlying raw stream and return it.\n"
78 "\n"
79 "After the raw stream has been detached, the buffer is in an unusable\n"
80 "state.\n");
81
82static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000083bufferediobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +000084{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000085 return bufferediobase_unsupported("detach");
Benjamin Petersond2e0c792009-05-01 20:40:59 +000086}
87
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000088PyDoc_STRVAR(bufferediobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000089 "Read and return up to n bytes.\n"
90 "\n"
91 "If the argument is omitted, None, or negative, reads and\n"
92 "returns all data until EOF.\n"
93 "\n"
94 "If the argument is positive, and the underlying raw stream is\n"
95 "not 'interactive', multiple raw reads may be issued to satisfy\n"
96 "the byte count (unless EOF is reached first). But for\n"
97 "interactive raw streams (as well as sockets and pipes), at most\n"
98 "one raw read will be issued, and a short result does not imply\n"
99 "that EOF is imminent.\n"
100 "\n"
101 "Returns an empty bytes object on EOF.\n"
102 "\n"
103 "Returns None if the underlying raw stream was open in non-blocking\n"
104 "mode and no data is available at the moment.\n");
105
106static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000107bufferediobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000108{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000109 return bufferediobase_unsupported("read");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000110}
111
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000112PyDoc_STRVAR(bufferediobase_read1_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000113 "Read and return up to n bytes, with at most one read() call\n"
114 "to the underlying raw stream. A short result does not imply\n"
115 "that EOF is imminent.\n"
116 "\n"
117 "Returns an empty bytes object on EOF.\n");
118
119static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000120bufferediobase_read1(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000121{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000122 return bufferediobase_unsupported("read1");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000123}
124
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000125PyDoc_STRVAR(bufferediobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000126 "Write the given buffer to the IO stream.\n"
127 "\n"
128 "Returns the number of bytes written, which is never less than\n"
129 "len(b).\n"
130 "\n"
131 "Raises BlockingIOError if the buffer is full and the\n"
132 "underlying raw stream cannot accept more data at the moment.\n");
133
134static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000135bufferediobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000136{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000137 return bufferediobase_unsupported("write");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000138}
139
140
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000141static PyMethodDef bufferediobase_methods[] = {
142 {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
143 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
144 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
145 {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
146 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000147 {NULL, NULL}
148};
149
150PyTypeObject PyBufferedIOBase_Type = {
151 PyVarObject_HEAD_INIT(NULL, 0)
152 "_io._BufferedIOBase", /*tp_name*/
153 0, /*tp_basicsize*/
154 0, /*tp_itemsize*/
155 0, /*tp_dealloc*/
156 0, /*tp_print*/
157 0, /*tp_getattr*/
158 0, /*tp_setattr*/
159 0, /*tp_compare */
160 0, /*tp_repr*/
161 0, /*tp_as_number*/
162 0, /*tp_as_sequence*/
163 0, /*tp_as_mapping*/
164 0, /*tp_hash */
165 0, /*tp_call*/
166 0, /*tp_str*/
167 0, /*tp_getattro*/
168 0, /*tp_setattro*/
169 0, /*tp_as_buffer*/
170 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000171 bufferediobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000172 0, /* tp_traverse */
173 0, /* tp_clear */
174 0, /* tp_richcompare */
175 0, /* tp_weaklistoffset */
176 0, /* tp_iter */
177 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000178 bufferediobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000179 0, /* tp_members */
180 0, /* tp_getset */
181 &PyIOBase_Type, /* tp_base */
182 0, /* tp_dict */
183 0, /* tp_descr_get */
184 0, /* tp_descr_set */
185 0, /* tp_dictoffset */
186 0, /* tp_init */
187 0, /* tp_alloc */
188 0, /* tp_new */
189};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000190
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000191
192typedef struct {
193 PyObject_HEAD
194
195 PyObject *raw;
196 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000197 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000198 int readable;
199 int writable;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000200
201 /* True if this is a vanilla Buffered object (rather than a user derived
202 class) *and* the raw stream is a vanilla FileIO object. */
203 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000204
205 /* Absolute position inside the raw stream (-1 if unknown). */
206 Py_off_t abs_pos;
207
208 /* A static buffer of size `buffer_size` */
209 char *buffer;
210 /* Current logical position in the buffer. */
211 Py_off_t pos;
212 /* Position of the raw stream in the buffer. */
213 Py_off_t raw_pos;
214
215 /* Just after the last buffered byte in the buffer, or -1 if the buffer
216 isn't ready for reading. */
217 Py_off_t read_end;
218
219 /* Just after the last byte actually written */
220 Py_off_t write_pos;
221 /* Just after the last byte waiting to be written, or -1 if the buffer
222 isn't ready for writing. */
223 Py_off_t write_end;
224
Georg Brandldfd73442009-04-05 11:47:34 +0000225#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000226 PyThread_type_lock lock;
Georg Brandldfd73442009-04-05 11:47:34 +0000227#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000228
229 Py_ssize_t buffer_size;
230 Py_ssize_t buffer_mask;
231
232 PyObject *dict;
233 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000234} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000235
236/*
237 Implementation notes:
238
239 * BufferedReader, BufferedWriter and BufferedRandom try to share most
240 methods (this is helped by the members `readable` and `writable`, which
241 are initialized in the respective constructors)
242 * They also share a single buffer for reading and writing. This enables
243 interleaved reads and writes without flushing. It also makes the logic
244 a bit trickier to get right.
245 * The absolute position of the raw stream is cached, if possible, in the
246 `abs_pos` member. It must be updated every time an operation is done
247 on the raw stream. If not sure, it can be reinitialized by calling
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000248 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000249 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000250 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
251 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000252
253 NOTE: we should try to maintain block alignment of reads and writes to the
254 raw stream (according to the buffer size), but for now it is only done
255 in read() and friends.
256
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000257*/
258
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000259/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000260
Georg Brandldfd73442009-04-05 11:47:34 +0000261#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000262#define ENTER_BUFFERED(self) \
263 Py_BEGIN_ALLOW_THREADS \
264 PyThread_acquire_lock(self->lock, 1); \
265 Py_END_ALLOW_THREADS
266
267#define LEAVE_BUFFERED(self) \
268 PyThread_release_lock(self->lock);
Georg Brandldfd73442009-04-05 11:47:34 +0000269#else
270#define ENTER_BUFFERED(self)
271#define LEAVE_BUFFERED(self)
272#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000273
274#define CHECK_INITIALIZED(self) \
275 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000276 if (self->detached) { \
277 PyErr_SetString(PyExc_ValueError, \
278 "raw stream has been detached"); \
279 } else { \
280 PyErr_SetString(PyExc_ValueError, \
281 "I/O operation on uninitialized object"); \
282 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000283 return NULL; \
284 }
285
286#define CHECK_INITIALIZED_INT(self) \
287 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000288 if (self->detached) { \
289 PyErr_SetString(PyExc_ValueError, \
290 "raw stream has been detached"); \
291 } else { \
292 PyErr_SetString(PyExc_ValueError, \
293 "I/O operation on uninitialized object"); \
294 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000295 return -1; \
296 }
297
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000298#define IS_CLOSED(self) \
299 (self->fast_closed_checks \
300 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000301 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000302
303#define CHECK_CLOSED(self, error_msg) \
304 if (IS_CLOSED(self)) { \
305 PyErr_SetString(PyExc_ValueError, error_msg); \
306 return NULL; \
307 }
308
309
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000310#define VALID_READ_BUFFER(self) \
311 (self->readable && self->read_end != -1)
312
313#define VALID_WRITE_BUFFER(self) \
314 (self->writable && self->write_end != -1)
315
316#define ADJUST_POSITION(self, _new_pos) \
317 do { \
318 self->pos = _new_pos; \
319 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
320 self->read_end = self->pos; \
321 } while(0)
322
323#define READAHEAD(self) \
324 ((self->readable && VALID_READ_BUFFER(self)) \
325 ? (self->read_end - self->pos) : 0)
326
327#define RAW_OFFSET(self) \
328 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
329 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
330
331#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000332 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000333
334#define MINUS_LAST_BLOCK(self, size) \
335 (self->buffer_mask ? \
336 (size & ~self->buffer_mask) : \
337 (self->buffer_size * (size / self->buffer_size)))
338
339
340static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000341buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000342{
343 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
344 return;
345 _PyObject_GC_UNTRACK(self);
346 self->ok = 0;
347 if (self->weakreflist != NULL)
348 PyObject_ClearWeakRefs((PyObject *)self);
349 Py_CLEAR(self->raw);
350 if (self->buffer) {
351 PyMem_Free(self->buffer);
352 self->buffer = NULL;
353 }
Georg Brandldfd73442009-04-05 11:47:34 +0000354#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000355 if (self->lock) {
356 PyThread_free_lock(self->lock);
357 self->lock = NULL;
358 }
Georg Brandldfd73442009-04-05 11:47:34 +0000359#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000360 Py_CLEAR(self->dict);
361 Py_TYPE(self)->tp_free((PyObject *)self);
362}
363
364static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000365buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000366{
367 Py_VISIT(self->raw);
368 Py_VISIT(self->dict);
369 return 0;
370}
371
372static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000373buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000374{
375 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
376 return -1;
377 self->ok = 0;
378 Py_CLEAR(self->raw);
379 Py_CLEAR(self->dict);
380 return 0;
381}
382
383/*
384 * _BufferedIOMixin methods
385 * This is not a class, just a collection of methods that will be reused
386 * by BufferedReader and BufferedWriter
387 */
388
389/* Flush and close */
390
391static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000392buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000393{
394 CHECK_INITIALIZED(self)
395 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
396}
397
398static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000399buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000400{
401 int closed;
402 PyObject *res;
403 CHECK_INITIALIZED_INT(self)
404 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
405 if (res == NULL)
406 return -1;
407 closed = PyObject_IsTrue(res);
408 Py_DECREF(res);
409 return closed;
410}
411
412static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000413buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000414{
415 CHECK_INITIALIZED(self)
416 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
417}
418
419static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000420buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000421{
422 PyObject *res = NULL;
423 int r;
424
425 CHECK_INITIALIZED(self)
426 ENTER_BUFFERED(self)
427
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000428 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000429 if (r < 0)
430 goto end;
431 if (r > 0) {
432 res = Py_None;
433 Py_INCREF(res);
434 goto end;
435 }
436 /* flush() will most probably re-take the lock, so drop it first */
437 LEAVE_BUFFERED(self)
438 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
439 ENTER_BUFFERED(self)
440 if (res == NULL) {
Antoine Pitroufaf90072010-05-03 16:58:19 +0000441 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000442 }
443 Py_XDECREF(res);
444
445 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
446
447end:
448 LEAVE_BUFFERED(self)
449 return res;
450}
451
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000452/* detach */
453
454static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000455buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000456{
457 PyObject *raw, *res;
458 CHECK_INITIALIZED(self)
459 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
460 if (res == NULL)
461 return NULL;
462 Py_DECREF(res);
463 raw = self->raw;
464 self->raw = NULL;
465 self->detached = 1;
466 self->ok = 0;
467 return raw;
468}
469
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000470/* Inquiries */
471
472static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000473buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000474{
475 CHECK_INITIALIZED(self)
476 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
477}
478
479static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000480buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000481{
482 CHECK_INITIALIZED(self)
483 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
484}
485
486static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000487buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000488{
489 CHECK_INITIALIZED(self)
490 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
491}
492
493static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000494buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000495{
496 CHECK_INITIALIZED(self)
497 return PyObject_GetAttrString(self->raw, "name");
498}
499
500static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000501buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000502{
503 CHECK_INITIALIZED(self)
504 return PyObject_GetAttrString(self->raw, "mode");
505}
506
507/* Lower-level APIs */
508
509static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000510buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000511{
512 CHECK_INITIALIZED(self)
513 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
514}
515
516static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000517buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000518{
519 CHECK_INITIALIZED(self)
520 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
521}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000522
523
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000524/* Forward decls */
525static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000526_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000527static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000528_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000529static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000530_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000531static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000532_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000533static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000534_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000535static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000536_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000537static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000538_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000539static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000540_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000541
542
543/*
544 * Helpers
545 */
546
547/* Returns the address of the `written` member if a BlockingIOError was
548 raised, NULL otherwise. The error is always re-raised. */
549static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000550_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000551{
552 PyObject *t, *v, *tb;
553 PyBlockingIOErrorObject *err;
554
555 PyErr_Fetch(&t, &v, &tb);
556 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
557 PyErr_Restore(t, v, tb);
558 return NULL;
559 }
560 err = (PyBlockingIOErrorObject *) v;
561 /* TODO: sanity check (err->written >= 0) */
562 PyErr_Restore(t, v, tb);
563 return &err->written;
564}
565
566static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000567_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000568{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000569 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000570 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000571 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
572 if (res == NULL)
573 return -1;
574 n = PyNumber_AsOff_t(res, PyExc_ValueError);
575 Py_DECREF(res);
576 if (n < 0) {
577 if (!PyErr_Occurred())
578 PyErr_Format(PyExc_IOError,
Mark Dickinson00de1bd2009-10-29 10:01:23 +0000579 "Raw stream returned invalid position %zd", n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000580 return -1;
581 }
582 self->abs_pos = n;
583 return n;
584}
585
586static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000587_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000588{
589 PyObject *res, *posobj, *whenceobj;
590 Py_off_t n;
591
592 posobj = PyLong_FromOff_t(target);
593 if (posobj == NULL)
594 return -1;
595 whenceobj = PyLong_FromLong(whence);
596 if (whenceobj == NULL) {
597 Py_DECREF(posobj);
598 return -1;
599 }
600 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
601 posobj, whenceobj, NULL);
602 Py_DECREF(posobj);
603 Py_DECREF(whenceobj);
604 if (res == NULL)
605 return -1;
606 n = PyNumber_AsOff_t(res, PyExc_ValueError);
607 Py_DECREF(res);
608 if (n < 0) {
609 if (!PyErr_Occurred())
610 PyErr_Format(PyExc_IOError,
Mark Dickinson00de1bd2009-10-29 10:01:23 +0000611 "Raw stream returned invalid position %zd", n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000612 return -1;
613 }
614 self->abs_pos = n;
615 return n;
616}
617
618static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000619_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000620{
621 Py_ssize_t n;
622 if (self->buffer_size <= 0) {
623 PyErr_SetString(PyExc_ValueError,
624 "buffer size must be strictly positive");
625 return -1;
626 }
627 if (self->buffer)
628 PyMem_Free(self->buffer);
629 self->buffer = PyMem_Malloc(self->buffer_size);
630 if (self->buffer == NULL) {
631 PyErr_NoMemory();
632 return -1;
633 }
Georg Brandldfd73442009-04-05 11:47:34 +0000634#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000635 self->lock = PyThread_allocate_lock();
636 if (self->lock == NULL) {
637 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
638 return -1;
639 }
Georg Brandldfd73442009-04-05 11:47:34 +0000640#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000641 /* Find out whether buffer_size is a power of 2 */
642 /* XXX is this optimization useful? */
643 for (n = self->buffer_size - 1; n & 1; n >>= 1)
644 ;
645 if (n == 0)
646 self->buffer_mask = self->buffer_size - 1;
647 else
648 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000649 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000650 PyErr_Clear();
651 return 0;
652}
653
654/*
655 * Shared methods and wrappers
656 */
657
658static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000659buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000660{
661 PyObject *res;
662
663 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000664 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000665
666 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000667 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000668 if (res != NULL && self->readable) {
669 /* Rewind the raw stream so that its position corresponds to
670 the current logical position. */
671 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000672 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000673 if (n == -1)
674 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000675 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000676 }
677 LEAVE_BUFFERED(self)
678
679 return res;
680}
681
682static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000683buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000684{
685 Py_ssize_t n = 0;
686 PyObject *res = NULL;
687
688 CHECK_INITIALIZED(self)
689 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
690 return NULL;
691 }
692
693 ENTER_BUFFERED(self)
694
695 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000696 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000697 if (res == NULL)
698 goto end;
699 Py_CLEAR(res);
700 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000701 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000702
703end:
704 LEAVE_BUFFERED(self)
705 return res;
706}
707
708static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000709buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000710{
711 Py_ssize_t n = -1;
712 PyObject *res;
713
714 CHECK_INITIALIZED(self)
Benjamin Peterson6b59f772009-12-13 19:30:15 +0000715 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000716 return NULL;
717 }
718 if (n < -1) {
719 PyErr_SetString(PyExc_ValueError,
720 "read length must be positive or -1");
721 return NULL;
722 }
723
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000724 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000725
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000726 if (n == -1) {
727 /* The number of bytes is unspecified, read until the end of stream */
728 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000729 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000730 LEAVE_BUFFERED(self)
731 }
732 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000733 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000734 if (res == Py_None) {
735 Py_DECREF(res);
736 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000737 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000738 LEAVE_BUFFERED(self)
739 }
740 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000741
742 return res;
743}
744
745static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000746buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000747{
748 Py_ssize_t n, have, r;
749 PyObject *res = NULL;
750
751 CHECK_INITIALIZED(self)
752 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
753 return NULL;
754 }
755
756 if (n < 0) {
757 PyErr_SetString(PyExc_ValueError,
758 "read length must be positive");
759 return NULL;
760 }
761 if (n == 0)
762 return PyBytes_FromStringAndSize(NULL, 0);
763
764 ENTER_BUFFERED(self)
765
766 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000767 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000768 if (res == NULL)
769 goto end;
770 Py_CLEAR(res);
771 }
772
773 /* Return up to n bytes. If at least one byte is buffered, we
774 only return buffered bytes. Otherwise, we do one raw read. */
775
776 /* XXX: this mimicks the io.py implementation but is probably wrong.
777 If we need to read from the raw stream, then we could actually read
778 all `n` bytes asked by the caller (and possibly more, so as to fill
779 our buffer for the next reads). */
780
781 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
782 if (have > 0) {
783 if (n > have)
784 n = have;
785 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
786 if (res == NULL)
787 goto end;
788 self->pos += n;
789 goto end;
790 }
791
792 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000793 _bufferedreader_reset_buf(self);
794 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000795 if (r == -1)
796 goto end;
797 if (r == -2)
798 r = 0;
799 if (n > r)
800 n = r;
801 res = PyBytes_FromStringAndSize(self->buffer, n);
802 if (res == NULL)
803 goto end;
804 self->pos = n;
805
806end:
807 LEAVE_BUFFERED(self)
808 return res;
809}
810
811static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000812buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000813{
814 PyObject *res = NULL;
815
816 CHECK_INITIALIZED(self)
817
818 /* TODO: use raw.readinto() instead! */
819 if (self->writable) {
820 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000821 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000822 LEAVE_BUFFERED(self)
823 if (res == NULL)
824 goto end;
825 Py_DECREF(res);
826 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000827 res = bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000828
829end:
830 return res;
831}
832
833static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000834_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000835{
836 PyObject *res = NULL;
837 PyObject *chunks = NULL;
838 Py_ssize_t n, written = 0;
839 const char *start, *s, *end;
840
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000841 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000842
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000843 /* First, try to find a line in the buffer. This can run unlocked because
844 the calls to the C API are simple enough that they can't trigger
845 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000846 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
847 if (limit >= 0 && n > limit)
848 n = limit;
849 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000850 s = memchr(start, '\n', n);
851 if (s != NULL) {
852 res = PyBytes_FromStringAndSize(start, s - start + 1);
853 if (res != NULL)
854 self->pos += s - start + 1;
855 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000856 }
857 if (n == limit) {
858 res = PyBytes_FromStringAndSize(start, n);
859 if (res != NULL)
860 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000861 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000862 }
863
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000864 ENTER_BUFFERED(self)
865
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000866 /* Now we try to get some more from the raw stream */
867 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000868 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000869 if (res == NULL)
870 goto end;
871 Py_CLEAR(res);
872 }
873 chunks = PyList_New(0);
874 if (chunks == NULL)
875 goto end;
876 if (n > 0) {
877 res = PyBytes_FromStringAndSize(start, n);
878 if (res == NULL)
879 goto end;
880 if (PyList_Append(chunks, res) < 0) {
881 Py_CLEAR(res);
882 goto end;
883 }
884 Py_CLEAR(res);
885 written += n;
886 if (limit >= 0)
887 limit -= n;
888 }
889
890 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000891 _bufferedreader_reset_buf(self);
892 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000893 if (n == -1)
894 goto end;
895 if (n <= 0)
896 break;
897 if (limit >= 0 && n > limit)
898 n = limit;
899 start = self->buffer;
900 end = start + n;
901 s = start;
902 while (s < end) {
903 if (*s++ == '\n') {
904 res = PyBytes_FromStringAndSize(start, s - start);
905 if (res == NULL)
906 goto end;
907 self->pos = s - start;
908 goto found;
909 }
910 }
911 res = PyBytes_FromStringAndSize(start, n);
912 if (res == NULL)
913 goto end;
914 if (n == limit) {
915 self->pos = n;
916 break;
917 }
918 if (PyList_Append(chunks, res) < 0) {
919 Py_CLEAR(res);
920 goto end;
921 }
922 Py_CLEAR(res);
923 written += n;
924 if (limit >= 0)
925 limit -= n;
926 }
927found:
928 if (res != NULL && PyList_Append(chunks, res) < 0) {
929 Py_CLEAR(res);
930 goto end;
931 }
932 Py_CLEAR(res);
933 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
934
935end:
936 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000937end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000938 Py_XDECREF(chunks);
939 return res;
940}
941
942static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000943buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000944{
945 Py_ssize_t limit = -1;
946
947 CHECK_INITIALIZED(self)
Benjamin Peterson6b59f772009-12-13 19:30:15 +0000948 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000949 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000950 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000951}
952
953
954static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000955buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000956{
957 Py_off_t pos;
958
959 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000960 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000961 if (pos == -1)
962 return NULL;
963 pos -= RAW_OFFSET(self);
964 /* TODO: sanity check (pos >= 0) */
965 return PyLong_FromOff_t(pos);
966}
967
968static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000969buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000970{
971 Py_off_t target, n;
972 int whence = 0;
973 PyObject *targetobj, *res = NULL;
974
975 CHECK_INITIALIZED(self)
976 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
977 return NULL;
978 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000979 if (whence < 0 || whence > 2) {
980 PyErr_Format(PyExc_ValueError,
981 "whence must be between 0 and 2, not %d", whence);
982 return NULL;
983 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000984
985 CHECK_CLOSED(self, "seek of closed file")
986
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000987 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
988 if (target == -1 && PyErr_Occurred())
989 return NULL;
990
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000991 if (whence != 2 && self->readable) {
992 Py_off_t current, avail;
993 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000994 so as to return quickly if possible. Also, we needn't take the
995 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000996 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000997 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
998 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000999 current = RAW_TELL(self);
1000 avail = READAHEAD(self);
1001 if (avail > 0) {
1002 Py_off_t offset;
1003 if (whence == 0)
1004 offset = target - (current - RAW_OFFSET(self));
1005 else
1006 offset = target;
1007 if (offset >= -self->pos && offset <= avail) {
1008 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001009 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001010 }
1011 }
1012 }
1013
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001014 ENTER_BUFFERED(self)
1015
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001016 /* Fallback: invoke raw seek() method and clear buffer */
1017 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001018 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001019 if (res == NULL)
1020 goto end;
1021 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001022 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001023 }
1024
1025 /* TODO: align on block boundary and read buffer if needed? */
1026 if (whence == 1)
1027 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001028 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001029 if (n == -1)
1030 goto end;
1031 self->raw_pos = -1;
1032 res = PyLong_FromOff_t(n);
1033 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001034 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001035
1036end:
1037 LEAVE_BUFFERED(self)
1038 return res;
1039}
1040
1041static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001042buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001043{
1044 PyObject *pos = Py_None;
1045 PyObject *res = NULL;
1046
1047 CHECK_INITIALIZED(self)
1048 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1049 return NULL;
1050 }
1051
1052 ENTER_BUFFERED(self)
1053
1054 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001055 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001056 if (res == NULL)
1057 goto end;
1058 Py_CLEAR(res);
1059 }
1060 if (self->readable) {
1061 if (pos == Py_None) {
1062 /* Rewind the raw stream so that its position corresponds to
1063 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001064 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001065 goto end;
1066 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001067 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001068 }
1069 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1070 if (res == NULL)
1071 goto end;
1072 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001073 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001074 PyErr_Clear();
1075
1076end:
1077 LEAVE_BUFFERED(self)
1078 return res;
1079}
1080
1081static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001082buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001083{
1084 PyObject *line;
1085 PyTypeObject *tp;
1086
1087 CHECK_INITIALIZED(self);
1088
1089 tp = Py_TYPE(self);
1090 if (tp == &PyBufferedReader_Type ||
1091 tp == &PyBufferedRandom_Type) {
1092 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001093 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001094 }
1095 else {
1096 line = PyObject_CallMethodObjArgs((PyObject *)self,
1097 _PyIO_str_readline, NULL);
1098 if (line && !PyBytes_Check(line)) {
1099 PyErr_Format(PyExc_IOError,
1100 "readline() should have returned a bytes object, "
1101 "not '%.200s'", Py_TYPE(line)->tp_name);
1102 Py_DECREF(line);
1103 return NULL;
1104 }
1105 }
1106
1107 if (line == NULL)
1108 return NULL;
1109
1110 if (PyBytes_GET_SIZE(line) == 0) {
1111 /* Reached EOF or would have blocked */
1112 Py_DECREF(line);
1113 return NULL;
1114 }
1115
1116 return line;
1117}
1118
Antoine Pitrou716c4442009-05-23 19:04:03 +00001119static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001120buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001121{
1122 PyObject *nameobj, *res;
1123
1124 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1125 if (nameobj == NULL) {
1126 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1127 PyErr_Clear();
1128 else
1129 return NULL;
1130 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1131 }
1132 else {
1133 res = PyUnicode_FromFormat("<%s name=%R>",
1134 Py_TYPE(self)->tp_name, nameobj);
1135 Py_DECREF(nameobj);
1136 }
1137 return res;
1138}
1139
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001140/*
1141 * class BufferedReader
1142 */
1143
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001144PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001145 "Create a new buffered reader using the given readable raw IO object.");
1146
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001147static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001148{
1149 self->read_end = -1;
1150}
1151
1152static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001153bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001154{
1155 char *kwlist[] = {"raw", "buffer_size", NULL};
1156 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1157 PyObject *raw;
1158
1159 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001160 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001161
1162 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1163 &raw, &buffer_size)) {
1164 return -1;
1165 }
1166
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001167 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001168 return -1;
1169
1170 Py_CLEAR(self->raw);
1171 Py_INCREF(raw);
1172 self->raw = raw;
1173 self->buffer_size = buffer_size;
1174 self->readable = 1;
1175 self->writable = 0;
1176
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001177 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001178 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001179 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001180
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001181 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1182 Py_TYPE(raw) == &PyFileIO_Type);
1183
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001184 self->ok = 1;
1185 return 0;
1186}
1187
1188static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001189_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001190{
1191 Py_buffer buf;
1192 PyObject *memobj, *res;
1193 Py_ssize_t n;
1194 /* NOTE: the buffer needn't be released as its object is NULL. */
1195 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1196 return -1;
1197 memobj = PyMemoryView_FromBuffer(&buf);
1198 if (memobj == NULL)
1199 return -1;
1200 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1201 Py_DECREF(memobj);
1202 if (res == NULL)
1203 return -1;
1204 if (res == Py_None) {
1205 /* Non-blocking stream would have blocked. Special return code! */
1206 Py_DECREF(res);
1207 return -2;
1208 }
1209 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1210 Py_DECREF(res);
1211 if (n < 0 || n > len) {
1212 PyErr_Format(PyExc_IOError,
1213 "raw readinto() returned invalid length %zd "
1214 "(should have been between 0 and %zd)", n, len);
1215 return -1;
1216 }
1217 if (n > 0 && self->abs_pos != -1)
1218 self->abs_pos += n;
1219 return n;
1220}
1221
1222static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001223_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001224{
1225 Py_ssize_t start, len, n;
1226 if (VALID_READ_BUFFER(self))
1227 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1228 else
1229 start = 0;
1230 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001231 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001232 if (n <= 0)
1233 return n;
1234 self->read_end = start + n;
1235 self->raw_pos = start + n;
1236 return n;
1237}
1238
1239static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001240_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001241{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001242 Py_ssize_t current_size;
1243 PyObject *res, *data = NULL;
1244 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001245
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001246 if (chunks == NULL)
1247 return NULL;
1248
1249 /* First copy what we have in the current buffer. */
1250 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1251 if (current_size) {
1252 data = PyBytes_FromStringAndSize(
1253 self->buffer + self->pos, current_size);
1254 if (data == NULL) {
1255 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001256 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001257 }
1258 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001259 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001260 /* We're going past the buffer's bounds, flush it */
1261 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001262 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001263 if (res == NULL) {
1264 Py_DECREF(chunks);
1265 return NULL;
1266 }
1267 Py_CLEAR(res);
1268 }
1269 while (1) {
1270 if (data) {
1271 if (PyList_Append(chunks, data) < 0) {
1272 Py_DECREF(data);
1273 Py_DECREF(chunks);
1274 return NULL;
1275 }
1276 Py_DECREF(data);
1277 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001278
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001279 /* Read until EOF or until read() would block. */
1280 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1281 if (data == NULL) {
1282 Py_DECREF(chunks);
1283 return NULL;
1284 }
1285 if (data != Py_None && !PyBytes_Check(data)) {
1286 Py_DECREF(data);
1287 Py_DECREF(chunks);
1288 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1289 return NULL;
1290 }
1291 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1292 if (current_size == 0) {
1293 Py_DECREF(chunks);
1294 return data;
1295 }
1296 else {
1297 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1298 Py_DECREF(data);
1299 Py_DECREF(chunks);
1300 return res;
1301 }
1302 }
1303 current_size += PyBytes_GET_SIZE(data);
1304 if (self->abs_pos != -1)
1305 self->abs_pos += PyBytes_GET_SIZE(data);
1306 }
1307}
1308
1309/* Read n bytes from the buffer if it can, otherwise return None.
1310 This function is simple enough that it can run unlocked. */
1311static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001312_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001313{
1314 Py_ssize_t current_size;
1315
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001316 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1317 if (n <= current_size) {
1318 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001319 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1320 if (res != NULL)
1321 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001322 return res;
1323 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001324 Py_RETURN_NONE;
1325}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001326
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001327/* Generic read function: read from the stream until enough bytes are read,
1328 * or until an EOF occurs or until read() would block.
1329 */
1330static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001331_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001332{
1333 PyObject *res = NULL;
1334 Py_ssize_t current_size, remaining, written;
1335 char *out;
1336
1337 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1338 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001339 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001340
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001341 res = PyBytes_FromStringAndSize(NULL, n);
1342 if (res == NULL)
1343 goto error;
1344 out = PyBytes_AS_STRING(res);
1345 remaining = n;
1346 written = 0;
1347 if (current_size > 0) {
1348 memcpy(out, self->buffer + self->pos, current_size);
1349 remaining -= current_size;
1350 written += current_size;
1351 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001352 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001353 while (remaining > 0) {
1354 /* We want to read a whole block at the end into buffer.
1355 If we had readv() we could do this in one pass. */
1356 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1357 if (r == 0)
1358 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001359 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001360 if (r == -1)
1361 goto error;
1362 if (r == 0 || r == -2) {
1363 /* EOF occurred or read() would block. */
1364 if (r == 0 || written > 0) {
1365 if (_PyBytes_Resize(&res, written))
1366 goto error;
1367 return res;
1368 }
1369 Py_DECREF(res);
1370 Py_INCREF(Py_None);
1371 return Py_None;
1372 }
1373 remaining -= r;
1374 written += r;
1375 }
1376 assert(remaining <= self->buffer_size);
1377 self->pos = 0;
1378 self->raw_pos = 0;
1379 self->read_end = 0;
1380 while (self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001381 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001382 if (r == -1)
1383 goto error;
1384 if (r == 0 || r == -2) {
1385 /* EOF occurred or read() would block. */
1386 if (r == 0 || written > 0) {
1387 if (_PyBytes_Resize(&res, written))
1388 goto error;
1389 return res;
1390 }
1391 Py_DECREF(res);
1392 Py_INCREF(Py_None);
1393 return Py_None;
1394 }
1395 if (remaining > r) {
1396 memcpy(out + written, self->buffer + self->pos, r);
1397 written += r;
1398 self->pos += r;
1399 remaining -= r;
1400 }
1401 else if (remaining > 0) {
1402 memcpy(out + written, self->buffer + self->pos, remaining);
1403 written += remaining;
1404 self->pos += remaining;
1405 remaining = 0;
1406 }
1407 if (remaining == 0)
1408 break;
1409 }
1410
1411 return res;
1412
1413error:
1414 Py_XDECREF(res);
1415 return NULL;
1416}
1417
1418static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001419_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001420{
1421 Py_ssize_t have, r;
1422
1423 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1424 /* Constraints:
1425 1. we don't want to advance the file position.
1426 2. we don't want to lose block alignment, so we can't shift the buffer
1427 to make some place.
1428 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1429 */
1430 if (have > 0) {
1431 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1432 }
1433
1434 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001435 _bufferedreader_reset_buf(self);
1436 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001437 if (r == -1)
1438 return NULL;
1439 if (r == -2)
1440 r = 0;
1441 self->pos = 0;
1442 return PyBytes_FromStringAndSize(self->buffer, r);
1443}
1444
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001445static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001446 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001447 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1448 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1449 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1450 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1451 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1452 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1453 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1454 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001455
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001456 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1457 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1458 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1459 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1460 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1461 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1462 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001463 {NULL, NULL}
1464};
1465
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001466static PyMemberDef bufferedreader_members[] = {
1467 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001468 {NULL}
1469};
1470
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001471static PyGetSetDef bufferedreader_getset[] = {
1472 {"closed", (getter)buffered_closed_get, NULL, NULL},
1473 {"name", (getter)buffered_name_get, NULL, NULL},
1474 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001475 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001476};
1477
1478
1479PyTypeObject PyBufferedReader_Type = {
1480 PyVarObject_HEAD_INIT(NULL, 0)
1481 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001482 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001483 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001484 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001485 0, /*tp_print*/
1486 0, /*tp_getattr*/
1487 0, /*tp_setattr*/
1488 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001489 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001490 0, /*tp_as_number*/
1491 0, /*tp_as_sequence*/
1492 0, /*tp_as_mapping*/
1493 0, /*tp_hash */
1494 0, /*tp_call*/
1495 0, /*tp_str*/
1496 0, /*tp_getattro*/
1497 0, /*tp_setattro*/
1498 0, /*tp_as_buffer*/
1499 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1500 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001501 bufferedreader_doc, /* tp_doc */
1502 (traverseproc)buffered_traverse, /* tp_traverse */
1503 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001504 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001505 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001506 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001507 (iternextfunc)buffered_iternext, /* tp_iternext */
1508 bufferedreader_methods, /* tp_methods */
1509 bufferedreader_members, /* tp_members */
1510 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001511 0, /* tp_base */
1512 0, /* tp_dict */
1513 0, /* tp_descr_get */
1514 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001515 offsetof(buffered, dict), /* tp_dictoffset */
1516 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001517 0, /* tp_alloc */
1518 PyType_GenericNew, /* tp_new */
1519};
1520
1521
Benjamin Peterson59406a92009-03-26 17:10:29 +00001522
1523static int
1524complain_about_max_buffer_size(void)
1525{
1526 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1527 "max_buffer_size is deprecated", 1) < 0)
1528 return 0;
1529 return 1;
1530}
1531
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001532/*
1533 * class BufferedWriter
1534 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001535PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001536 "A buffer for a writeable sequential RawIO object.\n"
1537 "\n"
1538 "The constructor creates a BufferedWriter for the given writeable raw\n"
1539 "stream. If the buffer_size is not given, it defaults to\n"
1540 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1541 );
1542
1543static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001544_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001545{
1546 self->write_pos = 0;
1547 self->write_end = -1;
1548}
1549
1550static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001551bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001552{
1553 /* TODO: properly deprecate max_buffer_size */
1554 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1555 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001556 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001557 PyObject *raw;
1558
1559 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001560 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001561
1562 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1563 &raw, &buffer_size, &max_buffer_size)) {
1564 return -1;
1565 }
1566
Benjamin Peterson59406a92009-03-26 17:10:29 +00001567 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1568 return -1;
1569
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001570 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001571 return -1;
1572
1573 Py_CLEAR(self->raw);
1574 Py_INCREF(raw);
1575 self->raw = raw;
1576 self->readable = 0;
1577 self->writable = 1;
1578
1579 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001580 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001581 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001582 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001583 self->pos = 0;
1584
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001585 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1586 Py_TYPE(raw) == &PyFileIO_Type);
1587
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001588 self->ok = 1;
1589 return 0;
1590}
1591
1592static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001593_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001594{
1595 Py_buffer buf;
1596 PyObject *memobj, *res;
1597 Py_ssize_t n;
1598 /* NOTE: the buffer needn't be released as its object is NULL. */
1599 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1600 return -1;
1601 memobj = PyMemoryView_FromBuffer(&buf);
1602 if (memobj == NULL)
1603 return -1;
1604 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1605 Py_DECREF(memobj);
1606 if (res == NULL)
1607 return -1;
1608 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1609 Py_DECREF(res);
1610 if (n < 0 || n > len) {
1611 PyErr_Format(PyExc_IOError,
1612 "raw write() returned invalid length %zd "
1613 "(should have been between 0 and %zd)", n, len);
1614 return -1;
1615 }
1616 if (n > 0 && self->abs_pos != -1)
1617 self->abs_pos += n;
1618 return n;
1619}
1620
1621/* `restore_pos` is 1 if we need to restore the raw stream position at
1622 the end, 0 otherwise. */
1623static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001624_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001625{
1626 Py_ssize_t written = 0;
1627 Py_off_t n, rewind;
1628
1629 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1630 goto end;
1631 /* First, rewind */
1632 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1633 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001634 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001635 if (n < 0) {
1636 goto error;
1637 }
1638 self->raw_pos -= rewind;
1639 }
1640 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001641 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001642 self->buffer + self->write_pos,
1643 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1644 Py_off_t, Py_ssize_t));
1645 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001646 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001647 if (w == NULL)
1648 goto error;
1649 self->write_pos += *w;
1650 self->raw_pos = self->write_pos;
1651 written += *w;
1652 *w = written;
1653 /* Already re-raised */
1654 goto error;
1655 }
1656 self->write_pos += n;
1657 self->raw_pos = self->write_pos;
1658 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1659 }
1660
1661 if (restore_pos) {
1662 Py_off_t forward = rewind - written;
1663 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001664 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001665 if (n < 0) {
1666 goto error;
1667 }
1668 self->raw_pos += forward;
1669 }
1670 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001671 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001672
1673end:
1674 Py_RETURN_NONE;
1675
1676error:
1677 return NULL;
1678}
1679
1680static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001681bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001682{
1683 PyObject *res = NULL;
1684 Py_buffer buf;
1685 Py_ssize_t written, avail, remaining, n;
1686
1687 CHECK_INITIALIZED(self)
1688 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1689 return NULL;
1690 }
1691
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001692 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001693 PyErr_SetString(PyExc_ValueError, "write to closed file");
1694 PyBuffer_Release(&buf);
1695 return NULL;
1696 }
1697
1698 ENTER_BUFFERED(self)
1699
1700 /* Fast path: the data to write can be fully buffered. */
1701 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1702 self->pos = 0;
1703 self->raw_pos = 0;
1704 }
1705 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1706 if (buf.len <= avail) {
1707 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1708 if (!VALID_WRITE_BUFFER(self)) {
1709 self->write_pos = self->pos;
1710 }
1711 ADJUST_POSITION(self, self->pos + buf.len);
1712 if (self->pos > self->write_end)
1713 self->write_end = self->pos;
1714 written = buf.len;
1715 goto end;
1716 }
1717
1718 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001719 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001720 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001721 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001722 if (w == NULL)
1723 goto error;
1724 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001725 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001726 /* Make some place by shifting the buffer. */
1727 assert(VALID_WRITE_BUFFER(self));
1728 memmove(self->buffer, self->buffer + self->write_pos,
1729 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1730 Py_off_t, Py_ssize_t));
1731 self->write_end -= self->write_pos;
1732 self->raw_pos -= self->write_pos;
1733 self->pos -= self->write_pos;
1734 self->write_pos = 0;
1735 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1736 Py_off_t, Py_ssize_t);
1737 if (buf.len <= avail) {
1738 /* Everything can be buffered */
1739 PyErr_Clear();
1740 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1741 self->write_end += buf.len;
1742 written = buf.len;
1743 goto end;
1744 }
1745 /* Buffer as much as possible. */
1746 memcpy(self->buffer + self->write_end, buf.buf, avail);
1747 self->write_end += avail;
1748 /* Already re-raised */
1749 *w = avail;
1750 goto error;
1751 }
1752 Py_CLEAR(res);
1753
Antoine Pitrou0473e562009-08-06 20:52:43 +00001754 /* Adjust the raw stream position if it is away from the logical stream
1755 position. This happens if the read buffer has been filled but not
1756 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1757 the raw stream by itself).
1758 Fixes issue #6629.
1759 */
1760 n = RAW_OFFSET(self);
1761 if (n != 0) {
1762 if (_buffered_raw_seek(self, -n, 1) < 0)
1763 goto error;
1764 self->raw_pos -= n;
1765 }
1766
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001767 /* Then write buf itself. At this point the buffer has been emptied. */
1768 remaining = buf.len;
1769 written = 0;
1770 while (remaining > self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001771 n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001772 self, (char *) buf.buf + written, buf.len - written);
1773 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001774 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001775 if (w == NULL)
1776 goto error;
1777 written += *w;
1778 remaining -= *w;
1779 if (remaining > self->buffer_size) {
1780 /* Can't buffer everything, still buffer as much as possible */
1781 memcpy(self->buffer,
1782 (char *) buf.buf + written, self->buffer_size);
1783 self->raw_pos = 0;
1784 ADJUST_POSITION(self, self->buffer_size);
1785 self->write_end = self->buffer_size;
1786 *w = written + self->buffer_size;
1787 /* Already re-raised */
1788 goto error;
1789 }
1790 PyErr_Clear();
1791 break;
1792 }
1793 written += n;
1794 remaining -= n;
1795 }
1796 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001797 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001798 if (remaining > 0) {
1799 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1800 written += remaining;
1801 }
1802 self->write_pos = 0;
1803 /* TODO: sanity check (remaining >= 0) */
1804 self->write_end = remaining;
1805 ADJUST_POSITION(self, remaining);
1806 self->raw_pos = 0;
1807
1808end:
1809 res = PyLong_FromSsize_t(written);
1810
1811error:
1812 LEAVE_BUFFERED(self)
1813 PyBuffer_Release(&buf);
1814 return res;
1815}
1816
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001817static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001818 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001819 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1820 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1821 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1822 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1823 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1824 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1825 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001826
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001827 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1828 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1829 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1830 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1831 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001832 {NULL, NULL}
1833};
1834
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001835static PyMemberDef bufferedwriter_members[] = {
1836 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001837 {NULL}
1838};
1839
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001840static PyGetSetDef bufferedwriter_getset[] = {
1841 {"closed", (getter)buffered_closed_get, NULL, NULL},
1842 {"name", (getter)buffered_name_get, NULL, NULL},
1843 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001844 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001845};
1846
1847
1848PyTypeObject PyBufferedWriter_Type = {
1849 PyVarObject_HEAD_INIT(NULL, 0)
1850 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001851 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001852 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001853 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001854 0, /*tp_print*/
1855 0, /*tp_getattr*/
1856 0, /*tp_setattr*/
1857 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001858 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001859 0, /*tp_as_number*/
1860 0, /*tp_as_sequence*/
1861 0, /*tp_as_mapping*/
1862 0, /*tp_hash */
1863 0, /*tp_call*/
1864 0, /*tp_str*/
1865 0, /*tp_getattro*/
1866 0, /*tp_setattro*/
1867 0, /*tp_as_buffer*/
1868 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1869 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001870 bufferedwriter_doc, /* tp_doc */
1871 (traverseproc)buffered_traverse, /* tp_traverse */
1872 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001873 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001874 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001875 0, /* tp_iter */
1876 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001877 bufferedwriter_methods, /* tp_methods */
1878 bufferedwriter_members, /* tp_members */
1879 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001880 0, /* tp_base */
1881 0, /* tp_dict */
1882 0, /* tp_descr_get */
1883 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001884 offsetof(buffered, dict), /* tp_dictoffset */
1885 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001886 0, /* tp_alloc */
1887 PyType_GenericNew, /* tp_new */
1888};
1889
1890
1891
1892/*
1893 * BufferedRWPair
1894 */
1895
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001896PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001897 "A buffered reader and writer object together.\n"
1898 "\n"
1899 "A buffered reader object and buffered writer object put together to\n"
1900 "form a sequential IO object that can read and write. This is typically\n"
1901 "used with a socket or two-way pipe.\n"
1902 "\n"
1903 "reader and writer are RawIOBase objects that are readable and\n"
1904 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001905 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001906 );
1907
1908/* XXX The usefulness of this (compared to having two separate IO objects) is
1909 * questionable.
1910 */
1911
1912typedef struct {
1913 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001914 buffered *reader;
1915 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001916 PyObject *dict;
1917 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001918} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001919
1920static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001921bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001922{
1923 PyObject *reader, *writer;
1924 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001925 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001926
1927 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1928 &buffer_size, &max_buffer_size)) {
1929 return -1;
1930 }
1931
Benjamin Peterson59406a92009-03-26 17:10:29 +00001932 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1933 return -1;
1934
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001935 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001936 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001937 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001938 return -1;
1939
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001940 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001941 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001942 if (self->reader == NULL)
1943 return -1;
1944
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001945 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001946 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001947 if (self->writer == NULL) {
1948 Py_CLEAR(self->reader);
1949 return -1;
1950 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001951
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001952 return 0;
1953}
1954
1955static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001956bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001957{
1958 Py_VISIT(self->dict);
1959 return 0;
1960}
1961
1962static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001963bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001964{
1965 Py_CLEAR(self->reader);
1966 Py_CLEAR(self->writer);
1967 Py_CLEAR(self->dict);
1968 return 0;
1969}
1970
1971static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001972bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001973{
1974 _PyObject_GC_UNTRACK(self);
1975 Py_CLEAR(self->reader);
1976 Py_CLEAR(self->writer);
1977 Py_CLEAR(self->dict);
1978 Py_TYPE(self)->tp_free((PyObject *) self);
1979}
1980
1981static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001982_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001983{
1984 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1985 PyObject *ret;
1986
1987 if (func == NULL) {
1988 PyErr_SetString(PyExc_AttributeError, name);
1989 return NULL;
1990 }
1991
1992 ret = PyObject_CallObject(func, args);
1993 Py_DECREF(func);
1994 return ret;
1995}
1996
1997static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001998bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001999{
2000 return _forward_call(self->reader, "read", args);
2001}
2002
2003static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002004bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002005{
2006 return _forward_call(self->reader, "peek", args);
2007}
2008
2009static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002010bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002011{
2012 return _forward_call(self->reader, "read1", args);
2013}
2014
2015static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002016bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002017{
2018 return _forward_call(self->reader, "readinto", args);
2019}
2020
2021static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002022bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002023{
2024 return _forward_call(self->writer, "write", args);
2025}
2026
2027static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002028bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002029{
2030 return _forward_call(self->writer, "flush", args);
2031}
2032
2033static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002034bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002035{
2036 return _forward_call(self->reader, "readable", args);
2037}
2038
2039static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002040bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002041{
2042 return _forward_call(self->writer, "writable", args);
2043}
2044
2045static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002046bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002047{
2048 PyObject *ret = _forward_call(self->writer, "close", args);
2049 if (ret == NULL)
2050 return NULL;
2051 Py_DECREF(ret);
2052
2053 return _forward_call(self->reader, "close", args);
2054}
2055
2056static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002057bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002058{
2059 PyObject *ret = _forward_call(self->writer, "isatty", args);
2060
2061 if (ret != Py_False) {
2062 /* either True or exception */
2063 return ret;
2064 }
2065 Py_DECREF(ret);
2066
2067 return _forward_call(self->reader, "isatty", args);
2068}
2069
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002070static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002071bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002072{
2073 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2074}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002075
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002076static PyMethodDef bufferedrwpair_methods[] = {
2077 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2078 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2079 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2080 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002081
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002082 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2083 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002084
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002085 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2086 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002087
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002088 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2089 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002090
2091 {NULL, NULL}
2092};
2093
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002094static PyGetSetDef bufferedrwpair_getset[] = {
2095 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002096 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002097};
2098
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002099PyTypeObject PyBufferedRWPair_Type = {
2100 PyVarObject_HEAD_INIT(NULL, 0)
2101 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002102 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002103 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002104 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002105 0, /*tp_print*/
2106 0, /*tp_getattr*/
2107 0, /*tp_setattr*/
2108 0, /*tp_compare */
2109 0, /*tp_repr*/
2110 0, /*tp_as_number*/
2111 0, /*tp_as_sequence*/
2112 0, /*tp_as_mapping*/
2113 0, /*tp_hash */
2114 0, /*tp_call*/
2115 0, /*tp_str*/
2116 0, /*tp_getattro*/
2117 0, /*tp_setattro*/
2118 0, /*tp_as_buffer*/
2119 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2120 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002121 bufferedrwpair_doc, /* tp_doc */
2122 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2123 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002124 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002125 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002126 0, /* tp_iter */
2127 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002128 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002129 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002130 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002131 0, /* tp_base */
2132 0, /* tp_dict */
2133 0, /* tp_descr_get */
2134 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002135 offsetof(rwpair, dict), /* tp_dictoffset */
2136 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002137 0, /* tp_alloc */
2138 PyType_GenericNew, /* tp_new */
2139};
2140
2141
2142
2143/*
2144 * BufferedRandom
2145 */
2146
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002147PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002148 "A buffered interface to random access streams.\n"
2149 "\n"
2150 "The constructor creates a reader and writer for a seekable stream,\n"
2151 "raw, given in the first argument. If the buffer_size is omitted it\n"
2152 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2153 );
2154
2155static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002156bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002157{
2158 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2159 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002160 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002161 PyObject *raw;
2162
2163 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002164 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002165
2166 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2167 &raw, &buffer_size, &max_buffer_size)) {
2168 return -1;
2169 }
2170
Benjamin Peterson59406a92009-03-26 17:10:29 +00002171 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2172 return -1;
2173
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002174 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002175 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002176 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002177 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002178 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002179 return -1;
2180
2181 Py_CLEAR(self->raw);
2182 Py_INCREF(raw);
2183 self->raw = raw;
2184 self->buffer_size = buffer_size;
2185 self->readable = 1;
2186 self->writable = 1;
2187
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002188 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002189 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002190 _bufferedreader_reset_buf(self);
2191 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002192 self->pos = 0;
2193
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002194 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2195 Py_TYPE(raw) == &PyFileIO_Type);
2196
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002197 self->ok = 1;
2198 return 0;
2199}
2200
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002201static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002202 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002203 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2204 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2205 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2206 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2207 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2208 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2209 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002210
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002211 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002212
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002213 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2214 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2215 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2216 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2217 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2218 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2219 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2220 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2221 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002222 {NULL, NULL}
2223};
2224
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002225static PyMemberDef bufferedrandom_members[] = {
2226 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002227 {NULL}
2228};
2229
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002230static PyGetSetDef bufferedrandom_getset[] = {
2231 {"closed", (getter)buffered_closed_get, NULL, NULL},
2232 {"name", (getter)buffered_name_get, NULL, NULL},
2233 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002234 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002235};
2236
2237
2238PyTypeObject PyBufferedRandom_Type = {
2239 PyVarObject_HEAD_INIT(NULL, 0)
2240 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002241 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002242 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002243 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002244 0, /*tp_print*/
2245 0, /*tp_getattr*/
2246 0, /*tp_setattr*/
2247 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002248 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002249 0, /*tp_as_number*/
2250 0, /*tp_as_sequence*/
2251 0, /*tp_as_mapping*/
2252 0, /*tp_hash */
2253 0, /*tp_call*/
2254 0, /*tp_str*/
2255 0, /*tp_getattro*/
2256 0, /*tp_setattro*/
2257 0, /*tp_as_buffer*/
2258 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2259 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002260 bufferedrandom_doc, /* tp_doc */
2261 (traverseproc)buffered_traverse, /* tp_traverse */
2262 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002263 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002264 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002265 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002266 (iternextfunc)buffered_iternext, /* tp_iternext */
2267 bufferedrandom_methods, /* tp_methods */
2268 bufferedrandom_members, /* tp_members */
2269 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002270 0, /* tp_base */
2271 0, /*tp_dict*/
2272 0, /* tp_descr_get */
2273 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002274 offsetof(buffered, dict), /*tp_dictoffset*/
2275 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002276 0, /* tp_alloc */
2277 PyType_GenericNew, /* tp_new */
2278};
2279