blob: fb651a7f9a0afa4777deb25dc11381f32450c8b2 [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) {
443 /* If flush() fails, just give up */
444 if (PyErr_ExceptionMatches(PyExc_IOError))
445 PyErr_Clear();
446 else
447 goto end;
448 }
449 Py_XDECREF(res);
450
451 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
452
453end:
454 LEAVE_BUFFERED(self)
455 return res;
456}
457
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000458/* detach */
459
460static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000461buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000462{
463 PyObject *raw, *res;
464 CHECK_INITIALIZED(self)
465 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
466 if (res == NULL)
467 return NULL;
468 Py_DECREF(res);
469 raw = self->raw;
470 self->raw = NULL;
471 self->detached = 1;
472 self->ok = 0;
473 return raw;
474}
475
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000476/* Inquiries */
477
478static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000479buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000480{
481 CHECK_INITIALIZED(self)
482 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
483}
484
485static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000486buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000487{
488 CHECK_INITIALIZED(self)
489 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
490}
491
492static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000493buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000494{
495 CHECK_INITIALIZED(self)
496 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
497}
498
499static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000500buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000501{
502 CHECK_INITIALIZED(self)
503 return PyObject_GetAttrString(self->raw, "name");
504}
505
506static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000507buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000508{
509 CHECK_INITIALIZED(self)
510 return PyObject_GetAttrString(self->raw, "mode");
511}
512
513/* Lower-level APIs */
514
515static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000516buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000517{
518 CHECK_INITIALIZED(self)
519 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
520}
521
522static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000523buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000524{
525 CHECK_INITIALIZED(self)
526 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
527}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000528
529
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000530/* Forward decls */
531static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000532_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000533static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000534_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000535static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000536_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000537static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000538_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000539static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000540_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000541static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000542_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000543static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000544_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000545static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000546_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000547
548
549/*
550 * Helpers
551 */
552
553/* Returns the address of the `written` member if a BlockingIOError was
554 raised, NULL otherwise. The error is always re-raised. */
555static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000556_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000557{
558 PyObject *t, *v, *tb;
559 PyBlockingIOErrorObject *err;
560
561 PyErr_Fetch(&t, &v, &tb);
562 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
563 PyErr_Restore(t, v, tb);
564 return NULL;
565 }
566 err = (PyBlockingIOErrorObject *) v;
567 /* TODO: sanity check (err->written >= 0) */
568 PyErr_Restore(t, v, tb);
569 return &err->written;
570}
571
572static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000573_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000574{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000575 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000576 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000577 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
578 if (res == NULL)
579 return -1;
580 n = PyNumber_AsOff_t(res, PyExc_ValueError);
581 Py_DECREF(res);
582 if (n < 0) {
583 if (!PyErr_Occurred())
584 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000585 "Raw stream returned invalid position %" PY_PRIdOFF,
586 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000587 return -1;
588 }
589 self->abs_pos = n;
590 return n;
591}
592
593static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000594_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000595{
596 PyObject *res, *posobj, *whenceobj;
597 Py_off_t n;
598
599 posobj = PyLong_FromOff_t(target);
600 if (posobj == NULL)
601 return -1;
602 whenceobj = PyLong_FromLong(whence);
603 if (whenceobj == NULL) {
604 Py_DECREF(posobj);
605 return -1;
606 }
607 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
608 posobj, whenceobj, NULL);
609 Py_DECREF(posobj);
610 Py_DECREF(whenceobj);
611 if (res == NULL)
612 return -1;
613 n = PyNumber_AsOff_t(res, PyExc_ValueError);
614 Py_DECREF(res);
615 if (n < 0) {
616 if (!PyErr_Occurred())
617 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000618 "Raw stream returned invalid position %" PY_PRIdOFF,
619 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000620 return -1;
621 }
622 self->abs_pos = n;
623 return n;
624}
625
626static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000627_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000628{
629 Py_ssize_t n;
630 if (self->buffer_size <= 0) {
631 PyErr_SetString(PyExc_ValueError,
632 "buffer size must be strictly positive");
633 return -1;
634 }
635 if (self->buffer)
636 PyMem_Free(self->buffer);
637 self->buffer = PyMem_Malloc(self->buffer_size);
638 if (self->buffer == NULL) {
639 PyErr_NoMemory();
640 return -1;
641 }
Georg Brandldfd73442009-04-05 11:47:34 +0000642#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000643 self->lock = PyThread_allocate_lock();
644 if (self->lock == NULL) {
645 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
646 return -1;
647 }
Georg Brandldfd73442009-04-05 11:47:34 +0000648#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000649 /* Find out whether buffer_size is a power of 2 */
650 /* XXX is this optimization useful? */
651 for (n = self->buffer_size - 1; n & 1; n >>= 1)
652 ;
653 if (n == 0)
654 self->buffer_mask = self->buffer_size - 1;
655 else
656 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000657 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000658 PyErr_Clear();
659 return 0;
660}
661
662/*
663 * Shared methods and wrappers
664 */
665
666static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000667buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000668{
669 PyObject *res;
670
671 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000672 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000673
674 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000675 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000676 if (res != NULL && self->readable) {
677 /* Rewind the raw stream so that its position corresponds to
678 the current logical position. */
679 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000680 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000681 if (n == -1)
682 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000683 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000684 }
685 LEAVE_BUFFERED(self)
686
687 return res;
688}
689
690static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000691buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000692{
693 Py_ssize_t n = 0;
694 PyObject *res = NULL;
695
696 CHECK_INITIALIZED(self)
697 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
698 return NULL;
699 }
700
701 ENTER_BUFFERED(self)
702
703 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000704 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000705 if (res == NULL)
706 goto end;
707 Py_CLEAR(res);
708 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000709 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000710
711end:
712 LEAVE_BUFFERED(self)
713 return res;
714}
715
716static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000717buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000718{
719 Py_ssize_t n = -1;
720 PyObject *res;
721
722 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000723 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000724 return NULL;
725 }
726 if (n < -1) {
727 PyErr_SetString(PyExc_ValueError,
728 "read length must be positive or -1");
729 return NULL;
730 }
731
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000732 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000733
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000734 if (n == -1) {
735 /* The number of bytes is unspecified, read until the end of stream */
736 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000737 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000738 LEAVE_BUFFERED(self)
739 }
740 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000741 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000742 if (res == Py_None) {
743 Py_DECREF(res);
744 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000745 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000746 LEAVE_BUFFERED(self)
747 }
748 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000749
750 return res;
751}
752
753static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000754buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000755{
756 Py_ssize_t n, have, r;
757 PyObject *res = NULL;
758
759 CHECK_INITIALIZED(self)
760 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
761 return NULL;
762 }
763
764 if (n < 0) {
765 PyErr_SetString(PyExc_ValueError,
766 "read length must be positive");
767 return NULL;
768 }
769 if (n == 0)
770 return PyBytes_FromStringAndSize(NULL, 0);
771
772 ENTER_BUFFERED(self)
773
774 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000775 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000776 if (res == NULL)
777 goto end;
778 Py_CLEAR(res);
779 }
780
781 /* Return up to n bytes. If at least one byte is buffered, we
782 only return buffered bytes. Otherwise, we do one raw read. */
783
784 /* XXX: this mimicks the io.py implementation but is probably wrong.
785 If we need to read from the raw stream, then we could actually read
786 all `n` bytes asked by the caller (and possibly more, so as to fill
787 our buffer for the next reads). */
788
789 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
790 if (have > 0) {
791 if (n > have)
792 n = have;
793 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
794 if (res == NULL)
795 goto end;
796 self->pos += n;
797 goto end;
798 }
799
800 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000801 _bufferedreader_reset_buf(self);
802 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000803 if (r == -1)
804 goto end;
805 if (r == -2)
806 r = 0;
807 if (n > r)
808 n = r;
809 res = PyBytes_FromStringAndSize(self->buffer, n);
810 if (res == NULL)
811 goto end;
812 self->pos = n;
813
814end:
815 LEAVE_BUFFERED(self)
816 return res;
817}
818
819static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000820buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000821{
822 PyObject *res = NULL;
823
824 CHECK_INITIALIZED(self)
825
826 /* TODO: use raw.readinto() instead! */
827 if (self->writable) {
828 ENTER_BUFFERED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000829 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000830 LEAVE_BUFFERED(self)
831 if (res == NULL)
832 goto end;
833 Py_DECREF(res);
834 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000835 res = bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000836
837end:
838 return res;
839}
840
841static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000842_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000843{
844 PyObject *res = NULL;
845 PyObject *chunks = NULL;
846 Py_ssize_t n, written = 0;
847 const char *start, *s, *end;
848
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000849 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000850
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000851 /* First, try to find a line in the buffer. This can run unlocked because
852 the calls to the C API are simple enough that they can't trigger
853 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000854 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
855 if (limit >= 0 && n > limit)
856 n = limit;
857 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000858 s = memchr(start, '\n', n);
859 if (s != NULL) {
860 res = PyBytes_FromStringAndSize(start, s - start + 1);
861 if (res != NULL)
862 self->pos += s - start + 1;
863 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000864 }
865 if (n == limit) {
866 res = PyBytes_FromStringAndSize(start, n);
867 if (res != NULL)
868 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000869 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000870 }
871
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000872 ENTER_BUFFERED(self)
873
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000874 /* Now we try to get some more from the raw stream */
875 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000876 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000877 if (res == NULL)
878 goto end;
879 Py_CLEAR(res);
880 }
881 chunks = PyList_New(0);
882 if (chunks == NULL)
883 goto end;
884 if (n > 0) {
885 res = PyBytes_FromStringAndSize(start, n);
886 if (res == NULL)
887 goto end;
888 if (PyList_Append(chunks, res) < 0) {
889 Py_CLEAR(res);
890 goto end;
891 }
892 Py_CLEAR(res);
893 written += n;
894 if (limit >= 0)
895 limit -= n;
896 }
897
898 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000899 _bufferedreader_reset_buf(self);
900 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000901 if (n == -1)
902 goto end;
903 if (n <= 0)
904 break;
905 if (limit >= 0 && n > limit)
906 n = limit;
907 start = self->buffer;
908 end = start + n;
909 s = start;
910 while (s < end) {
911 if (*s++ == '\n') {
912 res = PyBytes_FromStringAndSize(start, s - start);
913 if (res == NULL)
914 goto end;
915 self->pos = s - start;
916 goto found;
917 }
918 }
919 res = PyBytes_FromStringAndSize(start, n);
920 if (res == NULL)
921 goto end;
922 if (n == limit) {
923 self->pos = n;
924 break;
925 }
926 if (PyList_Append(chunks, res) < 0) {
927 Py_CLEAR(res);
928 goto end;
929 }
930 Py_CLEAR(res);
931 written += n;
932 if (limit >= 0)
933 limit -= n;
934 }
935found:
936 if (res != NULL && PyList_Append(chunks, res) < 0) {
937 Py_CLEAR(res);
938 goto end;
939 }
940 Py_CLEAR(res);
941 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
942
943end:
944 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000945end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000946 Py_XDECREF(chunks);
947 return res;
948}
949
950static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000951buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000952{
953 Py_ssize_t limit = -1;
954
955 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000956 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000957 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000958 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000959}
960
961
962static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000963buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000964{
965 Py_off_t pos;
966
967 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000968 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000969 if (pos == -1)
970 return NULL;
971 pos -= RAW_OFFSET(self);
972 /* TODO: sanity check (pos >= 0) */
973 return PyLong_FromOff_t(pos);
974}
975
976static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000977buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000978{
979 Py_off_t target, n;
980 int whence = 0;
981 PyObject *targetobj, *res = NULL;
982
983 CHECK_INITIALIZED(self)
984 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
985 return NULL;
986 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000987 if (whence < 0 || whence > 2) {
988 PyErr_Format(PyExc_ValueError,
989 "whence must be between 0 and 2, not %d", whence);
990 return NULL;
991 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000992
993 CHECK_CLOSED(self, "seek of closed file")
994
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000995 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
996 if (target == -1 && PyErr_Occurred())
997 return NULL;
998
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000999 if (whence != 2 && self->readable) {
1000 Py_off_t current, avail;
1001 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001002 so as to return quickly if possible. Also, we needn't take the
1003 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001004 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001005 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1006 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001007 current = RAW_TELL(self);
1008 avail = READAHEAD(self);
1009 if (avail > 0) {
1010 Py_off_t offset;
1011 if (whence == 0)
1012 offset = target - (current - RAW_OFFSET(self));
1013 else
1014 offset = target;
1015 if (offset >= -self->pos && offset <= avail) {
1016 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001017 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001018 }
1019 }
1020 }
1021
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001022 ENTER_BUFFERED(self)
1023
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001024 /* Fallback: invoke raw seek() method and clear buffer */
1025 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001026 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001027 if (res == NULL)
1028 goto end;
1029 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001030 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001031 }
1032
1033 /* TODO: align on block boundary and read buffer if needed? */
1034 if (whence == 1)
1035 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001036 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001037 if (n == -1)
1038 goto end;
1039 self->raw_pos = -1;
1040 res = PyLong_FromOff_t(n);
1041 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001042 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001043
1044end:
1045 LEAVE_BUFFERED(self)
1046 return res;
1047}
1048
1049static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001050buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001051{
1052 PyObject *pos = Py_None;
1053 PyObject *res = NULL;
1054
1055 CHECK_INITIALIZED(self)
1056 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1057 return NULL;
1058 }
1059
1060 ENTER_BUFFERED(self)
1061
1062 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001063 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001064 if (res == NULL)
1065 goto end;
1066 Py_CLEAR(res);
1067 }
1068 if (self->readable) {
1069 if (pos == Py_None) {
1070 /* Rewind the raw stream so that its position corresponds to
1071 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001072 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001073 goto end;
1074 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001075 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001076 }
1077 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1078 if (res == NULL)
1079 goto end;
1080 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001081 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001082 PyErr_Clear();
1083
1084end:
1085 LEAVE_BUFFERED(self)
1086 return res;
1087}
1088
1089static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001090buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001091{
1092 PyObject *line;
1093 PyTypeObject *tp;
1094
1095 CHECK_INITIALIZED(self);
1096
1097 tp = Py_TYPE(self);
1098 if (tp == &PyBufferedReader_Type ||
1099 tp == &PyBufferedRandom_Type) {
1100 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001101 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001102 }
1103 else {
1104 line = PyObject_CallMethodObjArgs((PyObject *)self,
1105 _PyIO_str_readline, NULL);
1106 if (line && !PyBytes_Check(line)) {
1107 PyErr_Format(PyExc_IOError,
1108 "readline() should have returned a bytes object, "
1109 "not '%.200s'", Py_TYPE(line)->tp_name);
1110 Py_DECREF(line);
1111 return NULL;
1112 }
1113 }
1114
1115 if (line == NULL)
1116 return NULL;
1117
1118 if (PyBytes_GET_SIZE(line) == 0) {
1119 /* Reached EOF or would have blocked */
1120 Py_DECREF(line);
1121 return NULL;
1122 }
1123
1124 return line;
1125}
1126
Antoine Pitrou716c4442009-05-23 19:04:03 +00001127static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001128buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001129{
1130 PyObject *nameobj, *res;
1131
1132 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1133 if (nameobj == NULL) {
1134 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1135 PyErr_Clear();
1136 else
1137 return NULL;
1138 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1139 }
1140 else {
1141 res = PyUnicode_FromFormat("<%s name=%R>",
1142 Py_TYPE(self)->tp_name, nameobj);
1143 Py_DECREF(nameobj);
1144 }
1145 return res;
1146}
1147
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001148/*
1149 * class BufferedReader
1150 */
1151
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001152PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001153 "Create a new buffered reader using the given readable raw IO object.");
1154
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001155static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001156{
1157 self->read_end = -1;
1158}
1159
1160static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001161bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001162{
1163 char *kwlist[] = {"raw", "buffer_size", NULL};
1164 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1165 PyObject *raw;
1166
1167 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001168 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001169
1170 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1171 &raw, &buffer_size)) {
1172 return -1;
1173 }
1174
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001175 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001176 return -1;
1177
1178 Py_CLEAR(self->raw);
1179 Py_INCREF(raw);
1180 self->raw = raw;
1181 self->buffer_size = buffer_size;
1182 self->readable = 1;
1183 self->writable = 0;
1184
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001185 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001186 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001187 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001188
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001189 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1190 Py_TYPE(raw) == &PyFileIO_Type);
1191
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001192 self->ok = 1;
1193 return 0;
1194}
1195
1196static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001197_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001198{
1199 Py_buffer buf;
1200 PyObject *memobj, *res;
1201 Py_ssize_t n;
1202 /* NOTE: the buffer needn't be released as its object is NULL. */
1203 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1204 return -1;
1205 memobj = PyMemoryView_FromBuffer(&buf);
1206 if (memobj == NULL)
1207 return -1;
1208 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1209 Py_DECREF(memobj);
1210 if (res == NULL)
1211 return -1;
1212 if (res == Py_None) {
1213 /* Non-blocking stream would have blocked. Special return code! */
1214 Py_DECREF(res);
1215 return -2;
1216 }
1217 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1218 Py_DECREF(res);
1219 if (n < 0 || n > len) {
1220 PyErr_Format(PyExc_IOError,
1221 "raw readinto() returned invalid length %zd "
1222 "(should have been between 0 and %zd)", n, len);
1223 return -1;
1224 }
1225 if (n > 0 && self->abs_pos != -1)
1226 self->abs_pos += n;
1227 return n;
1228}
1229
1230static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001231_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001232{
1233 Py_ssize_t start, len, n;
1234 if (VALID_READ_BUFFER(self))
1235 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1236 else
1237 start = 0;
1238 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001239 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001240 if (n <= 0)
1241 return n;
1242 self->read_end = start + n;
1243 self->raw_pos = start + n;
1244 return n;
1245}
1246
1247static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001248_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001249{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001250 Py_ssize_t current_size;
1251 PyObject *res, *data = NULL;
1252 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001253
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001254 if (chunks == NULL)
1255 return NULL;
1256
1257 /* First copy what we have in the current buffer. */
1258 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1259 if (current_size) {
1260 data = PyBytes_FromStringAndSize(
1261 self->buffer + self->pos, current_size);
1262 if (data == NULL) {
1263 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001264 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001265 }
1266 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001267 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001268 /* We're going past the buffer's bounds, flush it */
1269 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001270 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001271 if (res == NULL) {
1272 Py_DECREF(chunks);
1273 return NULL;
1274 }
1275 Py_CLEAR(res);
1276 }
1277 while (1) {
1278 if (data) {
1279 if (PyList_Append(chunks, data) < 0) {
1280 Py_DECREF(data);
1281 Py_DECREF(chunks);
1282 return NULL;
1283 }
1284 Py_DECREF(data);
1285 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001286
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001287 /* Read until EOF or until read() would block. */
1288 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1289 if (data == NULL) {
1290 Py_DECREF(chunks);
1291 return NULL;
1292 }
1293 if (data != Py_None && !PyBytes_Check(data)) {
1294 Py_DECREF(data);
1295 Py_DECREF(chunks);
1296 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1297 return NULL;
1298 }
1299 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1300 if (current_size == 0) {
1301 Py_DECREF(chunks);
1302 return data;
1303 }
1304 else {
1305 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1306 Py_DECREF(data);
1307 Py_DECREF(chunks);
1308 return res;
1309 }
1310 }
1311 current_size += PyBytes_GET_SIZE(data);
1312 if (self->abs_pos != -1)
1313 self->abs_pos += PyBytes_GET_SIZE(data);
1314 }
1315}
1316
1317/* Read n bytes from the buffer if it can, otherwise return None.
1318 This function is simple enough that it can run unlocked. */
1319static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001320_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001321{
1322 Py_ssize_t current_size;
1323
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001324 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1325 if (n <= current_size) {
1326 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001327 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1328 if (res != NULL)
1329 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001330 return res;
1331 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001332 Py_RETURN_NONE;
1333}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001334
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001335/* Generic read function: read from the stream until enough bytes are read,
1336 * or until an EOF occurs or until read() would block.
1337 */
1338static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001339_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001340{
1341 PyObject *res = NULL;
1342 Py_ssize_t current_size, remaining, written;
1343 char *out;
1344
1345 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1346 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001347 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001348
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001349 res = PyBytes_FromStringAndSize(NULL, n);
1350 if (res == NULL)
1351 goto error;
1352 out = PyBytes_AS_STRING(res);
1353 remaining = n;
1354 written = 0;
1355 if (current_size > 0) {
1356 memcpy(out, self->buffer + self->pos, current_size);
1357 remaining -= current_size;
1358 written += current_size;
1359 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001360 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001361 while (remaining > 0) {
1362 /* We want to read a whole block at the end into buffer.
1363 If we had readv() we could do this in one pass. */
1364 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1365 if (r == 0)
1366 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001367 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001368 if (r == -1)
1369 goto error;
1370 if (r == 0 || r == -2) {
1371 /* EOF occurred or read() would block. */
1372 if (r == 0 || written > 0) {
1373 if (_PyBytes_Resize(&res, written))
1374 goto error;
1375 return res;
1376 }
1377 Py_DECREF(res);
1378 Py_INCREF(Py_None);
1379 return Py_None;
1380 }
1381 remaining -= r;
1382 written += r;
1383 }
1384 assert(remaining <= self->buffer_size);
1385 self->pos = 0;
1386 self->raw_pos = 0;
1387 self->read_end = 0;
1388 while (self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001389 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001390 if (r == -1)
1391 goto error;
1392 if (r == 0 || r == -2) {
1393 /* EOF occurred or read() would block. */
1394 if (r == 0 || written > 0) {
1395 if (_PyBytes_Resize(&res, written))
1396 goto error;
1397 return res;
1398 }
1399 Py_DECREF(res);
1400 Py_INCREF(Py_None);
1401 return Py_None;
1402 }
1403 if (remaining > r) {
1404 memcpy(out + written, self->buffer + self->pos, r);
1405 written += r;
1406 self->pos += r;
1407 remaining -= r;
1408 }
1409 else if (remaining > 0) {
1410 memcpy(out + written, self->buffer + self->pos, remaining);
1411 written += remaining;
1412 self->pos += remaining;
1413 remaining = 0;
1414 }
1415 if (remaining == 0)
1416 break;
1417 }
1418
1419 return res;
1420
1421error:
1422 Py_XDECREF(res);
1423 return NULL;
1424}
1425
1426static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001427_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001428{
1429 Py_ssize_t have, r;
1430
1431 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1432 /* Constraints:
1433 1. we don't want to advance the file position.
1434 2. we don't want to lose block alignment, so we can't shift the buffer
1435 to make some place.
1436 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1437 */
1438 if (have > 0) {
1439 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1440 }
1441
1442 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001443 _bufferedreader_reset_buf(self);
1444 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001445 if (r == -1)
1446 return NULL;
1447 if (r == -2)
1448 r = 0;
1449 self->pos = 0;
1450 return PyBytes_FromStringAndSize(self->buffer, r);
1451}
1452
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001453static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001454 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001455 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1456 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1457 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1458 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1459 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1460 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1461 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1462 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001463
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001464 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1465 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1466 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1467 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1468 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1469 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1470 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001471 {NULL, NULL}
1472};
1473
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001474static PyMemberDef bufferedreader_members[] = {
1475 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001476 {NULL}
1477};
1478
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001479static PyGetSetDef bufferedreader_getset[] = {
1480 {"closed", (getter)buffered_closed_get, NULL, NULL},
1481 {"name", (getter)buffered_name_get, NULL, NULL},
1482 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001483 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001484};
1485
1486
1487PyTypeObject PyBufferedReader_Type = {
1488 PyVarObject_HEAD_INIT(NULL, 0)
1489 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001490 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001491 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001492 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001493 0, /*tp_print*/
1494 0, /*tp_getattr*/
1495 0, /*tp_setattr*/
1496 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001497 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001498 0, /*tp_as_number*/
1499 0, /*tp_as_sequence*/
1500 0, /*tp_as_mapping*/
1501 0, /*tp_hash */
1502 0, /*tp_call*/
1503 0, /*tp_str*/
1504 0, /*tp_getattro*/
1505 0, /*tp_setattro*/
1506 0, /*tp_as_buffer*/
1507 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1508 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001509 bufferedreader_doc, /* tp_doc */
1510 (traverseproc)buffered_traverse, /* tp_traverse */
1511 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001512 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001513 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001514 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001515 (iternextfunc)buffered_iternext, /* tp_iternext */
1516 bufferedreader_methods, /* tp_methods */
1517 bufferedreader_members, /* tp_members */
1518 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001519 0, /* tp_base */
1520 0, /* tp_dict */
1521 0, /* tp_descr_get */
1522 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001523 offsetof(buffered, dict), /* tp_dictoffset */
1524 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001525 0, /* tp_alloc */
1526 PyType_GenericNew, /* tp_new */
1527};
1528
1529
Benjamin Peterson59406a92009-03-26 17:10:29 +00001530
1531static int
1532complain_about_max_buffer_size(void)
1533{
1534 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1535 "max_buffer_size is deprecated", 1) < 0)
1536 return 0;
1537 return 1;
1538}
1539
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001540/*
1541 * class BufferedWriter
1542 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001543PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001544 "A buffer for a writeable sequential RawIO object.\n"
1545 "\n"
1546 "The constructor creates a BufferedWriter for the given writeable raw\n"
1547 "stream. If the buffer_size is not given, it defaults to\n"
1548 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1549 );
1550
1551static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001552_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001553{
1554 self->write_pos = 0;
1555 self->write_end = -1;
1556}
1557
1558static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001559bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001560{
1561 /* TODO: properly deprecate max_buffer_size */
1562 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1563 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001564 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001565 PyObject *raw;
1566
1567 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001568 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001569
1570 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1571 &raw, &buffer_size, &max_buffer_size)) {
1572 return -1;
1573 }
1574
Benjamin Peterson59406a92009-03-26 17:10:29 +00001575 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1576 return -1;
1577
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001578 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001579 return -1;
1580
1581 Py_CLEAR(self->raw);
1582 Py_INCREF(raw);
1583 self->raw = raw;
1584 self->readable = 0;
1585 self->writable = 1;
1586
1587 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001588 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001589 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001590 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001591 self->pos = 0;
1592
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001593 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1594 Py_TYPE(raw) == &PyFileIO_Type);
1595
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001596 self->ok = 1;
1597 return 0;
1598}
1599
1600static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001601_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001602{
1603 Py_buffer buf;
1604 PyObject *memobj, *res;
1605 Py_ssize_t n;
1606 /* NOTE: the buffer needn't be released as its object is NULL. */
1607 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1608 return -1;
1609 memobj = PyMemoryView_FromBuffer(&buf);
1610 if (memobj == NULL)
1611 return -1;
1612 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1613 Py_DECREF(memobj);
1614 if (res == NULL)
1615 return -1;
1616 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1617 Py_DECREF(res);
1618 if (n < 0 || n > len) {
1619 PyErr_Format(PyExc_IOError,
1620 "raw write() returned invalid length %zd "
1621 "(should have been between 0 and %zd)", n, len);
1622 return -1;
1623 }
1624 if (n > 0 && self->abs_pos != -1)
1625 self->abs_pos += n;
1626 return n;
1627}
1628
1629/* `restore_pos` is 1 if we need to restore the raw stream position at
1630 the end, 0 otherwise. */
1631static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001632_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001633{
1634 Py_ssize_t written = 0;
1635 Py_off_t n, rewind;
1636
1637 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1638 goto end;
1639 /* First, rewind */
1640 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1641 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001642 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001643 if (n < 0) {
1644 goto error;
1645 }
1646 self->raw_pos -= rewind;
1647 }
1648 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001649 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001650 self->buffer + self->write_pos,
1651 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1652 Py_off_t, Py_ssize_t));
1653 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001654 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001655 if (w == NULL)
1656 goto error;
1657 self->write_pos += *w;
1658 self->raw_pos = self->write_pos;
1659 written += *w;
1660 *w = written;
1661 /* Already re-raised */
1662 goto error;
1663 }
1664 self->write_pos += n;
1665 self->raw_pos = self->write_pos;
1666 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1667 }
1668
1669 if (restore_pos) {
1670 Py_off_t forward = rewind - written;
1671 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001672 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001673 if (n < 0) {
1674 goto error;
1675 }
1676 self->raw_pos += forward;
1677 }
1678 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001679 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001680
1681end:
1682 Py_RETURN_NONE;
1683
1684error:
1685 return NULL;
1686}
1687
1688static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001689bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001690{
1691 PyObject *res = NULL;
1692 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001693 Py_ssize_t written, avail, remaining;
1694 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001695
1696 CHECK_INITIALIZED(self)
1697 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1698 return NULL;
1699 }
1700
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001701 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001702 PyErr_SetString(PyExc_ValueError, "write to closed file");
1703 PyBuffer_Release(&buf);
1704 return NULL;
1705 }
1706
1707 ENTER_BUFFERED(self)
1708
1709 /* Fast path: the data to write can be fully buffered. */
1710 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1711 self->pos = 0;
1712 self->raw_pos = 0;
1713 }
1714 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1715 if (buf.len <= avail) {
1716 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1717 if (!VALID_WRITE_BUFFER(self)) {
1718 self->write_pos = self->pos;
1719 }
1720 ADJUST_POSITION(self, self->pos + buf.len);
1721 if (self->pos > self->write_end)
1722 self->write_end = self->pos;
1723 written = buf.len;
1724 goto end;
1725 }
1726
1727 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001728 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001729 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001730 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001731 if (w == NULL)
1732 goto error;
1733 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001734 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001735 /* Make some place by shifting the buffer. */
1736 assert(VALID_WRITE_BUFFER(self));
1737 memmove(self->buffer, self->buffer + self->write_pos,
1738 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1739 Py_off_t, Py_ssize_t));
1740 self->write_end -= self->write_pos;
1741 self->raw_pos -= self->write_pos;
1742 self->pos -= self->write_pos;
1743 self->write_pos = 0;
1744 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1745 Py_off_t, Py_ssize_t);
1746 if (buf.len <= avail) {
1747 /* Everything can be buffered */
1748 PyErr_Clear();
1749 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1750 self->write_end += buf.len;
1751 written = buf.len;
1752 goto end;
1753 }
1754 /* Buffer as much as possible. */
1755 memcpy(self->buffer + self->write_end, buf.buf, avail);
1756 self->write_end += avail;
1757 /* Already re-raised */
1758 *w = avail;
1759 goto error;
1760 }
1761 Py_CLEAR(res);
1762
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001763 /* Adjust the raw stream position if it is away from the logical stream
1764 position. This happens if the read buffer has been filled but not
1765 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1766 the raw stream by itself).
1767 Fixes issue #6629.
1768 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001769 offset = RAW_OFFSET(self);
1770 if (offset != 0) {
1771 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001772 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001773 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001774 }
1775
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001776 /* Then write buf itself. At this point the buffer has been emptied. */
1777 remaining = buf.len;
1778 written = 0;
1779 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001780 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001781 self, (char *) buf.buf + written, buf.len - written);
1782 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001783 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001784 if (w == NULL)
1785 goto error;
1786 written += *w;
1787 remaining -= *w;
1788 if (remaining > self->buffer_size) {
1789 /* Can't buffer everything, still buffer as much as possible */
1790 memcpy(self->buffer,
1791 (char *) buf.buf + written, self->buffer_size);
1792 self->raw_pos = 0;
1793 ADJUST_POSITION(self, self->buffer_size);
1794 self->write_end = self->buffer_size;
1795 *w = written + self->buffer_size;
1796 /* Already re-raised */
1797 goto error;
1798 }
1799 PyErr_Clear();
1800 break;
1801 }
1802 written += n;
1803 remaining -= n;
1804 }
1805 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001806 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001807 if (remaining > 0) {
1808 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1809 written += remaining;
1810 }
1811 self->write_pos = 0;
1812 /* TODO: sanity check (remaining >= 0) */
1813 self->write_end = remaining;
1814 ADJUST_POSITION(self, remaining);
1815 self->raw_pos = 0;
1816
1817end:
1818 res = PyLong_FromSsize_t(written);
1819
1820error:
1821 LEAVE_BUFFERED(self)
1822 PyBuffer_Release(&buf);
1823 return res;
1824}
1825
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001826static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001827 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001828 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1829 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1830 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1831 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1832 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1833 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1834 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001835
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001836 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1837 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1838 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1839 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1840 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001841 {NULL, NULL}
1842};
1843
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001844static PyMemberDef bufferedwriter_members[] = {
1845 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001846 {NULL}
1847};
1848
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001849static PyGetSetDef bufferedwriter_getset[] = {
1850 {"closed", (getter)buffered_closed_get, NULL, NULL},
1851 {"name", (getter)buffered_name_get, NULL, NULL},
1852 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001853 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001854};
1855
1856
1857PyTypeObject PyBufferedWriter_Type = {
1858 PyVarObject_HEAD_INIT(NULL, 0)
1859 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001860 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001861 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001862 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001863 0, /*tp_print*/
1864 0, /*tp_getattr*/
1865 0, /*tp_setattr*/
1866 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001867 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001868 0, /*tp_as_number*/
1869 0, /*tp_as_sequence*/
1870 0, /*tp_as_mapping*/
1871 0, /*tp_hash */
1872 0, /*tp_call*/
1873 0, /*tp_str*/
1874 0, /*tp_getattro*/
1875 0, /*tp_setattro*/
1876 0, /*tp_as_buffer*/
1877 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1878 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001879 bufferedwriter_doc, /* tp_doc */
1880 (traverseproc)buffered_traverse, /* tp_traverse */
1881 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001882 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001883 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001884 0, /* tp_iter */
1885 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001886 bufferedwriter_methods, /* tp_methods */
1887 bufferedwriter_members, /* tp_members */
1888 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001889 0, /* tp_base */
1890 0, /* tp_dict */
1891 0, /* tp_descr_get */
1892 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001893 offsetof(buffered, dict), /* tp_dictoffset */
1894 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001895 0, /* tp_alloc */
1896 PyType_GenericNew, /* tp_new */
1897};
1898
1899
1900
1901/*
1902 * BufferedRWPair
1903 */
1904
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001905PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001906 "A buffered reader and writer object together.\n"
1907 "\n"
1908 "A buffered reader object and buffered writer object put together to\n"
1909 "form a sequential IO object that can read and write. This is typically\n"
1910 "used with a socket or two-way pipe.\n"
1911 "\n"
1912 "reader and writer are RawIOBase objects that are readable and\n"
1913 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001914 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001915 );
1916
1917/* XXX The usefulness of this (compared to having two separate IO objects) is
1918 * questionable.
1919 */
1920
1921typedef struct {
1922 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001923 buffered *reader;
1924 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001925 PyObject *dict;
1926 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001927} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001928
1929static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001930bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001931{
1932 PyObject *reader, *writer;
1933 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001934 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001935
1936 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1937 &buffer_size, &max_buffer_size)) {
1938 return -1;
1939 }
1940
Benjamin Peterson59406a92009-03-26 17:10:29 +00001941 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1942 return -1;
1943
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001944 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001945 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001946 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001947 return -1;
1948
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001949 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001950 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001951 if (self->reader == NULL)
1952 return -1;
1953
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001954 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001955 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001956 if (self->writer == NULL) {
1957 Py_CLEAR(self->reader);
1958 return -1;
1959 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001960
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001961 return 0;
1962}
1963
1964static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001965bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001966{
1967 Py_VISIT(self->dict);
1968 return 0;
1969}
1970
1971static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001972bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001973{
1974 Py_CLEAR(self->reader);
1975 Py_CLEAR(self->writer);
1976 Py_CLEAR(self->dict);
1977 return 0;
1978}
1979
1980static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001981bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001982{
1983 _PyObject_GC_UNTRACK(self);
1984 Py_CLEAR(self->reader);
1985 Py_CLEAR(self->writer);
1986 Py_CLEAR(self->dict);
1987 Py_TYPE(self)->tp_free((PyObject *) self);
1988}
1989
1990static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001991_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001992{
1993 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1994 PyObject *ret;
1995
1996 if (func == NULL) {
1997 PyErr_SetString(PyExc_AttributeError, name);
1998 return NULL;
1999 }
2000
2001 ret = PyObject_CallObject(func, args);
2002 Py_DECREF(func);
2003 return ret;
2004}
2005
2006static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002007bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002008{
2009 return _forward_call(self->reader, "read", args);
2010}
2011
2012static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002013bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002014{
2015 return _forward_call(self->reader, "peek", args);
2016}
2017
2018static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002019bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002020{
2021 return _forward_call(self->reader, "read1", args);
2022}
2023
2024static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002025bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002026{
2027 return _forward_call(self->reader, "readinto", args);
2028}
2029
2030static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002031bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002032{
2033 return _forward_call(self->writer, "write", args);
2034}
2035
2036static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002037bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002038{
2039 return _forward_call(self->writer, "flush", args);
2040}
2041
2042static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002043bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002044{
2045 return _forward_call(self->reader, "readable", args);
2046}
2047
2048static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002049bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002050{
2051 return _forward_call(self->writer, "writable", args);
2052}
2053
2054static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002055bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002056{
2057 PyObject *ret = _forward_call(self->writer, "close", args);
2058 if (ret == NULL)
2059 return NULL;
2060 Py_DECREF(ret);
2061
2062 return _forward_call(self->reader, "close", args);
2063}
2064
2065static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002066bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002067{
2068 PyObject *ret = _forward_call(self->writer, "isatty", args);
2069
2070 if (ret != Py_False) {
2071 /* either True or exception */
2072 return ret;
2073 }
2074 Py_DECREF(ret);
2075
2076 return _forward_call(self->reader, "isatty", args);
2077}
2078
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002079static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002080bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002081{
2082 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2083}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002084
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002085static PyMethodDef bufferedrwpair_methods[] = {
2086 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2087 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2088 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2089 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002090
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002091 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2092 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002093
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002094 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2095 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002096
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002097 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2098 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002099
2100 {NULL, NULL}
2101};
2102
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002103static PyGetSetDef bufferedrwpair_getset[] = {
2104 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002105 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002106};
2107
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002108PyTypeObject PyBufferedRWPair_Type = {
2109 PyVarObject_HEAD_INIT(NULL, 0)
2110 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002111 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002112 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002113 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002114 0, /*tp_print*/
2115 0, /*tp_getattr*/
2116 0, /*tp_setattr*/
2117 0, /*tp_compare */
2118 0, /*tp_repr*/
2119 0, /*tp_as_number*/
2120 0, /*tp_as_sequence*/
2121 0, /*tp_as_mapping*/
2122 0, /*tp_hash */
2123 0, /*tp_call*/
2124 0, /*tp_str*/
2125 0, /*tp_getattro*/
2126 0, /*tp_setattro*/
2127 0, /*tp_as_buffer*/
2128 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2129 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002130 bufferedrwpair_doc, /* tp_doc */
2131 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2132 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002133 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002134 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002135 0, /* tp_iter */
2136 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002137 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002138 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002139 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002140 0, /* tp_base */
2141 0, /* tp_dict */
2142 0, /* tp_descr_get */
2143 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002144 offsetof(rwpair, dict), /* tp_dictoffset */
2145 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002146 0, /* tp_alloc */
2147 PyType_GenericNew, /* tp_new */
2148};
2149
2150
2151
2152/*
2153 * BufferedRandom
2154 */
2155
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002156PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002157 "A buffered interface to random access streams.\n"
2158 "\n"
2159 "The constructor creates a reader and writer for a seekable stream,\n"
2160 "raw, given in the first argument. If the buffer_size is omitted it\n"
2161 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2162 );
2163
2164static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002165bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002166{
2167 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2168 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002169 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002170 PyObject *raw;
2171
2172 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002173 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002174
2175 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2176 &raw, &buffer_size, &max_buffer_size)) {
2177 return -1;
2178 }
2179
Benjamin Peterson59406a92009-03-26 17:10:29 +00002180 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2181 return -1;
2182
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002183 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002184 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002185 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002186 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002187 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002188 return -1;
2189
2190 Py_CLEAR(self->raw);
2191 Py_INCREF(raw);
2192 self->raw = raw;
2193 self->buffer_size = buffer_size;
2194 self->readable = 1;
2195 self->writable = 1;
2196
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002197 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002198 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002199 _bufferedreader_reset_buf(self);
2200 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002201 self->pos = 0;
2202
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002203 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2204 Py_TYPE(raw) == &PyFileIO_Type);
2205
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002206 self->ok = 1;
2207 return 0;
2208}
2209
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002210static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002211 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002212 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2213 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2214 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2215 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2216 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2217 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2218 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002219
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002220 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002221
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002222 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2223 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2224 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2225 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2226 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2227 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2228 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2229 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2230 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002231 {NULL, NULL}
2232};
2233
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002234static PyMemberDef bufferedrandom_members[] = {
2235 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002236 {NULL}
2237};
2238
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002239static PyGetSetDef bufferedrandom_getset[] = {
2240 {"closed", (getter)buffered_closed_get, NULL, NULL},
2241 {"name", (getter)buffered_name_get, NULL, NULL},
2242 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002243 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002244};
2245
2246
2247PyTypeObject PyBufferedRandom_Type = {
2248 PyVarObject_HEAD_INIT(NULL, 0)
2249 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002250 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002251 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002252 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002253 0, /*tp_print*/
2254 0, /*tp_getattr*/
2255 0, /*tp_setattr*/
2256 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002257 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002258 0, /*tp_as_number*/
2259 0, /*tp_as_sequence*/
2260 0, /*tp_as_mapping*/
2261 0, /*tp_hash */
2262 0, /*tp_call*/
2263 0, /*tp_str*/
2264 0, /*tp_getattro*/
2265 0, /*tp_setattro*/
2266 0, /*tp_as_buffer*/
2267 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2268 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002269 bufferedrandom_doc, /* tp_doc */
2270 (traverseproc)buffered_traverse, /* tp_traverse */
2271 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002272 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002273 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002274 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002275 (iternextfunc)buffered_iternext, /* tp_iternext */
2276 bufferedrandom_methods, /* tp_methods */
2277 bufferedrandom_members, /* tp_members */
2278 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002279 0, /* tp_base */
2280 0, /*tp_dict*/
2281 0, /* tp_descr_get */
2282 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002283 offsetof(buffered, dict), /*tp_dictoffset*/
2284 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002285 0, /* tp_alloc */
2286 PyType_GenericNew, /* tp_new */
2287};
2288