blob: 39c778c5f194749740e40def9e3aecf6913c7375 [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)
723 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
724 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)
956
957 if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
958 return NULL;
959 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000960 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000961}
962
963
964static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000965buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000966{
967 Py_off_t pos;
968
969 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000970 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000971 if (pos == -1)
972 return NULL;
973 pos -= RAW_OFFSET(self);
974 /* TODO: sanity check (pos >= 0) */
975 return PyLong_FromOff_t(pos);
976}
977
978static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000979buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000980{
981 Py_off_t target, n;
982 int whence = 0;
983 PyObject *targetobj, *res = NULL;
984
985 CHECK_INITIALIZED(self)
986 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
987 return NULL;
988 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000989 if (whence < 0 || whence > 2) {
990 PyErr_Format(PyExc_ValueError,
991 "whence must be between 0 and 2, not %d", whence);
992 return NULL;
993 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000994
995 CHECK_CLOSED(self, "seek of closed file")
996
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000997 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
998 if (target == -1 && PyErr_Occurred())
999 return NULL;
1000
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001001 if (whence != 2 && self->readable) {
1002 Py_off_t current, avail;
1003 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001004 so as to return quickly if possible. Also, we needn't take the
1005 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001006 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001007 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1008 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001009 current = RAW_TELL(self);
1010 avail = READAHEAD(self);
1011 if (avail > 0) {
1012 Py_off_t offset;
1013 if (whence == 0)
1014 offset = target - (current - RAW_OFFSET(self));
1015 else
1016 offset = target;
1017 if (offset >= -self->pos && offset <= avail) {
1018 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001019 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001020 }
1021 }
1022 }
1023
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001024 ENTER_BUFFERED(self)
1025
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001026 /* Fallback: invoke raw seek() method and clear buffer */
1027 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001028 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001029 if (res == NULL)
1030 goto end;
1031 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001032 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001033 }
1034
1035 /* TODO: align on block boundary and read buffer if needed? */
1036 if (whence == 1)
1037 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001038 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001039 if (n == -1)
1040 goto end;
1041 self->raw_pos = -1;
1042 res = PyLong_FromOff_t(n);
1043 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001044 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001045
1046end:
1047 LEAVE_BUFFERED(self)
1048 return res;
1049}
1050
1051static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001052buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001053{
1054 PyObject *pos = Py_None;
1055 PyObject *res = NULL;
1056
1057 CHECK_INITIALIZED(self)
1058 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1059 return NULL;
1060 }
1061
1062 ENTER_BUFFERED(self)
1063
1064 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001065 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001066 if (res == NULL)
1067 goto end;
1068 Py_CLEAR(res);
1069 }
1070 if (self->readable) {
1071 if (pos == Py_None) {
1072 /* Rewind the raw stream so that its position corresponds to
1073 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001074 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001075 goto end;
1076 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001077 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001078 }
1079 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1080 if (res == NULL)
1081 goto end;
1082 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001083 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001084 PyErr_Clear();
1085
1086end:
1087 LEAVE_BUFFERED(self)
1088 return res;
1089}
1090
1091static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001092buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001093{
1094 PyObject *line;
1095 PyTypeObject *tp;
1096
1097 CHECK_INITIALIZED(self);
1098
1099 tp = Py_TYPE(self);
1100 if (tp == &PyBufferedReader_Type ||
1101 tp == &PyBufferedRandom_Type) {
1102 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001103 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001104 }
1105 else {
1106 line = PyObject_CallMethodObjArgs((PyObject *)self,
1107 _PyIO_str_readline, NULL);
1108 if (line && !PyBytes_Check(line)) {
1109 PyErr_Format(PyExc_IOError,
1110 "readline() should have returned a bytes object, "
1111 "not '%.200s'", Py_TYPE(line)->tp_name);
1112 Py_DECREF(line);
1113 return NULL;
1114 }
1115 }
1116
1117 if (line == NULL)
1118 return NULL;
1119
1120 if (PyBytes_GET_SIZE(line) == 0) {
1121 /* Reached EOF or would have blocked */
1122 Py_DECREF(line);
1123 return NULL;
1124 }
1125
1126 return line;
1127}
1128
Antoine Pitrou716c4442009-05-23 19:04:03 +00001129static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001130buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001131{
1132 PyObject *nameobj, *res;
1133
1134 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1135 if (nameobj == NULL) {
1136 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1137 PyErr_Clear();
1138 else
1139 return NULL;
1140 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1141 }
1142 else {
1143 res = PyUnicode_FromFormat("<%s name=%R>",
1144 Py_TYPE(self)->tp_name, nameobj);
1145 Py_DECREF(nameobj);
1146 }
1147 return res;
1148}
1149
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001150/*
1151 * class BufferedReader
1152 */
1153
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001154PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001155 "Create a new buffered reader using the given readable raw IO object.");
1156
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001157static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001158{
1159 self->read_end = -1;
1160}
1161
1162static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001163bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001164{
1165 char *kwlist[] = {"raw", "buffer_size", NULL};
1166 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1167 PyObject *raw;
1168
1169 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001170 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001171
1172 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1173 &raw, &buffer_size)) {
1174 return -1;
1175 }
1176
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001177 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001178 return -1;
1179
1180 Py_CLEAR(self->raw);
1181 Py_INCREF(raw);
1182 self->raw = raw;
1183 self->buffer_size = buffer_size;
1184 self->readable = 1;
1185 self->writable = 0;
1186
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001187 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001188 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001189 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001190
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001191 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1192 Py_TYPE(raw) == &PyFileIO_Type);
1193
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001194 self->ok = 1;
1195 return 0;
1196}
1197
1198static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001199_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001200{
1201 Py_buffer buf;
1202 PyObject *memobj, *res;
1203 Py_ssize_t n;
1204 /* NOTE: the buffer needn't be released as its object is NULL. */
1205 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1206 return -1;
1207 memobj = PyMemoryView_FromBuffer(&buf);
1208 if (memobj == NULL)
1209 return -1;
1210 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1211 Py_DECREF(memobj);
1212 if (res == NULL)
1213 return -1;
1214 if (res == Py_None) {
1215 /* Non-blocking stream would have blocked. Special return code! */
1216 Py_DECREF(res);
1217 return -2;
1218 }
1219 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1220 Py_DECREF(res);
1221 if (n < 0 || n > len) {
1222 PyErr_Format(PyExc_IOError,
1223 "raw readinto() returned invalid length %zd "
1224 "(should have been between 0 and %zd)", n, len);
1225 return -1;
1226 }
1227 if (n > 0 && self->abs_pos != -1)
1228 self->abs_pos += n;
1229 return n;
1230}
1231
1232static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001233_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001234{
1235 Py_ssize_t start, len, n;
1236 if (VALID_READ_BUFFER(self))
1237 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1238 else
1239 start = 0;
1240 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001241 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001242 if (n <= 0)
1243 return n;
1244 self->read_end = start + n;
1245 self->raw_pos = start + n;
1246 return n;
1247}
1248
1249static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001250_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001251{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001252 Py_ssize_t current_size;
1253 PyObject *res, *data = NULL;
1254 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001255
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001256 if (chunks == NULL)
1257 return NULL;
1258
1259 /* First copy what we have in the current buffer. */
1260 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1261 if (current_size) {
1262 data = PyBytes_FromStringAndSize(
1263 self->buffer + self->pos, current_size);
1264 if (data == NULL) {
1265 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001266 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001267 }
1268 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001269 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001270 /* We're going past the buffer's bounds, flush it */
1271 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001272 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001273 if (res == NULL) {
1274 Py_DECREF(chunks);
1275 return NULL;
1276 }
1277 Py_CLEAR(res);
1278 }
1279 while (1) {
1280 if (data) {
1281 if (PyList_Append(chunks, data) < 0) {
1282 Py_DECREF(data);
1283 Py_DECREF(chunks);
1284 return NULL;
1285 }
1286 Py_DECREF(data);
1287 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001288
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001289 /* Read until EOF or until read() would block. */
1290 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1291 if (data == NULL) {
1292 Py_DECREF(chunks);
1293 return NULL;
1294 }
1295 if (data != Py_None && !PyBytes_Check(data)) {
1296 Py_DECREF(data);
1297 Py_DECREF(chunks);
1298 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1299 return NULL;
1300 }
1301 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1302 if (current_size == 0) {
1303 Py_DECREF(chunks);
1304 return data;
1305 }
1306 else {
1307 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1308 Py_DECREF(data);
1309 Py_DECREF(chunks);
1310 return res;
1311 }
1312 }
1313 current_size += PyBytes_GET_SIZE(data);
1314 if (self->abs_pos != -1)
1315 self->abs_pos += PyBytes_GET_SIZE(data);
1316 }
1317}
1318
1319/* Read n bytes from the buffer if it can, otherwise return None.
1320 This function is simple enough that it can run unlocked. */
1321static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001322_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001323{
1324 Py_ssize_t current_size;
1325
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001326 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1327 if (n <= current_size) {
1328 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001329 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1330 if (res != NULL)
1331 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001332 return res;
1333 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001334 Py_RETURN_NONE;
1335}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001336
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001337/* Generic read function: read from the stream until enough bytes are read,
1338 * or until an EOF occurs or until read() would block.
1339 */
1340static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001341_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001342{
1343 PyObject *res = NULL;
1344 Py_ssize_t current_size, remaining, written;
1345 char *out;
1346
1347 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1348 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001349 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001350
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001351 res = PyBytes_FromStringAndSize(NULL, n);
1352 if (res == NULL)
1353 goto error;
1354 out = PyBytes_AS_STRING(res);
1355 remaining = n;
1356 written = 0;
1357 if (current_size > 0) {
1358 memcpy(out, self->buffer + self->pos, current_size);
1359 remaining -= current_size;
1360 written += current_size;
1361 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001362 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001363 while (remaining > 0) {
1364 /* We want to read a whole block at the end into buffer.
1365 If we had readv() we could do this in one pass. */
1366 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1367 if (r == 0)
1368 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001369 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001370 if (r == -1)
1371 goto error;
1372 if (r == 0 || r == -2) {
1373 /* EOF occurred or read() would block. */
1374 if (r == 0 || written > 0) {
1375 if (_PyBytes_Resize(&res, written))
1376 goto error;
1377 return res;
1378 }
1379 Py_DECREF(res);
1380 Py_INCREF(Py_None);
1381 return Py_None;
1382 }
1383 remaining -= r;
1384 written += r;
1385 }
1386 assert(remaining <= self->buffer_size);
1387 self->pos = 0;
1388 self->raw_pos = 0;
1389 self->read_end = 0;
1390 while (self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001391 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001392 if (r == -1)
1393 goto error;
1394 if (r == 0 || r == -2) {
1395 /* EOF occurred or read() would block. */
1396 if (r == 0 || written > 0) {
1397 if (_PyBytes_Resize(&res, written))
1398 goto error;
1399 return res;
1400 }
1401 Py_DECREF(res);
1402 Py_INCREF(Py_None);
1403 return Py_None;
1404 }
1405 if (remaining > r) {
1406 memcpy(out + written, self->buffer + self->pos, r);
1407 written += r;
1408 self->pos += r;
1409 remaining -= r;
1410 }
1411 else if (remaining > 0) {
1412 memcpy(out + written, self->buffer + self->pos, remaining);
1413 written += remaining;
1414 self->pos += remaining;
1415 remaining = 0;
1416 }
1417 if (remaining == 0)
1418 break;
1419 }
1420
1421 return res;
1422
1423error:
1424 Py_XDECREF(res);
1425 return NULL;
1426}
1427
1428static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001429_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001430{
1431 Py_ssize_t have, r;
1432
1433 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1434 /* Constraints:
1435 1. we don't want to advance the file position.
1436 2. we don't want to lose block alignment, so we can't shift the buffer
1437 to make some place.
1438 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1439 */
1440 if (have > 0) {
1441 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1442 }
1443
1444 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001445 _bufferedreader_reset_buf(self);
1446 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001447 if (r == -1)
1448 return NULL;
1449 if (r == -2)
1450 r = 0;
1451 self->pos = 0;
1452 return PyBytes_FromStringAndSize(self->buffer, r);
1453}
1454
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001455static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001456 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001457 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1458 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1459 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1460 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1461 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1462 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1463 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1464 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001465
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001466 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1467 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1468 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1469 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1470 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1471 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1472 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001473 {NULL, NULL}
1474};
1475
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001476static PyMemberDef bufferedreader_members[] = {
1477 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001478 {NULL}
1479};
1480
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001481static PyGetSetDef bufferedreader_getset[] = {
1482 {"closed", (getter)buffered_closed_get, NULL, NULL},
1483 {"name", (getter)buffered_name_get, NULL, NULL},
1484 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001485 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001486};
1487
1488
1489PyTypeObject PyBufferedReader_Type = {
1490 PyVarObject_HEAD_INIT(NULL, 0)
1491 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001492 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001493 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001494 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001495 0, /*tp_print*/
1496 0, /*tp_getattr*/
1497 0, /*tp_setattr*/
1498 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001499 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001500 0, /*tp_as_number*/
1501 0, /*tp_as_sequence*/
1502 0, /*tp_as_mapping*/
1503 0, /*tp_hash */
1504 0, /*tp_call*/
1505 0, /*tp_str*/
1506 0, /*tp_getattro*/
1507 0, /*tp_setattro*/
1508 0, /*tp_as_buffer*/
1509 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1510 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001511 bufferedreader_doc, /* tp_doc */
1512 (traverseproc)buffered_traverse, /* tp_traverse */
1513 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001514 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001515 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001516 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001517 (iternextfunc)buffered_iternext, /* tp_iternext */
1518 bufferedreader_methods, /* tp_methods */
1519 bufferedreader_members, /* tp_members */
1520 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001521 0, /* tp_base */
1522 0, /* tp_dict */
1523 0, /* tp_descr_get */
1524 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001525 offsetof(buffered, dict), /* tp_dictoffset */
1526 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001527 0, /* tp_alloc */
1528 PyType_GenericNew, /* tp_new */
1529};
1530
1531
Benjamin Peterson59406a92009-03-26 17:10:29 +00001532
1533static int
1534complain_about_max_buffer_size(void)
1535{
1536 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1537 "max_buffer_size is deprecated", 1) < 0)
1538 return 0;
1539 return 1;
1540}
1541
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001542/*
1543 * class BufferedWriter
1544 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001545PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001546 "A buffer for a writeable sequential RawIO object.\n"
1547 "\n"
1548 "The constructor creates a BufferedWriter for the given writeable raw\n"
1549 "stream. If the buffer_size is not given, it defaults to\n"
1550 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1551 );
1552
1553static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001554_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001555{
1556 self->write_pos = 0;
1557 self->write_end = -1;
1558}
1559
1560static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001561bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001562{
1563 /* TODO: properly deprecate max_buffer_size */
1564 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1565 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001566 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001567 PyObject *raw;
1568
1569 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001570 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001571
1572 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1573 &raw, &buffer_size, &max_buffer_size)) {
1574 return -1;
1575 }
1576
Benjamin Peterson59406a92009-03-26 17:10:29 +00001577 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1578 return -1;
1579
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001580 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001581 return -1;
1582
1583 Py_CLEAR(self->raw);
1584 Py_INCREF(raw);
1585 self->raw = raw;
1586 self->readable = 0;
1587 self->writable = 1;
1588
1589 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001590 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001591 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001592 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001593 self->pos = 0;
1594
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001595 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1596 Py_TYPE(raw) == &PyFileIO_Type);
1597
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001598 self->ok = 1;
1599 return 0;
1600}
1601
1602static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001603_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001604{
1605 Py_buffer buf;
1606 PyObject *memobj, *res;
1607 Py_ssize_t n;
1608 /* NOTE: the buffer needn't be released as its object is NULL. */
1609 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1610 return -1;
1611 memobj = PyMemoryView_FromBuffer(&buf);
1612 if (memobj == NULL)
1613 return -1;
1614 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1615 Py_DECREF(memobj);
1616 if (res == NULL)
1617 return -1;
1618 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1619 Py_DECREF(res);
1620 if (n < 0 || n > len) {
1621 PyErr_Format(PyExc_IOError,
1622 "raw write() returned invalid length %zd "
1623 "(should have been between 0 and %zd)", n, len);
1624 return -1;
1625 }
1626 if (n > 0 && self->abs_pos != -1)
1627 self->abs_pos += n;
1628 return n;
1629}
1630
1631/* `restore_pos` is 1 if we need to restore the raw stream position at
1632 the end, 0 otherwise. */
1633static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001634_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001635{
1636 Py_ssize_t written = 0;
1637 Py_off_t n, rewind;
1638
1639 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1640 goto end;
1641 /* First, rewind */
1642 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1643 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001644 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001645 if (n < 0) {
1646 goto error;
1647 }
1648 self->raw_pos -= rewind;
1649 }
1650 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001651 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001652 self->buffer + self->write_pos,
1653 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1654 Py_off_t, Py_ssize_t));
1655 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001656 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001657 if (w == NULL)
1658 goto error;
1659 self->write_pos += *w;
1660 self->raw_pos = self->write_pos;
1661 written += *w;
1662 *w = written;
1663 /* Already re-raised */
1664 goto error;
1665 }
1666 self->write_pos += n;
1667 self->raw_pos = self->write_pos;
1668 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1669 }
1670
1671 if (restore_pos) {
1672 Py_off_t forward = rewind - written;
1673 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001674 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001675 if (n < 0) {
1676 goto error;
1677 }
1678 self->raw_pos += forward;
1679 }
1680 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001681 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001682
1683end:
1684 Py_RETURN_NONE;
1685
1686error:
1687 return NULL;
1688}
1689
1690static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001691bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001692{
1693 PyObject *res = NULL;
1694 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001695 Py_ssize_t written, avail, remaining;
1696 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001697
1698 CHECK_INITIALIZED(self)
1699 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1700 return NULL;
1701 }
1702
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001703 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001704 PyErr_SetString(PyExc_ValueError, "write to closed file");
1705 PyBuffer_Release(&buf);
1706 return NULL;
1707 }
1708
1709 ENTER_BUFFERED(self)
1710
1711 /* Fast path: the data to write can be fully buffered. */
1712 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1713 self->pos = 0;
1714 self->raw_pos = 0;
1715 }
1716 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1717 if (buf.len <= avail) {
1718 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1719 if (!VALID_WRITE_BUFFER(self)) {
1720 self->write_pos = self->pos;
1721 }
1722 ADJUST_POSITION(self, self->pos + buf.len);
1723 if (self->pos > self->write_end)
1724 self->write_end = self->pos;
1725 written = buf.len;
1726 goto end;
1727 }
1728
1729 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001730 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001731 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001732 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001733 if (w == NULL)
1734 goto error;
1735 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001736 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001737 /* Make some place by shifting the buffer. */
1738 assert(VALID_WRITE_BUFFER(self));
1739 memmove(self->buffer, self->buffer + self->write_pos,
1740 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1741 Py_off_t, Py_ssize_t));
1742 self->write_end -= self->write_pos;
1743 self->raw_pos -= self->write_pos;
1744 self->pos -= self->write_pos;
1745 self->write_pos = 0;
1746 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1747 Py_off_t, Py_ssize_t);
1748 if (buf.len <= avail) {
1749 /* Everything can be buffered */
1750 PyErr_Clear();
1751 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1752 self->write_end += buf.len;
1753 written = buf.len;
1754 goto end;
1755 }
1756 /* Buffer as much as possible. */
1757 memcpy(self->buffer + self->write_end, buf.buf, avail);
1758 self->write_end += avail;
1759 /* Already re-raised */
1760 *w = avail;
1761 goto error;
1762 }
1763 Py_CLEAR(res);
1764
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001765 /* Adjust the raw stream position if it is away from the logical stream
1766 position. This happens if the read buffer has been filled but not
1767 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1768 the raw stream by itself).
1769 Fixes issue #6629.
1770 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001771 offset = RAW_OFFSET(self);
1772 if (offset != 0) {
1773 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001774 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001775 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001776 }
1777
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001778 /* Then write buf itself. At this point the buffer has been emptied. */
1779 remaining = buf.len;
1780 written = 0;
1781 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001782 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001783 self, (char *) buf.buf + written, buf.len - written);
1784 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001785 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001786 if (w == NULL)
1787 goto error;
1788 written += *w;
1789 remaining -= *w;
1790 if (remaining > self->buffer_size) {
1791 /* Can't buffer everything, still buffer as much as possible */
1792 memcpy(self->buffer,
1793 (char *) buf.buf + written, self->buffer_size);
1794 self->raw_pos = 0;
1795 ADJUST_POSITION(self, self->buffer_size);
1796 self->write_end = self->buffer_size;
1797 *w = written + self->buffer_size;
1798 /* Already re-raised */
1799 goto error;
1800 }
1801 PyErr_Clear();
1802 break;
1803 }
1804 written += n;
1805 remaining -= n;
1806 }
1807 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001808 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001809 if (remaining > 0) {
1810 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1811 written += remaining;
1812 }
1813 self->write_pos = 0;
1814 /* TODO: sanity check (remaining >= 0) */
1815 self->write_end = remaining;
1816 ADJUST_POSITION(self, remaining);
1817 self->raw_pos = 0;
1818
1819end:
1820 res = PyLong_FromSsize_t(written);
1821
1822error:
1823 LEAVE_BUFFERED(self)
1824 PyBuffer_Release(&buf);
1825 return res;
1826}
1827
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001828static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001829 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001830 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1831 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1832 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1833 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1834 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1835 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1836 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001837
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001838 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1839 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1840 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1841 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1842 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001843 {NULL, NULL}
1844};
1845
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001846static PyMemberDef bufferedwriter_members[] = {
1847 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001848 {NULL}
1849};
1850
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001851static PyGetSetDef bufferedwriter_getset[] = {
1852 {"closed", (getter)buffered_closed_get, NULL, NULL},
1853 {"name", (getter)buffered_name_get, NULL, NULL},
1854 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001855 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001856};
1857
1858
1859PyTypeObject PyBufferedWriter_Type = {
1860 PyVarObject_HEAD_INIT(NULL, 0)
1861 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001862 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001863 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001864 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001865 0, /*tp_print*/
1866 0, /*tp_getattr*/
1867 0, /*tp_setattr*/
1868 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001869 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001870 0, /*tp_as_number*/
1871 0, /*tp_as_sequence*/
1872 0, /*tp_as_mapping*/
1873 0, /*tp_hash */
1874 0, /*tp_call*/
1875 0, /*tp_str*/
1876 0, /*tp_getattro*/
1877 0, /*tp_setattro*/
1878 0, /*tp_as_buffer*/
1879 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1880 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001881 bufferedwriter_doc, /* tp_doc */
1882 (traverseproc)buffered_traverse, /* tp_traverse */
1883 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001884 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001885 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001886 0, /* tp_iter */
1887 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001888 bufferedwriter_methods, /* tp_methods */
1889 bufferedwriter_members, /* tp_members */
1890 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001891 0, /* tp_base */
1892 0, /* tp_dict */
1893 0, /* tp_descr_get */
1894 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001895 offsetof(buffered, dict), /* tp_dictoffset */
1896 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001897 0, /* tp_alloc */
1898 PyType_GenericNew, /* tp_new */
1899};
1900
1901
1902
1903/*
1904 * BufferedRWPair
1905 */
1906
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001907PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001908 "A buffered reader and writer object together.\n"
1909 "\n"
1910 "A buffered reader object and buffered writer object put together to\n"
1911 "form a sequential IO object that can read and write. This is typically\n"
1912 "used with a socket or two-way pipe.\n"
1913 "\n"
1914 "reader and writer are RawIOBase objects that are readable and\n"
1915 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001916 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001917 );
1918
1919/* XXX The usefulness of this (compared to having two separate IO objects) is
1920 * questionable.
1921 */
1922
1923typedef struct {
1924 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001925 buffered *reader;
1926 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001927 PyObject *dict;
1928 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001929} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001930
1931static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001932bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001933{
1934 PyObject *reader, *writer;
1935 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001936 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001937
1938 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1939 &buffer_size, &max_buffer_size)) {
1940 return -1;
1941 }
1942
Benjamin Peterson59406a92009-03-26 17:10:29 +00001943 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1944 return -1;
1945
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001946 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001947 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001948 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001949 return -1;
1950
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001951 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001952 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001953 if (self->reader == NULL)
1954 return -1;
1955
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001956 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001957 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001958 if (self->writer == NULL) {
1959 Py_CLEAR(self->reader);
1960 return -1;
1961 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001962
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001963 return 0;
1964}
1965
1966static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001967bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001968{
1969 Py_VISIT(self->dict);
1970 return 0;
1971}
1972
1973static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001974bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001975{
1976 Py_CLEAR(self->reader);
1977 Py_CLEAR(self->writer);
1978 Py_CLEAR(self->dict);
1979 return 0;
1980}
1981
1982static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001983bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001984{
1985 _PyObject_GC_UNTRACK(self);
1986 Py_CLEAR(self->reader);
1987 Py_CLEAR(self->writer);
1988 Py_CLEAR(self->dict);
1989 Py_TYPE(self)->tp_free((PyObject *) self);
1990}
1991
1992static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001993_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001994{
1995 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1996 PyObject *ret;
1997
1998 if (func == NULL) {
1999 PyErr_SetString(PyExc_AttributeError, name);
2000 return NULL;
2001 }
2002
2003 ret = PyObject_CallObject(func, args);
2004 Py_DECREF(func);
2005 return ret;
2006}
2007
2008static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002009bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002010{
2011 return _forward_call(self->reader, "read", args);
2012}
2013
2014static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002015bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002016{
2017 return _forward_call(self->reader, "peek", args);
2018}
2019
2020static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002021bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002022{
2023 return _forward_call(self->reader, "read1", args);
2024}
2025
2026static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002027bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002028{
2029 return _forward_call(self->reader, "readinto", args);
2030}
2031
2032static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002033bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002034{
2035 return _forward_call(self->writer, "write", args);
2036}
2037
2038static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002039bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002040{
2041 return _forward_call(self->writer, "flush", args);
2042}
2043
2044static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002045bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002046{
2047 return _forward_call(self->reader, "readable", args);
2048}
2049
2050static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002051bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002052{
2053 return _forward_call(self->writer, "writable", args);
2054}
2055
2056static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002057bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002058{
2059 PyObject *ret = _forward_call(self->writer, "close", args);
2060 if (ret == NULL)
2061 return NULL;
2062 Py_DECREF(ret);
2063
2064 return _forward_call(self->reader, "close", args);
2065}
2066
2067static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002068bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002069{
2070 PyObject *ret = _forward_call(self->writer, "isatty", args);
2071
2072 if (ret != Py_False) {
2073 /* either True or exception */
2074 return ret;
2075 }
2076 Py_DECREF(ret);
2077
2078 return _forward_call(self->reader, "isatty", args);
2079}
2080
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002081static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002082bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002083{
2084 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2085}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002086
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002087static PyMethodDef bufferedrwpair_methods[] = {
2088 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2089 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2090 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2091 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002092
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002093 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2094 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002095
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002096 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2097 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002098
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002099 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2100 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002101
2102 {NULL, NULL}
2103};
2104
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002105static PyGetSetDef bufferedrwpair_getset[] = {
2106 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002107 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002108};
2109
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002110PyTypeObject PyBufferedRWPair_Type = {
2111 PyVarObject_HEAD_INIT(NULL, 0)
2112 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002113 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002114 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002115 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002116 0, /*tp_print*/
2117 0, /*tp_getattr*/
2118 0, /*tp_setattr*/
2119 0, /*tp_compare */
2120 0, /*tp_repr*/
2121 0, /*tp_as_number*/
2122 0, /*tp_as_sequence*/
2123 0, /*tp_as_mapping*/
2124 0, /*tp_hash */
2125 0, /*tp_call*/
2126 0, /*tp_str*/
2127 0, /*tp_getattro*/
2128 0, /*tp_setattro*/
2129 0, /*tp_as_buffer*/
2130 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2131 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002132 bufferedrwpair_doc, /* tp_doc */
2133 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2134 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002135 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002136 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002137 0, /* tp_iter */
2138 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002139 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002140 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002141 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002142 0, /* tp_base */
2143 0, /* tp_dict */
2144 0, /* tp_descr_get */
2145 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002146 offsetof(rwpair, dict), /* tp_dictoffset */
2147 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002148 0, /* tp_alloc */
2149 PyType_GenericNew, /* tp_new */
2150};
2151
2152
2153
2154/*
2155 * BufferedRandom
2156 */
2157
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002158PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002159 "A buffered interface to random access streams.\n"
2160 "\n"
2161 "The constructor creates a reader and writer for a seekable stream,\n"
2162 "raw, given in the first argument. If the buffer_size is omitted it\n"
2163 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2164 );
2165
2166static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002167bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002168{
2169 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2170 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002171 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002172 PyObject *raw;
2173
2174 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002175 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002176
2177 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2178 &raw, &buffer_size, &max_buffer_size)) {
2179 return -1;
2180 }
2181
Benjamin Peterson59406a92009-03-26 17:10:29 +00002182 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2183 return -1;
2184
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002185 if (_PyIOBase_check_seekable(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_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002188 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002189 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002190 return -1;
2191
2192 Py_CLEAR(self->raw);
2193 Py_INCREF(raw);
2194 self->raw = raw;
2195 self->buffer_size = buffer_size;
2196 self->readable = 1;
2197 self->writable = 1;
2198
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002199 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002200 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002201 _bufferedreader_reset_buf(self);
2202 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002203 self->pos = 0;
2204
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002205 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2206 Py_TYPE(raw) == &PyFileIO_Type);
2207
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002208 self->ok = 1;
2209 return 0;
2210}
2211
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002212static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002213 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002214 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2215 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2216 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2217 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2218 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2219 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2220 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002221
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002222 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002223
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002224 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2225 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2226 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2227 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2228 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2229 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2230 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2231 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2232 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002233 {NULL, NULL}
2234};
2235
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002236static PyMemberDef bufferedrandom_members[] = {
2237 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002238 {NULL}
2239};
2240
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002241static PyGetSetDef bufferedrandom_getset[] = {
2242 {"closed", (getter)buffered_closed_get, NULL, NULL},
2243 {"name", (getter)buffered_name_get, NULL, NULL},
2244 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002245 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002246};
2247
2248
2249PyTypeObject PyBufferedRandom_Type = {
2250 PyVarObject_HEAD_INIT(NULL, 0)
2251 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002252 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002253 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002254 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002255 0, /*tp_print*/
2256 0, /*tp_getattr*/
2257 0, /*tp_setattr*/
2258 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002259 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002260 0, /*tp_as_number*/
2261 0, /*tp_as_sequence*/
2262 0, /*tp_as_mapping*/
2263 0, /*tp_hash */
2264 0, /*tp_call*/
2265 0, /*tp_str*/
2266 0, /*tp_getattro*/
2267 0, /*tp_setattro*/
2268 0, /*tp_as_buffer*/
2269 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2270 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002271 bufferedrandom_doc, /* tp_doc */
2272 (traverseproc)buffered_traverse, /* tp_traverse */
2273 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002274 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002275 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002276 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002277 (iternextfunc)buffered_iternext, /* tp_iternext */
2278 bufferedrandom_methods, /* tp_methods */
2279 bufferedrandom_members, /* tp_members */
2280 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002281 0, /* tp_base */
2282 0, /*tp_dict*/
2283 0, /* tp_descr_get */
2284 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002285 offsetof(buffered, dict), /*tp_dictoffset*/
2286 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002287 0, /* tp_alloc */
2288 PyType_GenericNew, /* tp_new */
2289};
2290