blob: 07fe0a1d81d63c6cb5ba77fdda31db03a6e9b89a [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
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000639 self->lock = PyThread_allocate_lock();
640 if (self->lock == NULL) {
641 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
642 return -1;
643 }
Georg Brandldfd73442009-04-05 11:47:34 +0000644#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000645 /* Find out whether buffer_size is a power of 2 */
646 /* XXX is this optimization useful? */
647 for (n = self->buffer_size - 1; n & 1; n >>= 1)
648 ;
649 if (n == 0)
650 self->buffer_mask = self->buffer_size - 1;
651 else
652 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000653 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000654 PyErr_Clear();
655 return 0;
656}
657
658/*
659 * Shared methods and wrappers
660 */
661
662static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000663buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000664{
665 PyObject *res;
666
667 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000668 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000669
670 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000671 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000672 if (res != NULL && self->readable) {
673 /* Rewind the raw stream so that its position corresponds to
674 the current logical position. */
675 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000676 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000677 if (n == -1)
678 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000679 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000680 }
681 LEAVE_BUFFERED(self)
682
683 return res;
684}
685
686static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000687buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000688{
689 Py_ssize_t n = 0;
690 PyObject *res = NULL;
691
692 CHECK_INITIALIZED(self)
693 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
694 return NULL;
695 }
696
697 ENTER_BUFFERED(self)
698
699 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000700 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000701 if (res == NULL)
702 goto end;
703 Py_CLEAR(res);
704 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000705 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000706
707end:
708 LEAVE_BUFFERED(self)
709 return res;
710}
711
712static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000713buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000714{
715 Py_ssize_t n = -1;
716 PyObject *res;
717
718 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000719 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000720 return NULL;
721 }
722 if (n < -1) {
723 PyErr_SetString(PyExc_ValueError,
724 "read length must be positive or -1");
725 return NULL;
726 }
727
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000728 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000729
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000730 if (n == -1) {
731 /* The number of bytes is unspecified, read until the end of stream */
732 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000733 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000734 LEAVE_BUFFERED(self)
735 }
736 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000737 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000738 if (res == Py_None) {
739 Py_DECREF(res);
740 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000741 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000742 LEAVE_BUFFERED(self)
743 }
744 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000745
746 return res;
747}
748
749static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000750buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000751{
752 Py_ssize_t n, have, r;
753 PyObject *res = NULL;
754
755 CHECK_INITIALIZED(self)
756 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
757 return NULL;
758 }
759
760 if (n < 0) {
761 PyErr_SetString(PyExc_ValueError,
762 "read length must be positive");
763 return NULL;
764 }
765 if (n == 0)
766 return PyBytes_FromStringAndSize(NULL, 0);
767
768 ENTER_BUFFERED(self)
769
770 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000771 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000772 if (res == NULL)
773 goto end;
774 Py_CLEAR(res);
775 }
776
777 /* Return up to n bytes. If at least one byte is buffered, we
778 only return buffered bytes. Otherwise, we do one raw read. */
779
780 /* XXX: this mimicks the io.py implementation but is probably wrong.
781 If we need to read from the raw stream, then we could actually read
782 all `n` bytes asked by the caller (and possibly more, so as to fill
783 our buffer for the next reads). */
784
785 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
786 if (have > 0) {
787 if (n > have)
788 n = have;
789 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
790 if (res == NULL)
791 goto end;
792 self->pos += n;
793 goto end;
794 }
795
796 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000797 _bufferedreader_reset_buf(self);
798 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000799 if (r == -1)
800 goto end;
801 if (r == -2)
802 r = 0;
803 if (n > r)
804 n = r;
805 res = PyBytes_FromStringAndSize(self->buffer, n);
806 if (res == NULL)
807 goto end;
808 self->pos = n;
809
810end:
811 LEAVE_BUFFERED(self)
812 return res;
813}
814
815static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000816buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000817{
818 PyObject *res = NULL;
819
820 CHECK_INITIALIZED(self)
821
822 /* TODO: use raw.readinto() instead! */
823 if (self->writable) {
824 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000825 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000826 LEAVE_BUFFERED(self)
827 if (res == NULL)
828 goto end;
829 Py_DECREF(res);
830 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000831 res = bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000832
833end:
834 return res;
835}
836
837static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000838_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000839{
840 PyObject *res = NULL;
841 PyObject *chunks = NULL;
842 Py_ssize_t n, written = 0;
843 const char *start, *s, *end;
844
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000845 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000846
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000847 /* First, try to find a line in the buffer. This can run unlocked because
848 the calls to the C API are simple enough that they can't trigger
849 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000850 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
851 if (limit >= 0 && n > limit)
852 n = limit;
853 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000854 s = memchr(start, '\n', n);
855 if (s != NULL) {
856 res = PyBytes_FromStringAndSize(start, s - start + 1);
857 if (res != NULL)
858 self->pos += s - start + 1;
859 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000860 }
861 if (n == limit) {
862 res = PyBytes_FromStringAndSize(start, n);
863 if (res != NULL)
864 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000865 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000866 }
867
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000868 ENTER_BUFFERED(self)
869
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000870 /* Now we try to get some more from the raw stream */
871 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000872 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000873 if (res == NULL)
874 goto end;
875 Py_CLEAR(res);
876 }
877 chunks = PyList_New(0);
878 if (chunks == NULL)
879 goto end;
880 if (n > 0) {
881 res = PyBytes_FromStringAndSize(start, n);
882 if (res == NULL)
883 goto end;
884 if (PyList_Append(chunks, res) < 0) {
885 Py_CLEAR(res);
886 goto end;
887 }
888 Py_CLEAR(res);
889 written += n;
890 if (limit >= 0)
891 limit -= n;
892 }
893
894 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000895 _bufferedreader_reset_buf(self);
896 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000897 if (n == -1)
898 goto end;
899 if (n <= 0)
900 break;
901 if (limit >= 0 && n > limit)
902 n = limit;
903 start = self->buffer;
904 end = start + n;
905 s = start;
906 while (s < end) {
907 if (*s++ == '\n') {
908 res = PyBytes_FromStringAndSize(start, s - start);
909 if (res == NULL)
910 goto end;
911 self->pos = s - start;
912 goto found;
913 }
914 }
915 res = PyBytes_FromStringAndSize(start, n);
916 if (res == NULL)
917 goto end;
918 if (n == limit) {
919 self->pos = n;
920 break;
921 }
922 if (PyList_Append(chunks, res) < 0) {
923 Py_CLEAR(res);
924 goto end;
925 }
926 Py_CLEAR(res);
927 written += n;
928 if (limit >= 0)
929 limit -= n;
930 }
931found:
932 if (res != NULL && PyList_Append(chunks, res) < 0) {
933 Py_CLEAR(res);
934 goto end;
935 }
936 Py_CLEAR(res);
937 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
938
939end:
940 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000941end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000942 Py_XDECREF(chunks);
943 return res;
944}
945
946static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000947buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000948{
949 Py_ssize_t limit = -1;
950
951 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000952 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000953 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000954 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000955}
956
957
958static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000959buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000960{
961 Py_off_t pos;
962
963 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000964 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000965 if (pos == -1)
966 return NULL;
967 pos -= RAW_OFFSET(self);
968 /* TODO: sanity check (pos >= 0) */
969 return PyLong_FromOff_t(pos);
970}
971
972static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000973buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000974{
975 Py_off_t target, n;
976 int whence = 0;
977 PyObject *targetobj, *res = NULL;
978
979 CHECK_INITIALIZED(self)
980 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
981 return NULL;
982 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000983 if (whence < 0 || whence > 2) {
984 PyErr_Format(PyExc_ValueError,
985 "whence must be between 0 and 2, not %d", whence);
986 return NULL;
987 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000988
989 CHECK_CLOSED(self, "seek of closed file")
990
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000991 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
992 if (target == -1 && PyErr_Occurred())
993 return NULL;
994
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000995 if (whence != 2 && self->readable) {
996 Py_off_t current, avail;
997 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000998 so as to return quickly if possible. Also, we needn't take the
999 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001000 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001001 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1002 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001003 current = RAW_TELL(self);
1004 avail = READAHEAD(self);
1005 if (avail > 0) {
1006 Py_off_t offset;
1007 if (whence == 0)
1008 offset = target - (current - RAW_OFFSET(self));
1009 else
1010 offset = target;
1011 if (offset >= -self->pos && offset <= avail) {
1012 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001013 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001014 }
1015 }
1016 }
1017
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001018 ENTER_BUFFERED(self)
1019
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001020 /* Fallback: invoke raw seek() method and clear buffer */
1021 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001022 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001023 if (res == NULL)
1024 goto end;
1025 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001026 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001027 }
1028
1029 /* TODO: align on block boundary and read buffer if needed? */
1030 if (whence == 1)
1031 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001032 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001033 if (n == -1)
1034 goto end;
1035 self->raw_pos = -1;
1036 res = PyLong_FromOff_t(n);
1037 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001038 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001039
1040end:
1041 LEAVE_BUFFERED(self)
1042 return res;
1043}
1044
1045static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001046buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001047{
1048 PyObject *pos = Py_None;
1049 PyObject *res = NULL;
1050
1051 CHECK_INITIALIZED(self)
1052 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1053 return NULL;
1054 }
1055
1056 ENTER_BUFFERED(self)
1057
1058 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001059 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001060 if (res == NULL)
1061 goto end;
1062 Py_CLEAR(res);
1063 }
1064 if (self->readable) {
1065 if (pos == Py_None) {
1066 /* Rewind the raw stream so that its position corresponds to
1067 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001068 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001069 goto end;
1070 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001071 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001072 }
1073 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1074 if (res == NULL)
1075 goto end;
1076 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001077 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001078 PyErr_Clear();
1079
1080end:
1081 LEAVE_BUFFERED(self)
1082 return res;
1083}
1084
1085static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001086buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001087{
1088 PyObject *line;
1089 PyTypeObject *tp;
1090
1091 CHECK_INITIALIZED(self);
1092
1093 tp = Py_TYPE(self);
1094 if (tp == &PyBufferedReader_Type ||
1095 tp == &PyBufferedRandom_Type) {
1096 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001097 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001098 }
1099 else {
1100 line = PyObject_CallMethodObjArgs((PyObject *)self,
1101 _PyIO_str_readline, NULL);
1102 if (line && !PyBytes_Check(line)) {
1103 PyErr_Format(PyExc_IOError,
1104 "readline() should have returned a bytes object, "
1105 "not '%.200s'", Py_TYPE(line)->tp_name);
1106 Py_DECREF(line);
1107 return NULL;
1108 }
1109 }
1110
1111 if (line == NULL)
1112 return NULL;
1113
1114 if (PyBytes_GET_SIZE(line) == 0) {
1115 /* Reached EOF or would have blocked */
1116 Py_DECREF(line);
1117 return NULL;
1118 }
1119
1120 return line;
1121}
1122
Antoine Pitrou716c4442009-05-23 19:04:03 +00001123static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001124buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001125{
1126 PyObject *nameobj, *res;
1127
1128 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1129 if (nameobj == NULL) {
1130 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1131 PyErr_Clear();
1132 else
1133 return NULL;
1134 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1135 }
1136 else {
1137 res = PyUnicode_FromFormat("<%s name=%R>",
1138 Py_TYPE(self)->tp_name, nameobj);
1139 Py_DECREF(nameobj);
1140 }
1141 return res;
1142}
1143
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001144/*
1145 * class BufferedReader
1146 */
1147
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001148PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001149 "Create a new buffered reader using the given readable raw IO object.");
1150
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001151static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001152{
1153 self->read_end = -1;
1154}
1155
1156static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001157bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001158{
1159 char *kwlist[] = {"raw", "buffer_size", NULL};
1160 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1161 PyObject *raw;
1162
1163 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001164 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001165
1166 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1167 &raw, &buffer_size)) {
1168 return -1;
1169 }
1170
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001171 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001172 return -1;
1173
1174 Py_CLEAR(self->raw);
1175 Py_INCREF(raw);
1176 self->raw = raw;
1177 self->buffer_size = buffer_size;
1178 self->readable = 1;
1179 self->writable = 0;
1180
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001181 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001182 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001183 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001184
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001185 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1186 Py_TYPE(raw) == &PyFileIO_Type);
1187
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001188 self->ok = 1;
1189 return 0;
1190}
1191
1192static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001193_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001194{
1195 Py_buffer buf;
1196 PyObject *memobj, *res;
1197 Py_ssize_t n;
1198 /* NOTE: the buffer needn't be released as its object is NULL. */
1199 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1200 return -1;
1201 memobj = PyMemoryView_FromBuffer(&buf);
1202 if (memobj == NULL)
1203 return -1;
1204 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1205 Py_DECREF(memobj);
1206 if (res == NULL)
1207 return -1;
1208 if (res == Py_None) {
1209 /* Non-blocking stream would have blocked. Special return code! */
1210 Py_DECREF(res);
1211 return -2;
1212 }
1213 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1214 Py_DECREF(res);
1215 if (n < 0 || n > len) {
1216 PyErr_Format(PyExc_IOError,
1217 "raw readinto() returned invalid length %zd "
1218 "(should have been between 0 and %zd)", n, len);
1219 return -1;
1220 }
1221 if (n > 0 && self->abs_pos != -1)
1222 self->abs_pos += n;
1223 return n;
1224}
1225
1226static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001227_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001228{
1229 Py_ssize_t start, len, n;
1230 if (VALID_READ_BUFFER(self))
1231 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1232 else
1233 start = 0;
1234 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001235 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001236 if (n <= 0)
1237 return n;
1238 self->read_end = start + n;
1239 self->raw_pos = start + n;
1240 return n;
1241}
1242
1243static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001244_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001245{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001246 Py_ssize_t current_size;
1247 PyObject *res, *data = NULL;
1248 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001249
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001250 if (chunks == NULL)
1251 return NULL;
1252
1253 /* First copy what we have in the current buffer. */
1254 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1255 if (current_size) {
1256 data = PyBytes_FromStringAndSize(
1257 self->buffer + self->pos, current_size);
1258 if (data == NULL) {
1259 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001260 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001261 }
1262 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001263 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001264 /* We're going past the buffer's bounds, flush it */
1265 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001266 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001267 if (res == NULL) {
1268 Py_DECREF(chunks);
1269 return NULL;
1270 }
1271 Py_CLEAR(res);
1272 }
1273 while (1) {
1274 if (data) {
1275 if (PyList_Append(chunks, data) < 0) {
1276 Py_DECREF(data);
1277 Py_DECREF(chunks);
1278 return NULL;
1279 }
1280 Py_DECREF(data);
1281 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001282
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001283 /* Read until EOF or until read() would block. */
1284 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1285 if (data == NULL) {
1286 Py_DECREF(chunks);
1287 return NULL;
1288 }
1289 if (data != Py_None && !PyBytes_Check(data)) {
1290 Py_DECREF(data);
1291 Py_DECREF(chunks);
1292 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1293 return NULL;
1294 }
1295 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1296 if (current_size == 0) {
1297 Py_DECREF(chunks);
1298 return data;
1299 }
1300 else {
1301 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1302 Py_DECREF(data);
1303 Py_DECREF(chunks);
1304 return res;
1305 }
1306 }
1307 current_size += PyBytes_GET_SIZE(data);
1308 if (self->abs_pos != -1)
1309 self->abs_pos += PyBytes_GET_SIZE(data);
1310 }
1311}
1312
1313/* Read n bytes from the buffer if it can, otherwise return None.
1314 This function is simple enough that it can run unlocked. */
1315static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001316_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001317{
1318 Py_ssize_t current_size;
1319
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001320 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1321 if (n <= current_size) {
1322 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001323 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1324 if (res != NULL)
1325 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001326 return res;
1327 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001328 Py_RETURN_NONE;
1329}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001330
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001331/* Generic read function: read from the stream until enough bytes are read,
1332 * or until an EOF occurs or until read() would block.
1333 */
1334static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001335_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001336{
1337 PyObject *res = NULL;
1338 Py_ssize_t current_size, remaining, written;
1339 char *out;
1340
1341 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1342 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001343 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001344
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001345 res = PyBytes_FromStringAndSize(NULL, n);
1346 if (res == NULL)
1347 goto error;
1348 out = PyBytes_AS_STRING(res);
1349 remaining = n;
1350 written = 0;
1351 if (current_size > 0) {
1352 memcpy(out, self->buffer + self->pos, current_size);
1353 remaining -= current_size;
1354 written += current_size;
1355 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001356 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001357 while (remaining > 0) {
1358 /* We want to read a whole block at the end into buffer.
1359 If we had readv() we could do this in one pass. */
1360 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1361 if (r == 0)
1362 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001363 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001364 if (r == -1)
1365 goto error;
1366 if (r == 0 || r == -2) {
1367 /* EOF occurred or read() would block. */
1368 if (r == 0 || written > 0) {
1369 if (_PyBytes_Resize(&res, written))
1370 goto error;
1371 return res;
1372 }
1373 Py_DECREF(res);
1374 Py_INCREF(Py_None);
1375 return Py_None;
1376 }
1377 remaining -= r;
1378 written += r;
1379 }
1380 assert(remaining <= self->buffer_size);
1381 self->pos = 0;
1382 self->raw_pos = 0;
1383 self->read_end = 0;
1384 while (self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001385 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001386 if (r == -1)
1387 goto error;
1388 if (r == 0 || r == -2) {
1389 /* EOF occurred or read() would block. */
1390 if (r == 0 || written > 0) {
1391 if (_PyBytes_Resize(&res, written))
1392 goto error;
1393 return res;
1394 }
1395 Py_DECREF(res);
1396 Py_INCREF(Py_None);
1397 return Py_None;
1398 }
1399 if (remaining > r) {
1400 memcpy(out + written, self->buffer + self->pos, r);
1401 written += r;
1402 self->pos += r;
1403 remaining -= r;
1404 }
1405 else if (remaining > 0) {
1406 memcpy(out + written, self->buffer + self->pos, remaining);
1407 written += remaining;
1408 self->pos += remaining;
1409 remaining = 0;
1410 }
1411 if (remaining == 0)
1412 break;
1413 }
1414
1415 return res;
1416
1417error:
1418 Py_XDECREF(res);
1419 return NULL;
1420}
1421
1422static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001423_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001424{
1425 Py_ssize_t have, r;
1426
1427 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1428 /* Constraints:
1429 1. we don't want to advance the file position.
1430 2. we don't want to lose block alignment, so we can't shift the buffer
1431 to make some place.
1432 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1433 */
1434 if (have > 0) {
1435 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1436 }
1437
1438 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001439 _bufferedreader_reset_buf(self);
1440 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001441 if (r == -1)
1442 return NULL;
1443 if (r == -2)
1444 r = 0;
1445 self->pos = 0;
1446 return PyBytes_FromStringAndSize(self->buffer, r);
1447}
1448
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001449static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001450 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001451 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1452 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1453 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1454 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1455 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1456 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1457 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1458 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001459
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001460 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1461 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1462 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1463 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1464 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1465 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1466 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001467 {NULL, NULL}
1468};
1469
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001470static PyMemberDef bufferedreader_members[] = {
1471 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001472 {NULL}
1473};
1474
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001475static PyGetSetDef bufferedreader_getset[] = {
1476 {"closed", (getter)buffered_closed_get, NULL, NULL},
1477 {"name", (getter)buffered_name_get, NULL, NULL},
1478 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001479 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001480};
1481
1482
1483PyTypeObject PyBufferedReader_Type = {
1484 PyVarObject_HEAD_INIT(NULL, 0)
1485 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001486 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001487 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001488 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001489 0, /*tp_print*/
1490 0, /*tp_getattr*/
1491 0, /*tp_setattr*/
1492 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001493 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001494 0, /*tp_as_number*/
1495 0, /*tp_as_sequence*/
1496 0, /*tp_as_mapping*/
1497 0, /*tp_hash */
1498 0, /*tp_call*/
1499 0, /*tp_str*/
1500 0, /*tp_getattro*/
1501 0, /*tp_setattro*/
1502 0, /*tp_as_buffer*/
1503 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1504 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001505 bufferedreader_doc, /* tp_doc */
1506 (traverseproc)buffered_traverse, /* tp_traverse */
1507 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001508 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001509 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001510 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001511 (iternextfunc)buffered_iternext, /* tp_iternext */
1512 bufferedreader_methods, /* tp_methods */
1513 bufferedreader_members, /* tp_members */
1514 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001515 0, /* tp_base */
1516 0, /* tp_dict */
1517 0, /* tp_descr_get */
1518 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001519 offsetof(buffered, dict), /* tp_dictoffset */
1520 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001521 0, /* tp_alloc */
1522 PyType_GenericNew, /* tp_new */
1523};
1524
1525
Benjamin Peterson59406a92009-03-26 17:10:29 +00001526
1527static int
1528complain_about_max_buffer_size(void)
1529{
1530 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1531 "max_buffer_size is deprecated", 1) < 0)
1532 return 0;
1533 return 1;
1534}
1535
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001536/*
1537 * class BufferedWriter
1538 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001539PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001540 "A buffer for a writeable sequential RawIO object.\n"
1541 "\n"
1542 "The constructor creates a BufferedWriter for the given writeable raw\n"
1543 "stream. If the buffer_size is not given, it defaults to\n"
1544 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1545 );
1546
1547static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001548_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001549{
1550 self->write_pos = 0;
1551 self->write_end = -1;
1552}
1553
1554static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001555bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001556{
1557 /* TODO: properly deprecate max_buffer_size */
1558 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1559 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001560 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001561 PyObject *raw;
1562
1563 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001564 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001565
1566 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1567 &raw, &buffer_size, &max_buffer_size)) {
1568 return -1;
1569 }
1570
Benjamin Peterson59406a92009-03-26 17:10:29 +00001571 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1572 return -1;
1573
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001574 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001575 return -1;
1576
1577 Py_CLEAR(self->raw);
1578 Py_INCREF(raw);
1579 self->raw = raw;
1580 self->readable = 0;
1581 self->writable = 1;
1582
1583 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001584 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001585 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001586 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001587 self->pos = 0;
1588
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001589 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1590 Py_TYPE(raw) == &PyFileIO_Type);
1591
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001592 self->ok = 1;
1593 return 0;
1594}
1595
1596static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001597_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001598{
1599 Py_buffer buf;
1600 PyObject *memobj, *res;
1601 Py_ssize_t n;
1602 /* NOTE: the buffer needn't be released as its object is NULL. */
1603 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1604 return -1;
1605 memobj = PyMemoryView_FromBuffer(&buf);
1606 if (memobj == NULL)
1607 return -1;
1608 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1609 Py_DECREF(memobj);
1610 if (res == NULL)
1611 return -1;
1612 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1613 Py_DECREF(res);
1614 if (n < 0 || n > len) {
1615 PyErr_Format(PyExc_IOError,
1616 "raw write() returned invalid length %zd "
1617 "(should have been between 0 and %zd)", n, len);
1618 return -1;
1619 }
1620 if (n > 0 && self->abs_pos != -1)
1621 self->abs_pos += n;
1622 return n;
1623}
1624
1625/* `restore_pos` is 1 if we need to restore the raw stream position at
1626 the end, 0 otherwise. */
1627static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001628_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001629{
1630 Py_ssize_t written = 0;
1631 Py_off_t n, rewind;
1632
1633 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1634 goto end;
1635 /* First, rewind */
1636 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1637 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001638 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001639 if (n < 0) {
1640 goto error;
1641 }
1642 self->raw_pos -= rewind;
1643 }
1644 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001645 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001646 self->buffer + self->write_pos,
1647 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1648 Py_off_t, Py_ssize_t));
1649 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001650 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001651 if (w == NULL)
1652 goto error;
1653 self->write_pos += *w;
1654 self->raw_pos = self->write_pos;
1655 written += *w;
1656 *w = written;
1657 /* Already re-raised */
1658 goto error;
1659 }
1660 self->write_pos += n;
1661 self->raw_pos = self->write_pos;
1662 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1663 }
1664
1665 if (restore_pos) {
1666 Py_off_t forward = rewind - written;
1667 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001668 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001669 if (n < 0) {
1670 goto error;
1671 }
1672 self->raw_pos += forward;
1673 }
1674 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001675 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001676
1677end:
1678 Py_RETURN_NONE;
1679
1680error:
1681 return NULL;
1682}
1683
1684static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001685bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001686{
1687 PyObject *res = NULL;
1688 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001689 Py_ssize_t written, avail, remaining;
1690 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001691
1692 CHECK_INITIALIZED(self)
1693 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1694 return NULL;
1695 }
1696
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001697 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001698 PyErr_SetString(PyExc_ValueError, "write to closed file");
1699 PyBuffer_Release(&buf);
1700 return NULL;
1701 }
1702
1703 ENTER_BUFFERED(self)
1704
1705 /* Fast path: the data to write can be fully buffered. */
1706 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1707 self->pos = 0;
1708 self->raw_pos = 0;
1709 }
1710 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1711 if (buf.len <= avail) {
1712 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1713 if (!VALID_WRITE_BUFFER(self)) {
1714 self->write_pos = self->pos;
1715 }
1716 ADJUST_POSITION(self, self->pos + buf.len);
1717 if (self->pos > self->write_end)
1718 self->write_end = self->pos;
1719 written = buf.len;
1720 goto end;
1721 }
1722
1723 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001724 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001725 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001726 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001727 if (w == NULL)
1728 goto error;
1729 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001730 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001731 /* Make some place by shifting the buffer. */
1732 assert(VALID_WRITE_BUFFER(self));
1733 memmove(self->buffer, self->buffer + self->write_pos,
1734 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1735 Py_off_t, Py_ssize_t));
1736 self->write_end -= self->write_pos;
1737 self->raw_pos -= self->write_pos;
1738 self->pos -= self->write_pos;
1739 self->write_pos = 0;
1740 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1741 Py_off_t, Py_ssize_t);
1742 if (buf.len <= avail) {
1743 /* Everything can be buffered */
1744 PyErr_Clear();
1745 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1746 self->write_end += buf.len;
1747 written = buf.len;
1748 goto end;
1749 }
1750 /* Buffer as much as possible. */
1751 memcpy(self->buffer + self->write_end, buf.buf, avail);
1752 self->write_end += avail;
1753 /* Already re-raised */
1754 *w = avail;
1755 goto error;
1756 }
1757 Py_CLEAR(res);
1758
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001759 /* Adjust the raw stream position if it is away from the logical stream
1760 position. This happens if the read buffer has been filled but not
1761 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1762 the raw stream by itself).
1763 Fixes issue #6629.
1764 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001765 offset = RAW_OFFSET(self);
1766 if (offset != 0) {
1767 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001768 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001769 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001770 }
1771
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001772 /* Then write buf itself. At this point the buffer has been emptied. */
1773 remaining = buf.len;
1774 written = 0;
1775 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001776 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001777 self, (char *) buf.buf + written, buf.len - written);
1778 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001779 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001780 if (w == NULL)
1781 goto error;
1782 written += *w;
1783 remaining -= *w;
1784 if (remaining > self->buffer_size) {
1785 /* Can't buffer everything, still buffer as much as possible */
1786 memcpy(self->buffer,
1787 (char *) buf.buf + written, self->buffer_size);
1788 self->raw_pos = 0;
1789 ADJUST_POSITION(self, self->buffer_size);
1790 self->write_end = self->buffer_size;
1791 *w = written + self->buffer_size;
1792 /* Already re-raised */
1793 goto error;
1794 }
1795 PyErr_Clear();
1796 break;
1797 }
1798 written += n;
1799 remaining -= n;
1800 }
1801 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001802 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001803 if (remaining > 0) {
1804 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1805 written += remaining;
1806 }
1807 self->write_pos = 0;
1808 /* TODO: sanity check (remaining >= 0) */
1809 self->write_end = remaining;
1810 ADJUST_POSITION(self, remaining);
1811 self->raw_pos = 0;
1812
1813end:
1814 res = PyLong_FromSsize_t(written);
1815
1816error:
1817 LEAVE_BUFFERED(self)
1818 PyBuffer_Release(&buf);
1819 return res;
1820}
1821
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001822static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001823 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001824 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1825 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1826 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1827 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1828 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1829 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1830 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001831
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001832 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1833 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1834 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1835 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1836 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001837 {NULL, NULL}
1838};
1839
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001840static PyMemberDef bufferedwriter_members[] = {
1841 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001842 {NULL}
1843};
1844
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001845static PyGetSetDef bufferedwriter_getset[] = {
1846 {"closed", (getter)buffered_closed_get, NULL, NULL},
1847 {"name", (getter)buffered_name_get, NULL, NULL},
1848 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001849 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001850};
1851
1852
1853PyTypeObject PyBufferedWriter_Type = {
1854 PyVarObject_HEAD_INIT(NULL, 0)
1855 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001856 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001857 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001858 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001859 0, /*tp_print*/
1860 0, /*tp_getattr*/
1861 0, /*tp_setattr*/
1862 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001863 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001864 0, /*tp_as_number*/
1865 0, /*tp_as_sequence*/
1866 0, /*tp_as_mapping*/
1867 0, /*tp_hash */
1868 0, /*tp_call*/
1869 0, /*tp_str*/
1870 0, /*tp_getattro*/
1871 0, /*tp_setattro*/
1872 0, /*tp_as_buffer*/
1873 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1874 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001875 bufferedwriter_doc, /* tp_doc */
1876 (traverseproc)buffered_traverse, /* tp_traverse */
1877 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001878 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001879 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001880 0, /* tp_iter */
1881 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001882 bufferedwriter_methods, /* tp_methods */
1883 bufferedwriter_members, /* tp_members */
1884 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001885 0, /* tp_base */
1886 0, /* tp_dict */
1887 0, /* tp_descr_get */
1888 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001889 offsetof(buffered, dict), /* tp_dictoffset */
1890 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001891 0, /* tp_alloc */
1892 PyType_GenericNew, /* tp_new */
1893};
1894
1895
1896
1897/*
1898 * BufferedRWPair
1899 */
1900
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001901PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001902 "A buffered reader and writer object together.\n"
1903 "\n"
1904 "A buffered reader object and buffered writer object put together to\n"
1905 "form a sequential IO object that can read and write. This is typically\n"
1906 "used with a socket or two-way pipe.\n"
1907 "\n"
1908 "reader and writer are RawIOBase objects that are readable and\n"
1909 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001910 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001911 );
1912
1913/* XXX The usefulness of this (compared to having two separate IO objects) is
1914 * questionable.
1915 */
1916
1917typedef struct {
1918 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001919 buffered *reader;
1920 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001921 PyObject *dict;
1922 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001923} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001924
1925static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001926bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001927{
1928 PyObject *reader, *writer;
1929 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001930 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001931
1932 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1933 &buffer_size, &max_buffer_size)) {
1934 return -1;
1935 }
1936
Benjamin Peterson59406a92009-03-26 17:10:29 +00001937 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1938 return -1;
1939
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001940 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001941 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001942 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001943 return -1;
1944
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001945 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001946 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001947 if (self->reader == NULL)
1948 return -1;
1949
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001950 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001951 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001952 if (self->writer == NULL) {
1953 Py_CLEAR(self->reader);
1954 return -1;
1955 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001956
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001957 return 0;
1958}
1959
1960static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001961bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001962{
1963 Py_VISIT(self->dict);
1964 return 0;
1965}
1966
1967static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001968bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001969{
1970 Py_CLEAR(self->reader);
1971 Py_CLEAR(self->writer);
1972 Py_CLEAR(self->dict);
1973 return 0;
1974}
1975
1976static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001977bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001978{
1979 _PyObject_GC_UNTRACK(self);
1980 Py_CLEAR(self->reader);
1981 Py_CLEAR(self->writer);
1982 Py_CLEAR(self->dict);
1983 Py_TYPE(self)->tp_free((PyObject *) self);
1984}
1985
1986static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001987_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001988{
1989 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1990 PyObject *ret;
1991
1992 if (func == NULL) {
1993 PyErr_SetString(PyExc_AttributeError, name);
1994 return NULL;
1995 }
1996
1997 ret = PyObject_CallObject(func, args);
1998 Py_DECREF(func);
1999 return ret;
2000}
2001
2002static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002003bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002004{
2005 return _forward_call(self->reader, "read", args);
2006}
2007
2008static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002009bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002010{
2011 return _forward_call(self->reader, "peek", args);
2012}
2013
2014static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002015bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002016{
2017 return _forward_call(self->reader, "read1", args);
2018}
2019
2020static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002021bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002022{
2023 return _forward_call(self->reader, "readinto", args);
2024}
2025
2026static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002027bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002028{
2029 return _forward_call(self->writer, "write", args);
2030}
2031
2032static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002033bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002034{
2035 return _forward_call(self->writer, "flush", args);
2036}
2037
2038static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002039bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002040{
2041 return _forward_call(self->reader, "readable", args);
2042}
2043
2044static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002045bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002046{
2047 return _forward_call(self->writer, "writable", args);
2048}
2049
2050static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002051bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002052{
2053 PyObject *ret = _forward_call(self->writer, "close", args);
2054 if (ret == NULL)
2055 return NULL;
2056 Py_DECREF(ret);
2057
2058 return _forward_call(self->reader, "close", args);
2059}
2060
2061static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002062bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002063{
2064 PyObject *ret = _forward_call(self->writer, "isatty", args);
2065
2066 if (ret != Py_False) {
2067 /* either True or exception */
2068 return ret;
2069 }
2070 Py_DECREF(ret);
2071
2072 return _forward_call(self->reader, "isatty", args);
2073}
2074
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002075static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002076bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002077{
2078 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2079}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002080
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002081static PyMethodDef bufferedrwpair_methods[] = {
2082 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2083 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2084 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2085 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002086
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002087 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2088 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002089
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002090 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2091 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002092
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002093 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2094 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002095
2096 {NULL, NULL}
2097};
2098
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002099static PyGetSetDef bufferedrwpair_getset[] = {
2100 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002101 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002102};
2103
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002104PyTypeObject PyBufferedRWPair_Type = {
2105 PyVarObject_HEAD_INIT(NULL, 0)
2106 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002107 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002108 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002109 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002110 0, /*tp_print*/
2111 0, /*tp_getattr*/
2112 0, /*tp_setattr*/
2113 0, /*tp_compare */
2114 0, /*tp_repr*/
2115 0, /*tp_as_number*/
2116 0, /*tp_as_sequence*/
2117 0, /*tp_as_mapping*/
2118 0, /*tp_hash */
2119 0, /*tp_call*/
2120 0, /*tp_str*/
2121 0, /*tp_getattro*/
2122 0, /*tp_setattro*/
2123 0, /*tp_as_buffer*/
2124 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2125 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002126 bufferedrwpair_doc, /* tp_doc */
2127 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2128 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002129 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002130 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002131 0, /* tp_iter */
2132 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002133 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002134 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002135 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002136 0, /* tp_base */
2137 0, /* tp_dict */
2138 0, /* tp_descr_get */
2139 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002140 offsetof(rwpair, dict), /* tp_dictoffset */
2141 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002142 0, /* tp_alloc */
2143 PyType_GenericNew, /* tp_new */
2144};
2145
2146
2147
2148/*
2149 * BufferedRandom
2150 */
2151
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002152PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002153 "A buffered interface to random access streams.\n"
2154 "\n"
2155 "The constructor creates a reader and writer for a seekable stream,\n"
2156 "raw, given in the first argument. If the buffer_size is omitted it\n"
2157 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2158 );
2159
2160static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002161bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002162{
2163 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2164 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002165 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002166 PyObject *raw;
2167
2168 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002169 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002170
2171 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2172 &raw, &buffer_size, &max_buffer_size)) {
2173 return -1;
2174 }
2175
Benjamin Peterson59406a92009-03-26 17:10:29 +00002176 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2177 return -1;
2178
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002179 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002180 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002181 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002182 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002183 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002184 return -1;
2185
2186 Py_CLEAR(self->raw);
2187 Py_INCREF(raw);
2188 self->raw = raw;
2189 self->buffer_size = buffer_size;
2190 self->readable = 1;
2191 self->writable = 1;
2192
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002193 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002194 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002195 _bufferedreader_reset_buf(self);
2196 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002197 self->pos = 0;
2198
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002199 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2200 Py_TYPE(raw) == &PyFileIO_Type);
2201
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002202 self->ok = 1;
2203 return 0;
2204}
2205
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002206static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002207 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002208 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2209 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2210 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2211 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2212 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2213 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2214 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002215
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002216 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002217
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002218 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2219 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2220 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2221 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2222 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2223 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2224 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2225 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2226 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002227 {NULL, NULL}
2228};
2229
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002230static PyMemberDef bufferedrandom_members[] = {
2231 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002232 {NULL}
2233};
2234
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002235static PyGetSetDef bufferedrandom_getset[] = {
2236 {"closed", (getter)buffered_closed_get, NULL, NULL},
2237 {"name", (getter)buffered_name_get, NULL, NULL},
2238 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002239 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002240};
2241
2242
2243PyTypeObject PyBufferedRandom_Type = {
2244 PyVarObject_HEAD_INIT(NULL, 0)
2245 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002246 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002247 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002248 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002249 0, /*tp_print*/
2250 0, /*tp_getattr*/
2251 0, /*tp_setattr*/
2252 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002253 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002254 0, /*tp_as_number*/
2255 0, /*tp_as_sequence*/
2256 0, /*tp_as_mapping*/
2257 0, /*tp_hash */
2258 0, /*tp_call*/
2259 0, /*tp_str*/
2260 0, /*tp_getattro*/
2261 0, /*tp_setattro*/
2262 0, /*tp_as_buffer*/
2263 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2264 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002265 bufferedrandom_doc, /* tp_doc */
2266 (traverseproc)buffered_traverse, /* tp_traverse */
2267 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002268 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002269 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002270 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002271 (iternextfunc)buffered_iternext, /* tp_iternext */
2272 bufferedrandom_methods, /* tp_methods */
2273 bufferedrandom_members, /* tp_members */
2274 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002275 0, /* tp_base */
2276 0, /*tp_dict*/
2277 0, /* tp_descr_get */
2278 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002279 offsetof(buffered, dict), /*tp_dictoffset*/
2280 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002281 0, /* tp_alloc */
2282 PyType_GenericNew, /* tp_new */
2283};
2284