blob: 4678da91c97c1ac13910045897b9d532d1a7f8d4 [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) \
Antoine Pitrou5800b272009-11-01 12:05:48 +0000263 if (!PyThread_acquire_lock(self->lock, 0)) { \
264 Py_BEGIN_ALLOW_THREADS \
265 PyThread_acquire_lock(self->lock, 1); \
266 Py_END_ALLOW_THREADS \
267 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000268
269#define LEAVE_BUFFERED(self) \
270 PyThread_release_lock(self->lock);
Georg Brandldfd73442009-04-05 11:47:34 +0000271#else
272#define ENTER_BUFFERED(self)
273#define LEAVE_BUFFERED(self)
274#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000275
276#define CHECK_INITIALIZED(self) \
277 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000278 if (self->detached) { \
279 PyErr_SetString(PyExc_ValueError, \
280 "raw stream has been detached"); \
281 } else { \
282 PyErr_SetString(PyExc_ValueError, \
283 "I/O operation on uninitialized object"); \
284 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000285 return NULL; \
286 }
287
288#define CHECK_INITIALIZED_INT(self) \
289 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000290 if (self->detached) { \
291 PyErr_SetString(PyExc_ValueError, \
292 "raw stream has been detached"); \
293 } else { \
294 PyErr_SetString(PyExc_ValueError, \
295 "I/O operation on uninitialized object"); \
296 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000297 return -1; \
298 }
299
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000300#define IS_CLOSED(self) \
301 (self->fast_closed_checks \
302 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000303 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000304
305#define CHECK_CLOSED(self, error_msg) \
306 if (IS_CLOSED(self)) { \
307 PyErr_SetString(PyExc_ValueError, error_msg); \
308 return NULL; \
309 }
310
311
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000312#define VALID_READ_BUFFER(self) \
313 (self->readable && self->read_end != -1)
314
315#define VALID_WRITE_BUFFER(self) \
316 (self->writable && self->write_end != -1)
317
318#define ADJUST_POSITION(self, _new_pos) \
319 do { \
320 self->pos = _new_pos; \
321 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
322 self->read_end = self->pos; \
323 } while(0)
324
325#define READAHEAD(self) \
326 ((self->readable && VALID_READ_BUFFER(self)) \
327 ? (self->read_end - self->pos) : 0)
328
329#define RAW_OFFSET(self) \
330 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
331 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
332
333#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000334 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000335
336#define MINUS_LAST_BLOCK(self, size) \
337 (self->buffer_mask ? \
338 (size & ~self->buffer_mask) : \
339 (self->buffer_size * (size / self->buffer_size)))
340
341
342static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000343buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000344{
345 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
346 return;
347 _PyObject_GC_UNTRACK(self);
348 self->ok = 0;
349 if (self->weakreflist != NULL)
350 PyObject_ClearWeakRefs((PyObject *)self);
351 Py_CLEAR(self->raw);
352 if (self->buffer) {
353 PyMem_Free(self->buffer);
354 self->buffer = NULL;
355 }
Georg Brandldfd73442009-04-05 11:47:34 +0000356#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000357 if (self->lock) {
358 PyThread_free_lock(self->lock);
359 self->lock = NULL;
360 }
Georg Brandldfd73442009-04-05 11:47:34 +0000361#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000362 Py_CLEAR(self->dict);
363 Py_TYPE(self)->tp_free((PyObject *)self);
364}
365
366static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000367buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000368{
369 Py_VISIT(self->raw);
370 Py_VISIT(self->dict);
371 return 0;
372}
373
374static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000375buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000376{
377 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
378 return -1;
379 self->ok = 0;
380 Py_CLEAR(self->raw);
381 Py_CLEAR(self->dict);
382 return 0;
383}
384
385/*
386 * _BufferedIOMixin methods
387 * This is not a class, just a collection of methods that will be reused
388 * by BufferedReader and BufferedWriter
389 */
390
391/* Flush and close */
392
393static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000394buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000395{
396 CHECK_INITIALIZED(self)
397 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
398}
399
400static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000401buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000402{
403 int closed;
404 PyObject *res;
405 CHECK_INITIALIZED_INT(self)
406 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
407 if (res == NULL)
408 return -1;
409 closed = PyObject_IsTrue(res);
410 Py_DECREF(res);
411 return closed;
412}
413
414static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000415buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000416{
417 CHECK_INITIALIZED(self)
418 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
419}
420
421static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000422buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000423{
424 PyObject *res = NULL;
425 int r;
426
427 CHECK_INITIALIZED(self)
428 ENTER_BUFFERED(self)
429
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000430 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000431 if (r < 0)
432 goto end;
433 if (r > 0) {
434 res = Py_None;
435 Py_INCREF(res);
436 goto end;
437 }
438 /* flush() will most probably re-take the lock, so drop it first */
439 LEAVE_BUFFERED(self)
440 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
441 ENTER_BUFFERED(self)
442 if (res == NULL) {
Antoine Pitrou6be88762010-05-03 16:48:20 +0000443 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000444 }
445 Py_XDECREF(res);
446
447 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
448
449end:
450 LEAVE_BUFFERED(self)
451 return res;
452}
453
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000454/* detach */
455
456static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000457buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000458{
459 PyObject *raw, *res;
460 CHECK_INITIALIZED(self)
461 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
462 if (res == NULL)
463 return NULL;
464 Py_DECREF(res);
465 raw = self->raw;
466 self->raw = NULL;
467 self->detached = 1;
468 self->ok = 0;
469 return raw;
470}
471
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000472/* Inquiries */
473
474static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000475buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000476{
477 CHECK_INITIALIZED(self)
478 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
479}
480
481static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000482buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000483{
484 CHECK_INITIALIZED(self)
485 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
486}
487
488static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000489buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000490{
491 CHECK_INITIALIZED(self)
492 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
493}
494
495static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000496buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000497{
498 CHECK_INITIALIZED(self)
499 return PyObject_GetAttrString(self->raw, "name");
500}
501
502static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000503buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000504{
505 CHECK_INITIALIZED(self)
506 return PyObject_GetAttrString(self->raw, "mode");
507}
508
509/* Lower-level APIs */
510
511static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000512buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000513{
514 CHECK_INITIALIZED(self)
515 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
516}
517
518static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000519buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000520{
521 CHECK_INITIALIZED(self)
522 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
523}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000524
525
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000526/* Forward decls */
527static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000528_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000529static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000530_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000531static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000532_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000533static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000534_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000535static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000536_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000537static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000538_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000539static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000540_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000541static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000542_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000543
544
545/*
546 * Helpers
547 */
548
549/* Returns the address of the `written` member if a BlockingIOError was
550 raised, NULL otherwise. The error is always re-raised. */
551static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000552_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000553{
554 PyObject *t, *v, *tb;
555 PyBlockingIOErrorObject *err;
556
557 PyErr_Fetch(&t, &v, &tb);
558 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
559 PyErr_Restore(t, v, tb);
560 return NULL;
561 }
562 err = (PyBlockingIOErrorObject *) v;
563 /* TODO: sanity check (err->written >= 0) */
564 PyErr_Restore(t, v, tb);
565 return &err->written;
566}
567
568static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000569_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000570{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000571 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000572 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000573 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
574 if (res == NULL)
575 return -1;
576 n = PyNumber_AsOff_t(res, PyExc_ValueError);
577 Py_DECREF(res);
578 if (n < 0) {
579 if (!PyErr_Occurred())
580 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000581 "Raw stream returned invalid position %" PY_PRIdOFF,
582 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000583 return -1;
584 }
585 self->abs_pos = n;
586 return n;
587}
588
589static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000590_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000591{
592 PyObject *res, *posobj, *whenceobj;
593 Py_off_t n;
594
595 posobj = PyLong_FromOff_t(target);
596 if (posobj == NULL)
597 return -1;
598 whenceobj = PyLong_FromLong(whence);
599 if (whenceobj == NULL) {
600 Py_DECREF(posobj);
601 return -1;
602 }
603 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
604 posobj, whenceobj, NULL);
605 Py_DECREF(posobj);
606 Py_DECREF(whenceobj);
607 if (res == NULL)
608 return -1;
609 n = PyNumber_AsOff_t(res, PyExc_ValueError);
610 Py_DECREF(res);
611 if (n < 0) {
612 if (!PyErr_Occurred())
613 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000614 "Raw stream returned invalid position %" PY_PRIdOFF,
615 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000616 return -1;
617 }
618 self->abs_pos = n;
619 return n;
620}
621
622static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000623_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000624{
625 Py_ssize_t n;
626 if (self->buffer_size <= 0) {
627 PyErr_SetString(PyExc_ValueError,
628 "buffer size must be strictly positive");
629 return -1;
630 }
631 if (self->buffer)
632 PyMem_Free(self->buffer);
633 self->buffer = PyMem_Malloc(self->buffer_size);
634 if (self->buffer == NULL) {
635 PyErr_NoMemory();
636 return -1;
637 }
Georg Brandldfd73442009-04-05 11:47:34 +0000638#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000639 if (self->lock)
640 PyThread_free_lock(self->lock);
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)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000721 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000722 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)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000954 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000955 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000956 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000957}
958
959
960static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000961buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000962{
963 Py_off_t pos;
964
965 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000966 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000967 if (pos == -1)
968 return NULL;
969 pos -= RAW_OFFSET(self);
970 /* TODO: sanity check (pos >= 0) */
971 return PyLong_FromOff_t(pos);
972}
973
974static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000975buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000976{
977 Py_off_t target, n;
978 int whence = 0;
979 PyObject *targetobj, *res = NULL;
980
981 CHECK_INITIALIZED(self)
982 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
983 return NULL;
984 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000985 if (whence < 0 || whence > 2) {
986 PyErr_Format(PyExc_ValueError,
987 "whence must be between 0 and 2, not %d", whence);
988 return NULL;
989 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000990
991 CHECK_CLOSED(self, "seek of closed file")
992
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000993 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
994 if (target == -1 && PyErr_Occurred())
995 return NULL;
996
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000997 if (whence != 2 && self->readable) {
998 Py_off_t current, avail;
999 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001000 so as to return quickly if possible. Also, we needn't take the
1001 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001002 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001003 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1004 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001005 current = RAW_TELL(self);
1006 avail = READAHEAD(self);
1007 if (avail > 0) {
1008 Py_off_t offset;
1009 if (whence == 0)
1010 offset = target - (current - RAW_OFFSET(self));
1011 else
1012 offset = target;
1013 if (offset >= -self->pos && offset <= avail) {
1014 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001015 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001016 }
1017 }
1018 }
1019
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001020 ENTER_BUFFERED(self)
1021
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001022 /* Fallback: invoke raw seek() method and clear buffer */
1023 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001024 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001025 if (res == NULL)
1026 goto end;
1027 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001028 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001029 }
1030
1031 /* TODO: align on block boundary and read buffer if needed? */
1032 if (whence == 1)
1033 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001034 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001035 if (n == -1)
1036 goto end;
1037 self->raw_pos = -1;
1038 res = PyLong_FromOff_t(n);
1039 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001040 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001041
1042end:
1043 LEAVE_BUFFERED(self)
1044 return res;
1045}
1046
1047static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001048buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001049{
1050 PyObject *pos = Py_None;
1051 PyObject *res = NULL;
1052
1053 CHECK_INITIALIZED(self)
1054 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1055 return NULL;
1056 }
1057
1058 ENTER_BUFFERED(self)
1059
1060 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001061 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001062 if (res == NULL)
1063 goto end;
1064 Py_CLEAR(res);
1065 }
1066 if (self->readable) {
1067 if (pos == Py_None) {
1068 /* Rewind the raw stream so that its position corresponds to
1069 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001070 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001071 goto end;
1072 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001073 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001074 }
1075 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1076 if (res == NULL)
1077 goto end;
1078 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001079 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001080 PyErr_Clear();
1081
1082end:
1083 LEAVE_BUFFERED(self)
1084 return res;
1085}
1086
1087static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001088buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001089{
1090 PyObject *line;
1091 PyTypeObject *tp;
1092
1093 CHECK_INITIALIZED(self);
1094
1095 tp = Py_TYPE(self);
1096 if (tp == &PyBufferedReader_Type ||
1097 tp == &PyBufferedRandom_Type) {
1098 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001099 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001100 }
1101 else {
1102 line = PyObject_CallMethodObjArgs((PyObject *)self,
1103 _PyIO_str_readline, NULL);
1104 if (line && !PyBytes_Check(line)) {
1105 PyErr_Format(PyExc_IOError,
1106 "readline() should have returned a bytes object, "
1107 "not '%.200s'", Py_TYPE(line)->tp_name);
1108 Py_DECREF(line);
1109 return NULL;
1110 }
1111 }
1112
1113 if (line == NULL)
1114 return NULL;
1115
1116 if (PyBytes_GET_SIZE(line) == 0) {
1117 /* Reached EOF or would have blocked */
1118 Py_DECREF(line);
1119 return NULL;
1120 }
1121
1122 return line;
1123}
1124
Antoine Pitrou716c4442009-05-23 19:04:03 +00001125static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001126buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001127{
1128 PyObject *nameobj, *res;
1129
1130 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1131 if (nameobj == NULL) {
1132 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1133 PyErr_Clear();
1134 else
1135 return NULL;
1136 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1137 }
1138 else {
1139 res = PyUnicode_FromFormat("<%s name=%R>",
1140 Py_TYPE(self)->tp_name, nameobj);
1141 Py_DECREF(nameobj);
1142 }
1143 return res;
1144}
1145
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001146/*
1147 * class BufferedReader
1148 */
1149
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001150PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001151 "Create a new buffered reader using the given readable raw IO object.");
1152
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001153static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001154{
1155 self->read_end = -1;
1156}
1157
1158static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001159bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001160{
1161 char *kwlist[] = {"raw", "buffer_size", NULL};
1162 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1163 PyObject *raw;
1164
1165 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001166 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001167
1168 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1169 &raw, &buffer_size)) {
1170 return -1;
1171 }
1172
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001173 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001174 return -1;
1175
1176 Py_CLEAR(self->raw);
1177 Py_INCREF(raw);
1178 self->raw = raw;
1179 self->buffer_size = buffer_size;
1180 self->readable = 1;
1181 self->writable = 0;
1182
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001183 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001184 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001185 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001186
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001187 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1188 Py_TYPE(raw) == &PyFileIO_Type);
1189
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001190 self->ok = 1;
1191 return 0;
1192}
1193
1194static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001195_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001196{
1197 Py_buffer buf;
1198 PyObject *memobj, *res;
1199 Py_ssize_t n;
1200 /* NOTE: the buffer needn't be released as its object is NULL. */
1201 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1202 return -1;
1203 memobj = PyMemoryView_FromBuffer(&buf);
1204 if (memobj == NULL)
1205 return -1;
1206 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1207 Py_DECREF(memobj);
1208 if (res == NULL)
1209 return -1;
1210 if (res == Py_None) {
1211 /* Non-blocking stream would have blocked. Special return code! */
1212 Py_DECREF(res);
1213 return -2;
1214 }
1215 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1216 Py_DECREF(res);
1217 if (n < 0 || n > len) {
1218 PyErr_Format(PyExc_IOError,
1219 "raw readinto() returned invalid length %zd "
1220 "(should have been between 0 and %zd)", n, len);
1221 return -1;
1222 }
1223 if (n > 0 && self->abs_pos != -1)
1224 self->abs_pos += n;
1225 return n;
1226}
1227
1228static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001229_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001230{
1231 Py_ssize_t start, len, n;
1232 if (VALID_READ_BUFFER(self))
1233 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1234 else
1235 start = 0;
1236 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001237 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001238 if (n <= 0)
1239 return n;
1240 self->read_end = start + n;
1241 self->raw_pos = start + n;
1242 return n;
1243}
1244
1245static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001246_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001247{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001248 Py_ssize_t current_size;
1249 PyObject *res, *data = NULL;
1250 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001251
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001252 if (chunks == NULL)
1253 return NULL;
1254
1255 /* First copy what we have in the current buffer. */
1256 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1257 if (current_size) {
1258 data = PyBytes_FromStringAndSize(
1259 self->buffer + self->pos, current_size);
1260 if (data == NULL) {
1261 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001262 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001263 }
1264 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001265 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001266 /* We're going past the buffer's bounds, flush it */
1267 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001268 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001269 if (res == NULL) {
1270 Py_DECREF(chunks);
1271 return NULL;
1272 }
1273 Py_CLEAR(res);
1274 }
1275 while (1) {
1276 if (data) {
1277 if (PyList_Append(chunks, data) < 0) {
1278 Py_DECREF(data);
1279 Py_DECREF(chunks);
1280 return NULL;
1281 }
1282 Py_DECREF(data);
1283 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001284
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001285 /* Read until EOF or until read() would block. */
1286 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1287 if (data == NULL) {
1288 Py_DECREF(chunks);
1289 return NULL;
1290 }
1291 if (data != Py_None && !PyBytes_Check(data)) {
1292 Py_DECREF(data);
1293 Py_DECREF(chunks);
1294 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1295 return NULL;
1296 }
1297 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1298 if (current_size == 0) {
1299 Py_DECREF(chunks);
1300 return data;
1301 }
1302 else {
1303 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1304 Py_DECREF(data);
1305 Py_DECREF(chunks);
1306 return res;
1307 }
1308 }
1309 current_size += PyBytes_GET_SIZE(data);
1310 if (self->abs_pos != -1)
1311 self->abs_pos += PyBytes_GET_SIZE(data);
1312 }
1313}
1314
1315/* Read n bytes from the buffer if it can, otherwise return None.
1316 This function is simple enough that it can run unlocked. */
1317static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001318_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001319{
1320 Py_ssize_t current_size;
1321
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001322 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1323 if (n <= current_size) {
1324 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001325 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1326 if (res != NULL)
1327 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001328 return res;
1329 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001330 Py_RETURN_NONE;
1331}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001332
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001333/* Generic read function: read from the stream until enough bytes are read,
1334 * or until an EOF occurs or until read() would block.
1335 */
1336static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001337_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001338{
1339 PyObject *res = NULL;
1340 Py_ssize_t current_size, remaining, written;
1341 char *out;
1342
1343 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1344 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001345 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001346
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001347 res = PyBytes_FromStringAndSize(NULL, n);
1348 if (res == NULL)
1349 goto error;
1350 out = PyBytes_AS_STRING(res);
1351 remaining = n;
1352 written = 0;
1353 if (current_size > 0) {
1354 memcpy(out, self->buffer + self->pos, current_size);
1355 remaining -= current_size;
1356 written += current_size;
1357 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001358 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001359 while (remaining > 0) {
1360 /* We want to read a whole block at the end into buffer.
1361 If we had readv() we could do this in one pass. */
1362 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1363 if (r == 0)
1364 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001365 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001366 if (r == -1)
1367 goto error;
1368 if (r == 0 || r == -2) {
1369 /* EOF occurred or read() would block. */
1370 if (r == 0 || written > 0) {
1371 if (_PyBytes_Resize(&res, written))
1372 goto error;
1373 return res;
1374 }
1375 Py_DECREF(res);
1376 Py_INCREF(Py_None);
1377 return Py_None;
1378 }
1379 remaining -= r;
1380 written += r;
1381 }
1382 assert(remaining <= self->buffer_size);
1383 self->pos = 0;
1384 self->raw_pos = 0;
1385 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001386 /* NOTE: when the read is satisfied, we avoid issuing any additional
1387 reads, which could block indefinitely (e.g. on a socket).
1388 See issue #9550. */
1389 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001390 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001391 if (r == -1)
1392 goto error;
1393 if (r == 0 || r == -2) {
1394 /* EOF occurred or read() would block. */
1395 if (r == 0 || written > 0) {
1396 if (_PyBytes_Resize(&res, written))
1397 goto error;
1398 return res;
1399 }
1400 Py_DECREF(res);
1401 Py_INCREF(Py_None);
1402 return Py_None;
1403 }
1404 if (remaining > r) {
1405 memcpy(out + written, self->buffer + self->pos, r);
1406 written += r;
1407 self->pos += r;
1408 remaining -= r;
1409 }
1410 else if (remaining > 0) {
1411 memcpy(out + written, self->buffer + self->pos, remaining);
1412 written += remaining;
1413 self->pos += remaining;
1414 remaining = 0;
1415 }
1416 if (remaining == 0)
1417 break;
1418 }
1419
1420 return res;
1421
1422error:
1423 Py_XDECREF(res);
1424 return NULL;
1425}
1426
1427static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001428_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001429{
1430 Py_ssize_t have, r;
1431
1432 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1433 /* Constraints:
1434 1. we don't want to advance the file position.
1435 2. we don't want to lose block alignment, so we can't shift the buffer
1436 to make some place.
1437 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1438 */
1439 if (have > 0) {
1440 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1441 }
1442
1443 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001444 _bufferedreader_reset_buf(self);
1445 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001446 if (r == -1)
1447 return NULL;
1448 if (r == -2)
1449 r = 0;
1450 self->pos = 0;
1451 return PyBytes_FromStringAndSize(self->buffer, r);
1452}
1453
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001454static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001455 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001456 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1457 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1458 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1459 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1460 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1461 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1462 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1463 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001464
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001465 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1466 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1467 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1468 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1469 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1470 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1471 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001472 {NULL, NULL}
1473};
1474
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001475static PyMemberDef bufferedreader_members[] = {
1476 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001477 {NULL}
1478};
1479
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001480static PyGetSetDef bufferedreader_getset[] = {
1481 {"closed", (getter)buffered_closed_get, NULL, NULL},
1482 {"name", (getter)buffered_name_get, NULL, NULL},
1483 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001484 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001485};
1486
1487
1488PyTypeObject PyBufferedReader_Type = {
1489 PyVarObject_HEAD_INIT(NULL, 0)
1490 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001491 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001492 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001493 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001494 0, /*tp_print*/
1495 0, /*tp_getattr*/
1496 0, /*tp_setattr*/
1497 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001498 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001499 0, /*tp_as_number*/
1500 0, /*tp_as_sequence*/
1501 0, /*tp_as_mapping*/
1502 0, /*tp_hash */
1503 0, /*tp_call*/
1504 0, /*tp_str*/
1505 0, /*tp_getattro*/
1506 0, /*tp_setattro*/
1507 0, /*tp_as_buffer*/
1508 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1509 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001510 bufferedreader_doc, /* tp_doc */
1511 (traverseproc)buffered_traverse, /* tp_traverse */
1512 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001513 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001514 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001515 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001516 (iternextfunc)buffered_iternext, /* tp_iternext */
1517 bufferedreader_methods, /* tp_methods */
1518 bufferedreader_members, /* tp_members */
1519 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001520 0, /* tp_base */
1521 0, /* tp_dict */
1522 0, /* tp_descr_get */
1523 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001524 offsetof(buffered, dict), /* tp_dictoffset */
1525 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001526 0, /* tp_alloc */
1527 PyType_GenericNew, /* tp_new */
1528};
1529
1530
Benjamin Peterson59406a92009-03-26 17:10:29 +00001531
1532static int
1533complain_about_max_buffer_size(void)
1534{
1535 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1536 "max_buffer_size is deprecated", 1) < 0)
1537 return 0;
1538 return 1;
1539}
1540
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001541/*
1542 * class BufferedWriter
1543 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001544PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001545 "A buffer for a writeable sequential RawIO object.\n"
1546 "\n"
1547 "The constructor creates a BufferedWriter for the given writeable raw\n"
1548 "stream. If the buffer_size is not given, it defaults to\n"
1549 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1550 );
1551
1552static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001553_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001554{
1555 self->write_pos = 0;
1556 self->write_end = -1;
1557}
1558
1559static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001560bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001561{
1562 /* TODO: properly deprecate max_buffer_size */
1563 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1564 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001565 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001566 PyObject *raw;
1567
1568 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001569 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001570
1571 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1572 &raw, &buffer_size, &max_buffer_size)) {
1573 return -1;
1574 }
1575
Benjamin Peterson59406a92009-03-26 17:10:29 +00001576 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1577 return -1;
1578
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001579 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001580 return -1;
1581
1582 Py_CLEAR(self->raw);
1583 Py_INCREF(raw);
1584 self->raw = raw;
1585 self->readable = 0;
1586 self->writable = 1;
1587
1588 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001589 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001590 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001591 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001592 self->pos = 0;
1593
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001594 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1595 Py_TYPE(raw) == &PyFileIO_Type);
1596
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001597 self->ok = 1;
1598 return 0;
1599}
1600
1601static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001602_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001603{
1604 Py_buffer buf;
1605 PyObject *memobj, *res;
1606 Py_ssize_t n;
1607 /* NOTE: the buffer needn't be released as its object is NULL. */
1608 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1609 return -1;
1610 memobj = PyMemoryView_FromBuffer(&buf);
1611 if (memobj == NULL)
1612 return -1;
1613 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1614 Py_DECREF(memobj);
1615 if (res == NULL)
1616 return -1;
1617 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1618 Py_DECREF(res);
1619 if (n < 0 || n > len) {
1620 PyErr_Format(PyExc_IOError,
1621 "raw write() returned invalid length %zd "
1622 "(should have been between 0 and %zd)", n, len);
1623 return -1;
1624 }
1625 if (n > 0 && self->abs_pos != -1)
1626 self->abs_pos += n;
1627 return n;
1628}
1629
1630/* `restore_pos` is 1 if we need to restore the raw stream position at
1631 the end, 0 otherwise. */
1632static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001633_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001634{
1635 Py_ssize_t written = 0;
1636 Py_off_t n, rewind;
1637
1638 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1639 goto end;
1640 /* First, rewind */
1641 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1642 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001643 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001644 if (n < 0) {
1645 goto error;
1646 }
1647 self->raw_pos -= rewind;
1648 }
1649 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001650 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001651 self->buffer + self->write_pos,
1652 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1653 Py_off_t, Py_ssize_t));
1654 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001655 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001656 if (w == NULL)
1657 goto error;
1658 self->write_pos += *w;
1659 self->raw_pos = self->write_pos;
1660 written += *w;
1661 *w = written;
1662 /* Already re-raised */
1663 goto error;
1664 }
1665 self->write_pos += n;
1666 self->raw_pos = self->write_pos;
1667 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1668 }
1669
1670 if (restore_pos) {
1671 Py_off_t forward = rewind - written;
1672 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001673 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001674 if (n < 0) {
1675 goto error;
1676 }
1677 self->raw_pos += forward;
1678 }
1679 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001680 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001681
1682end:
1683 Py_RETURN_NONE;
1684
1685error:
1686 return NULL;
1687}
1688
1689static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001690bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001691{
1692 PyObject *res = NULL;
1693 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001694 Py_ssize_t written, avail, remaining;
1695 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001696
1697 CHECK_INITIALIZED(self)
1698 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1699 return NULL;
1700 }
1701
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001702 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001703 PyErr_SetString(PyExc_ValueError, "write to closed file");
1704 PyBuffer_Release(&buf);
1705 return NULL;
1706 }
1707
1708 ENTER_BUFFERED(self)
1709
1710 /* Fast path: the data to write can be fully buffered. */
1711 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1712 self->pos = 0;
1713 self->raw_pos = 0;
1714 }
1715 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1716 if (buf.len <= avail) {
1717 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1718 if (!VALID_WRITE_BUFFER(self)) {
1719 self->write_pos = self->pos;
1720 }
1721 ADJUST_POSITION(self, self->pos + buf.len);
1722 if (self->pos > self->write_end)
1723 self->write_end = self->pos;
1724 written = buf.len;
1725 goto end;
1726 }
1727
1728 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001729 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001730 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001731 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001732 if (w == NULL)
1733 goto error;
1734 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001735 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001736 /* Make some place by shifting the buffer. */
1737 assert(VALID_WRITE_BUFFER(self));
1738 memmove(self->buffer, self->buffer + self->write_pos,
1739 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1740 Py_off_t, Py_ssize_t));
1741 self->write_end -= self->write_pos;
1742 self->raw_pos -= self->write_pos;
1743 self->pos -= self->write_pos;
1744 self->write_pos = 0;
1745 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1746 Py_off_t, Py_ssize_t);
1747 if (buf.len <= avail) {
1748 /* Everything can be buffered */
1749 PyErr_Clear();
1750 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1751 self->write_end += buf.len;
1752 written = buf.len;
1753 goto end;
1754 }
1755 /* Buffer as much as possible. */
1756 memcpy(self->buffer + self->write_end, buf.buf, avail);
1757 self->write_end += avail;
1758 /* Already re-raised */
1759 *w = avail;
1760 goto error;
1761 }
1762 Py_CLEAR(res);
1763
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001764 /* Adjust the raw stream position if it is away from the logical stream
1765 position. This happens if the read buffer has been filled but not
1766 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1767 the raw stream by itself).
1768 Fixes issue #6629.
1769 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001770 offset = RAW_OFFSET(self);
1771 if (offset != 0) {
1772 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001773 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001774 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001775 }
1776
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001777 /* Then write buf itself. At this point the buffer has been emptied. */
1778 remaining = buf.len;
1779 written = 0;
1780 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001781 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001782 self, (char *) buf.buf + written, buf.len - written);
1783 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001784 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001785 if (w == NULL)
1786 goto error;
1787 written += *w;
1788 remaining -= *w;
1789 if (remaining > self->buffer_size) {
1790 /* Can't buffer everything, still buffer as much as possible */
1791 memcpy(self->buffer,
1792 (char *) buf.buf + written, self->buffer_size);
1793 self->raw_pos = 0;
1794 ADJUST_POSITION(self, self->buffer_size);
1795 self->write_end = self->buffer_size;
1796 *w = written + self->buffer_size;
1797 /* Already re-raised */
1798 goto error;
1799 }
1800 PyErr_Clear();
1801 break;
1802 }
1803 written += n;
1804 remaining -= n;
1805 }
1806 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001807 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001808 if (remaining > 0) {
1809 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1810 written += remaining;
1811 }
1812 self->write_pos = 0;
1813 /* TODO: sanity check (remaining >= 0) */
1814 self->write_end = remaining;
1815 ADJUST_POSITION(self, remaining);
1816 self->raw_pos = 0;
1817
1818end:
1819 res = PyLong_FromSsize_t(written);
1820
1821error:
1822 LEAVE_BUFFERED(self)
1823 PyBuffer_Release(&buf);
1824 return res;
1825}
1826
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001827static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001828 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001829 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1830 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1831 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1832 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1833 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1834 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1835 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001836
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001837 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1838 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1839 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1840 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1841 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001842 {NULL, NULL}
1843};
1844
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001845static PyMemberDef bufferedwriter_members[] = {
1846 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001847 {NULL}
1848};
1849
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001850static PyGetSetDef bufferedwriter_getset[] = {
1851 {"closed", (getter)buffered_closed_get, NULL, NULL},
1852 {"name", (getter)buffered_name_get, NULL, NULL},
1853 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001854 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001855};
1856
1857
1858PyTypeObject PyBufferedWriter_Type = {
1859 PyVarObject_HEAD_INIT(NULL, 0)
1860 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001861 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001862 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001863 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001864 0, /*tp_print*/
1865 0, /*tp_getattr*/
1866 0, /*tp_setattr*/
1867 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001868 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001869 0, /*tp_as_number*/
1870 0, /*tp_as_sequence*/
1871 0, /*tp_as_mapping*/
1872 0, /*tp_hash */
1873 0, /*tp_call*/
1874 0, /*tp_str*/
1875 0, /*tp_getattro*/
1876 0, /*tp_setattro*/
1877 0, /*tp_as_buffer*/
1878 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1879 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001880 bufferedwriter_doc, /* tp_doc */
1881 (traverseproc)buffered_traverse, /* tp_traverse */
1882 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001883 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001884 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001885 0, /* tp_iter */
1886 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001887 bufferedwriter_methods, /* tp_methods */
1888 bufferedwriter_members, /* tp_members */
1889 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001890 0, /* tp_base */
1891 0, /* tp_dict */
1892 0, /* tp_descr_get */
1893 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001894 offsetof(buffered, dict), /* tp_dictoffset */
1895 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001896 0, /* tp_alloc */
1897 PyType_GenericNew, /* tp_new */
1898};
1899
1900
1901
1902/*
1903 * BufferedRWPair
1904 */
1905
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001906PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001907 "A buffered reader and writer object together.\n"
1908 "\n"
1909 "A buffered reader object and buffered writer object put together to\n"
1910 "form a sequential IO object that can read and write. This is typically\n"
1911 "used with a socket or two-way pipe.\n"
1912 "\n"
1913 "reader and writer are RawIOBase objects that are readable and\n"
1914 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001915 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001916 );
1917
1918/* XXX The usefulness of this (compared to having two separate IO objects) is
1919 * questionable.
1920 */
1921
1922typedef struct {
1923 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001924 buffered *reader;
1925 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001926 PyObject *dict;
1927 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001928} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001929
1930static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001931bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001932{
1933 PyObject *reader, *writer;
1934 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001935 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001936
1937 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1938 &buffer_size, &max_buffer_size)) {
1939 return -1;
1940 }
1941
Benjamin Peterson59406a92009-03-26 17:10:29 +00001942 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1943 return -1;
1944
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001945 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001946 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001947 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001948 return -1;
1949
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001950 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001951 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001952 if (self->reader == NULL)
1953 return -1;
1954
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001955 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001956 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001957 if (self->writer == NULL) {
1958 Py_CLEAR(self->reader);
1959 return -1;
1960 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001961
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001962 return 0;
1963}
1964
1965static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001966bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001967{
1968 Py_VISIT(self->dict);
1969 return 0;
1970}
1971
1972static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001973bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001974{
1975 Py_CLEAR(self->reader);
1976 Py_CLEAR(self->writer);
1977 Py_CLEAR(self->dict);
1978 return 0;
1979}
1980
1981static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001982bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001983{
1984 _PyObject_GC_UNTRACK(self);
1985 Py_CLEAR(self->reader);
1986 Py_CLEAR(self->writer);
1987 Py_CLEAR(self->dict);
1988 Py_TYPE(self)->tp_free((PyObject *) self);
1989}
1990
1991static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001992_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001993{
1994 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1995 PyObject *ret;
1996
1997 if (func == NULL) {
1998 PyErr_SetString(PyExc_AttributeError, name);
1999 return NULL;
2000 }
2001
2002 ret = PyObject_CallObject(func, args);
2003 Py_DECREF(func);
2004 return ret;
2005}
2006
2007static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002008bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002009{
2010 return _forward_call(self->reader, "read", args);
2011}
2012
2013static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002014bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002015{
2016 return _forward_call(self->reader, "peek", args);
2017}
2018
2019static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002020bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002021{
2022 return _forward_call(self->reader, "read1", args);
2023}
2024
2025static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002026bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002027{
2028 return _forward_call(self->reader, "readinto", args);
2029}
2030
2031static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002032bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002033{
2034 return _forward_call(self->writer, "write", args);
2035}
2036
2037static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002038bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002039{
2040 return _forward_call(self->writer, "flush", args);
2041}
2042
2043static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002044bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002045{
2046 return _forward_call(self->reader, "readable", args);
2047}
2048
2049static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002050bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002051{
2052 return _forward_call(self->writer, "writable", args);
2053}
2054
2055static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002056bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002057{
2058 PyObject *ret = _forward_call(self->writer, "close", args);
2059 if (ret == NULL)
2060 return NULL;
2061 Py_DECREF(ret);
2062
2063 return _forward_call(self->reader, "close", args);
2064}
2065
2066static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002067bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002068{
2069 PyObject *ret = _forward_call(self->writer, "isatty", args);
2070
2071 if (ret != Py_False) {
2072 /* either True or exception */
2073 return ret;
2074 }
2075 Py_DECREF(ret);
2076
2077 return _forward_call(self->reader, "isatty", args);
2078}
2079
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002080static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002081bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002082{
2083 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2084}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002085
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002086static PyMethodDef bufferedrwpair_methods[] = {
2087 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2088 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2089 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2090 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002091
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002092 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2093 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002094
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002095 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2096 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002097
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002098 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2099 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002100
2101 {NULL, NULL}
2102};
2103
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002104static PyGetSetDef bufferedrwpair_getset[] = {
2105 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002106 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002107};
2108
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002109PyTypeObject PyBufferedRWPair_Type = {
2110 PyVarObject_HEAD_INIT(NULL, 0)
2111 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002112 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002113 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002114 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002115 0, /*tp_print*/
2116 0, /*tp_getattr*/
2117 0, /*tp_setattr*/
2118 0, /*tp_compare */
2119 0, /*tp_repr*/
2120 0, /*tp_as_number*/
2121 0, /*tp_as_sequence*/
2122 0, /*tp_as_mapping*/
2123 0, /*tp_hash */
2124 0, /*tp_call*/
2125 0, /*tp_str*/
2126 0, /*tp_getattro*/
2127 0, /*tp_setattro*/
2128 0, /*tp_as_buffer*/
2129 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2130 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002131 bufferedrwpair_doc, /* tp_doc */
2132 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2133 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002134 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002135 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002136 0, /* tp_iter */
2137 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002138 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002139 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002140 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002141 0, /* tp_base */
2142 0, /* tp_dict */
2143 0, /* tp_descr_get */
2144 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002145 offsetof(rwpair, dict), /* tp_dictoffset */
2146 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002147 0, /* tp_alloc */
2148 PyType_GenericNew, /* tp_new */
2149};
2150
2151
2152
2153/*
2154 * BufferedRandom
2155 */
2156
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002157PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002158 "A buffered interface to random access streams.\n"
2159 "\n"
2160 "The constructor creates a reader and writer for a seekable stream,\n"
2161 "raw, given in the first argument. If the buffer_size is omitted it\n"
2162 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2163 );
2164
2165static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002166bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002167{
2168 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2169 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002170 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002171 PyObject *raw;
2172
2173 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002174 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002175
2176 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2177 &raw, &buffer_size, &max_buffer_size)) {
2178 return -1;
2179 }
2180
Benjamin Peterson59406a92009-03-26 17:10:29 +00002181 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2182 return -1;
2183
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002184 if (_PyIOBase_check_seekable(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_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002187 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002188 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002189 return -1;
2190
2191 Py_CLEAR(self->raw);
2192 Py_INCREF(raw);
2193 self->raw = raw;
2194 self->buffer_size = buffer_size;
2195 self->readable = 1;
2196 self->writable = 1;
2197
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002198 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002199 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002200 _bufferedreader_reset_buf(self);
2201 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002202 self->pos = 0;
2203
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002204 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2205 Py_TYPE(raw) == &PyFileIO_Type);
2206
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002207 self->ok = 1;
2208 return 0;
2209}
2210
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002211static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002212 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002213 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2214 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2215 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2216 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2217 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2218 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2219 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002220
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002221 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002222
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002223 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2224 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2225 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2226 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2227 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2228 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2229 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2230 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2231 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002232 {NULL, NULL}
2233};
2234
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002235static PyMemberDef bufferedrandom_members[] = {
2236 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002237 {NULL}
2238};
2239
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002240static PyGetSetDef bufferedrandom_getset[] = {
2241 {"closed", (getter)buffered_closed_get, NULL, NULL},
2242 {"name", (getter)buffered_name_get, NULL, NULL},
2243 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002244 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002245};
2246
2247
2248PyTypeObject PyBufferedRandom_Type = {
2249 PyVarObject_HEAD_INIT(NULL, 0)
2250 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002251 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002252 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002253 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002254 0, /*tp_print*/
2255 0, /*tp_getattr*/
2256 0, /*tp_setattr*/
2257 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002258 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002259 0, /*tp_as_number*/
2260 0, /*tp_as_sequence*/
2261 0, /*tp_as_mapping*/
2262 0, /*tp_hash */
2263 0, /*tp_call*/
2264 0, /*tp_str*/
2265 0, /*tp_getattro*/
2266 0, /*tp_setattro*/
2267 0, /*tp_as_buffer*/
2268 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2269 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002270 bufferedrandom_doc, /* tp_doc */
2271 (traverseproc)buffered_traverse, /* tp_traverse */
2272 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002273 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002274 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002275 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002276 (iternextfunc)buffered_iternext, /* tp_iternext */
2277 bufferedrandom_methods, /* tp_methods */
2278 bufferedrandom_members, /* tp_members */
2279 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002280 0, /* tp_base */
2281 0, /*tp_dict*/
2282 0, /* tp_descr_get */
2283 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002284 offsetof(buffered, dict), /*tp_dictoffset*/
2285 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002286 0, /* tp_alloc */
2287 PyType_GenericNew, /* tp_new */
2288};
2289