blob: 8e3d3c67b582dab9729abfe5a02625ba0c95e866 [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"
Antoine Pitrou3486a982011-05-12 01:57:53 +02003
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00004 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
Antoine Pitrou3486a982011-05-12 01:57:53 +02006
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00007 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 Pitroue033e062010-10-29 10:38:18 +0000200 int deallocating;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200201
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000202 /* True if this is a vanilla Buffered object (rather than a user derived
203 class) *and* the raw stream is a vanilla FileIO object. */
204 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000205
206 /* Absolute position inside the raw stream (-1 if unknown). */
207 Py_off_t abs_pos;
208
209 /* A static buffer of size `buffer_size` */
210 char *buffer;
211 /* Current logical position in the buffer. */
212 Py_off_t pos;
213 /* Position of the raw stream in the buffer. */
214 Py_off_t raw_pos;
215
216 /* Just after the last buffered byte in the buffer, or -1 if the buffer
217 isn't ready for reading. */
218 Py_off_t read_end;
219
220 /* Just after the last byte actually written */
221 Py_off_t write_pos;
222 /* Just after the last byte waiting to be written, or -1 if the buffer
223 isn't ready for writing. */
224 Py_off_t write_end;
225
Georg Brandldfd73442009-04-05 11:47:34 +0000226#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000227 PyThread_type_lock lock;
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000228 volatile long owner;
Georg Brandldfd73442009-04-05 11:47:34 +0000229#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000230
231 Py_ssize_t buffer_size;
232 Py_ssize_t buffer_mask;
233
234 PyObject *dict;
235 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000236} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000237
238/*
239 Implementation notes:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200240
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000241 * BufferedReader, BufferedWriter and BufferedRandom try to share most
242 methods (this is helped by the members `readable` and `writable`, which
243 are initialized in the respective constructors)
244 * They also share a single buffer for reading and writing. This enables
245 interleaved reads and writes without flushing. It also makes the logic
246 a bit trickier to get right.
247 * The absolute position of the raw stream is cached, if possible, in the
248 `abs_pos` member. It must be updated every time an operation is done
249 on the raw stream. If not sure, it can be reinitialized by calling
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000250 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000251 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000252 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
253 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000254
255 NOTE: we should try to maintain block alignment of reads and writes to the
256 raw stream (according to the buffer size), but for now it is only done
257 in read() and friends.
Antoine Pitrou3486a982011-05-12 01:57:53 +0200258
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000259*/
260
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000261/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000262
Georg Brandldfd73442009-04-05 11:47:34 +0000263#ifdef WITH_THREAD
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000264
265static int
266_enter_buffered_busy(buffered *self)
267{
268 if (self->owner == PyThread_get_thread_ident()) {
269 PyErr_Format(PyExc_RuntimeError,
270 "reentrant call inside %R", self);
271 return 0;
Antoine Pitrou5800b272009-11-01 12:05:48 +0000272 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000273 Py_BEGIN_ALLOW_THREADS
274 PyThread_acquire_lock(self->lock, 1);
275 Py_END_ALLOW_THREADS
276 return 1;
277}
278
279#define ENTER_BUFFERED(self) \
280 ( (PyThread_acquire_lock(self->lock, 0) ? \
281 1 : _enter_buffered_busy(self)) \
282 && (self->owner = PyThread_get_thread_ident(), 1) )
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000283
284#define LEAVE_BUFFERED(self) \
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000285 do { \
286 self->owner = 0; \
287 PyThread_release_lock(self->lock); \
288 } while(0);
289
Georg Brandldfd73442009-04-05 11:47:34 +0000290#else
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000291#define ENTER_BUFFERED(self) 1
Georg Brandldfd73442009-04-05 11:47:34 +0000292#define LEAVE_BUFFERED(self)
293#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000294
295#define CHECK_INITIALIZED(self) \
296 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000297 if (self->detached) { \
298 PyErr_SetString(PyExc_ValueError, \
299 "raw stream has been detached"); \
300 } else { \
301 PyErr_SetString(PyExc_ValueError, \
302 "I/O operation on uninitialized object"); \
303 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000304 return NULL; \
305 }
306
307#define CHECK_INITIALIZED_INT(self) \
308 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000309 if (self->detached) { \
310 PyErr_SetString(PyExc_ValueError, \
311 "raw stream has been detached"); \
312 } else { \
313 PyErr_SetString(PyExc_ValueError, \
314 "I/O operation on uninitialized object"); \
315 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000316 return -1; \
317 }
318
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000319#define IS_CLOSED(self) \
320 (self->fast_closed_checks \
321 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000322 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000323
324#define CHECK_CLOSED(self, error_msg) \
325 if (IS_CLOSED(self)) { \
326 PyErr_SetString(PyExc_ValueError, error_msg); \
327 return NULL; \
328 }
329
330
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000331#define VALID_READ_BUFFER(self) \
332 (self->readable && self->read_end != -1)
333
334#define VALID_WRITE_BUFFER(self) \
335 (self->writable && self->write_end != -1)
336
337#define ADJUST_POSITION(self, _new_pos) \
338 do { \
339 self->pos = _new_pos; \
340 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
341 self->read_end = self->pos; \
342 } while(0)
343
344#define READAHEAD(self) \
345 ((self->readable && VALID_READ_BUFFER(self)) \
346 ? (self->read_end - self->pos) : 0)
347
348#define RAW_OFFSET(self) \
349 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
350 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
351
352#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000353 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000354
355#define MINUS_LAST_BLOCK(self, size) \
356 (self->buffer_mask ? \
357 (size & ~self->buffer_mask) : \
358 (self->buffer_size * (size / self->buffer_size)))
359
360
361static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000362buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000363{
Antoine Pitroue033e062010-10-29 10:38:18 +0000364 self->deallocating = 1;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000365 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
366 return;
367 _PyObject_GC_UNTRACK(self);
368 self->ok = 0;
369 if (self->weakreflist != NULL)
370 PyObject_ClearWeakRefs((PyObject *)self);
371 Py_CLEAR(self->raw);
372 if (self->buffer) {
373 PyMem_Free(self->buffer);
374 self->buffer = NULL;
375 }
Georg Brandldfd73442009-04-05 11:47:34 +0000376#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000377 if (self->lock) {
378 PyThread_free_lock(self->lock);
379 self->lock = NULL;
380 }
Georg Brandldfd73442009-04-05 11:47:34 +0000381#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000382 Py_CLEAR(self->dict);
383 Py_TYPE(self)->tp_free((PyObject *)self);
384}
385
386static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000387buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000388{
389 Py_VISIT(self->raw);
390 Py_VISIT(self->dict);
391 return 0;
392}
393
394static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000395buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000396{
397 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
398 return -1;
399 self->ok = 0;
400 Py_CLEAR(self->raw);
401 Py_CLEAR(self->dict);
402 return 0;
403}
404
Antoine Pitroue033e062010-10-29 10:38:18 +0000405/* Because this can call arbitrary code, it shouldn't be called when
406 the refcount is 0 (that is, not directly from tp_dealloc unless
407 the refcount has been temporarily re-incremented). */
Matthias Klosebee33162010-11-16 20:07:51 +0000408static PyObject *
Antoine Pitroue033e062010-10-29 10:38:18 +0000409buffered_dealloc_warn(buffered *self, PyObject *source)
410{
411 if (self->ok && self->raw) {
412 PyObject *r;
413 r = PyObject_CallMethod(self->raw, "_dealloc_warn", "O", source);
414 if (r)
415 Py_DECREF(r);
416 else
417 PyErr_Clear();
418 }
419 Py_RETURN_NONE;
420}
421
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000422/*
423 * _BufferedIOMixin methods
424 * This is not a class, just a collection of methods that will be reused
425 * by BufferedReader and BufferedWriter
426 */
427
428/* Flush and close */
429
430static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000431buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000432{
433 CHECK_INITIALIZED(self)
434 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
435}
436
437static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000438buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000439{
440 int closed;
441 PyObject *res;
442 CHECK_INITIALIZED_INT(self)
443 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
444 if (res == NULL)
445 return -1;
446 closed = PyObject_IsTrue(res);
447 Py_DECREF(res);
448 return closed;
449}
450
451static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000452buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000453{
454 CHECK_INITIALIZED(self)
455 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
456}
457
458static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000459buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000460{
461 PyObject *res = NULL;
462 int r;
463
464 CHECK_INITIALIZED(self)
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000465 if (!ENTER_BUFFERED(self))
466 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000467
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000468 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000469 if (r < 0)
470 goto end;
471 if (r > 0) {
472 res = Py_None;
473 Py_INCREF(res);
474 goto end;
475 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000476
477 if (self->deallocating) {
478 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
479 if (r)
480 Py_DECREF(r);
481 else
482 PyErr_Clear();
483 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000484 /* flush() will most probably re-take the lock, so drop it first */
485 LEAVE_BUFFERED(self)
486 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000487 if (!ENTER_BUFFERED(self))
488 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000489 if (res == NULL) {
Antoine Pitrou6be88762010-05-03 16:48:20 +0000490 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000491 }
492 Py_XDECREF(res);
493
494 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
495
496end:
497 LEAVE_BUFFERED(self)
498 return res;
499}
500
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000501/* detach */
502
503static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000504buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000505{
506 PyObject *raw, *res;
507 CHECK_INITIALIZED(self)
508 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
509 if (res == NULL)
510 return NULL;
511 Py_DECREF(res);
512 raw = self->raw;
513 self->raw = NULL;
514 self->detached = 1;
515 self->ok = 0;
516 return raw;
517}
518
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000519/* Inquiries */
520
521static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000522buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000523{
524 CHECK_INITIALIZED(self)
525 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
526}
527
528static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000529buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000530{
531 CHECK_INITIALIZED(self)
532 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
533}
534
535static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000536buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000537{
538 CHECK_INITIALIZED(self)
539 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
540}
541
542static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000543buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000544{
545 CHECK_INITIALIZED(self)
546 return PyObject_GetAttrString(self->raw, "name");
547}
548
549static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000550buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000551{
552 CHECK_INITIALIZED(self)
553 return PyObject_GetAttrString(self->raw, "mode");
554}
555
556/* Lower-level APIs */
557
558static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000559buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000560{
561 CHECK_INITIALIZED(self)
562 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
563}
564
565static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000566buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000567{
568 CHECK_INITIALIZED(self)
569 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
570}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000571
Antoine Pitrou243757e2010-11-05 21:15:39 +0000572/* Serialization */
573
574static PyObject *
575buffered_getstate(buffered *self, PyObject *args)
576{
577 PyErr_Format(PyExc_TypeError,
578 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
579 return NULL;
580}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000581
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000582/* Forward decls */
583static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000584_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000585static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000586_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000587static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000588_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000589static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000590_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000591static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000592_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000593static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000594_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000595static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000596_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000597static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000598_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200599static Py_ssize_t
600_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000601
602/*
603 * Helpers
604 */
605
606/* Returns the address of the `written` member if a BlockingIOError was
607 raised, NULL otherwise. The error is always re-raised. */
608static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000609_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000610{
611 PyObject *t, *v, *tb;
612 PyBlockingIOErrorObject *err;
613
614 PyErr_Fetch(&t, &v, &tb);
615 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
616 PyErr_Restore(t, v, tb);
617 return NULL;
618 }
619 err = (PyBlockingIOErrorObject *) v;
620 /* TODO: sanity check (err->written >= 0) */
621 PyErr_Restore(t, v, tb);
622 return &err->written;
623}
624
625static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000626_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000627{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000628 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000629 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000630 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
631 if (res == NULL)
632 return -1;
633 n = PyNumber_AsOff_t(res, PyExc_ValueError);
634 Py_DECREF(res);
635 if (n < 0) {
636 if (!PyErr_Occurred())
637 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000638 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200639 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000640 return -1;
641 }
642 self->abs_pos = n;
643 return n;
644}
645
646static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000647_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000648{
649 PyObject *res, *posobj, *whenceobj;
650 Py_off_t n;
651
652 posobj = PyLong_FromOff_t(target);
653 if (posobj == NULL)
654 return -1;
655 whenceobj = PyLong_FromLong(whence);
656 if (whenceobj == NULL) {
657 Py_DECREF(posobj);
658 return -1;
659 }
660 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
661 posobj, whenceobj, NULL);
662 Py_DECREF(posobj);
663 Py_DECREF(whenceobj);
664 if (res == NULL)
665 return -1;
666 n = PyNumber_AsOff_t(res, PyExc_ValueError);
667 Py_DECREF(res);
668 if (n < 0) {
669 if (!PyErr_Occurred())
670 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000671 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200672 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000673 return -1;
674 }
675 self->abs_pos = n;
676 return n;
677}
678
679static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000680_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000681{
682 Py_ssize_t n;
683 if (self->buffer_size <= 0) {
684 PyErr_SetString(PyExc_ValueError,
685 "buffer size must be strictly positive");
686 return -1;
687 }
688 if (self->buffer)
689 PyMem_Free(self->buffer);
690 self->buffer = PyMem_Malloc(self->buffer_size);
691 if (self->buffer == NULL) {
692 PyErr_NoMemory();
693 return -1;
694 }
Georg Brandldfd73442009-04-05 11:47:34 +0000695#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000696 if (self->lock)
697 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000698 self->lock = PyThread_allocate_lock();
699 if (self->lock == NULL) {
700 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
701 return -1;
702 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000703 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000704#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000705 /* Find out whether buffer_size is a power of 2 */
706 /* XXX is this optimization useful? */
707 for (n = self->buffer_size - 1; n & 1; n >>= 1)
708 ;
709 if (n == 0)
710 self->buffer_mask = self->buffer_size - 1;
711 else
712 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000713 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000714 PyErr_Clear();
715 return 0;
716}
717
Antoine Pitrou707ce822011-02-25 21:24:11 +0000718/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
719 clears the error indicator), 0 otherwise.
720 Should only be called when PyErr_Occurred() is true.
721*/
722static int
723_trap_eintr(void)
724{
725 static PyObject *eintr_int = NULL;
726 PyObject *typ, *val, *tb;
727 PyEnvironmentErrorObject *env_err;
728
729 if (eintr_int == NULL) {
730 eintr_int = PyLong_FromLong(EINTR);
731 assert(eintr_int != NULL);
732 }
733 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
734 return 0;
735 PyErr_Fetch(&typ, &val, &tb);
736 PyErr_NormalizeException(&typ, &val, &tb);
737 env_err = (PyEnvironmentErrorObject *) val;
738 assert(env_err != NULL);
739 if (env_err->myerrno != NULL &&
740 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
741 Py_DECREF(typ);
742 Py_DECREF(val);
743 Py_XDECREF(tb);
744 return 1;
745 }
746 /* This silences any error set by PyObject_RichCompareBool() */
747 PyErr_Restore(typ, val, tb);
748 return 0;
749}
750
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000751/*
752 * Shared methods and wrappers
753 */
754
755static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000756buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000757{
758 PyObject *res;
759
760 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000761 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000762
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000763 if (!ENTER_BUFFERED(self))
764 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000765 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000766 if (res != NULL && self->readable) {
767 /* Rewind the raw stream so that its position corresponds to
768 the current logical position. */
769 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000770 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000771 if (n == -1)
772 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000773 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000774 }
775 LEAVE_BUFFERED(self)
776
777 return res;
778}
779
780static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000781buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000782{
783 Py_ssize_t n = 0;
784 PyObject *res = NULL;
785
786 CHECK_INITIALIZED(self)
787 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
788 return NULL;
789 }
790
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000791 if (!ENTER_BUFFERED(self))
792 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000793
794 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000795 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000796 if (res == NULL)
797 goto end;
798 Py_CLEAR(res);
799 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000800 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000801
802end:
803 LEAVE_BUFFERED(self)
804 return res;
805}
806
807static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000808buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000809{
810 Py_ssize_t n = -1;
811 PyObject *res;
812
813 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000814 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000815 return NULL;
816 }
817 if (n < -1) {
818 PyErr_SetString(PyExc_ValueError,
819 "read length must be positive or -1");
820 return NULL;
821 }
822
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000823 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000824
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000825 if (n == -1) {
826 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000827 if (!ENTER_BUFFERED(self))
828 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000829 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000830 LEAVE_BUFFERED(self)
831 }
832 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000833 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000834 if (res == Py_None) {
835 Py_DECREF(res);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000836 if (!ENTER_BUFFERED(self))
837 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000838 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000839 LEAVE_BUFFERED(self)
840 }
841 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000842
843 return res;
844}
845
846static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000847buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000848{
849 Py_ssize_t n, have, r;
850 PyObject *res = NULL;
851
852 CHECK_INITIALIZED(self)
853 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
854 return NULL;
855 }
856
857 if (n < 0) {
858 PyErr_SetString(PyExc_ValueError,
859 "read length must be positive");
860 return NULL;
861 }
862 if (n == 0)
863 return PyBytes_FromStringAndSize(NULL, 0);
864
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000865 if (!ENTER_BUFFERED(self))
866 return NULL;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200867
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000868 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000869 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000870 if (res == NULL)
871 goto end;
872 Py_CLEAR(res);
873 }
874
875 /* Return up to n bytes. If at least one byte is buffered, we
876 only return buffered bytes. Otherwise, we do one raw read. */
877
878 /* XXX: this mimicks the io.py implementation but is probably wrong.
879 If we need to read from the raw stream, then we could actually read
880 all `n` bytes asked by the caller (and possibly more, so as to fill
881 our buffer for the next reads). */
882
883 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
884 if (have > 0) {
885 if (n > have)
886 n = have;
887 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
888 if (res == NULL)
889 goto end;
890 self->pos += n;
891 goto end;
892 }
893
894 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000895 _bufferedreader_reset_buf(self);
896 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000897 if (r == -1)
898 goto end;
899 if (r == -2)
900 r = 0;
901 if (n > r)
902 n = r;
903 res = PyBytes_FromStringAndSize(self->buffer, n);
904 if (res == NULL)
905 goto end;
906 self->pos = n;
907
908end:
909 LEAVE_BUFFERED(self)
910 return res;
911}
912
913static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000914buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000915{
Antoine Pitrou3486a982011-05-12 01:57:53 +0200916 Py_buffer buf;
917 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000918 PyObject *res = NULL;
919
920 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +0200921
922 if (!PyArg_ParseTuple(args, "w*:readinto", &buf))
923 return NULL;
924
925 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
926 if (n > 0) {
927 if (n >= buf.len) {
928 memcpy(buf.buf, self->buffer + self->pos, buf.len);
929 self->pos += buf.len;
930 res = PyLong_FromSsize_t(buf.len);
931 goto end_unlocked;
932 }
933 memcpy(buf.buf, self->buffer + self->pos, n);
934 self->pos += n;
935 written = n;
936 }
937
938 if (!ENTER_BUFFERED(self))
939 goto end_unlocked;
940
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000941 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000942 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000943 if (res == NULL)
944 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200945 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000946 }
Antoine Pitrou3486a982011-05-12 01:57:53 +0200947
948 _bufferedreader_reset_buf(self);
949 self->pos = 0;
950
951 for (remaining = buf.len - written;
952 remaining > 0;
953 written += n, remaining -= n) {
954 /* If remaining bytes is larger than internal buffer size, copy
955 * directly into caller's buffer. */
956 if (remaining > self->buffer_size) {
957 n = _bufferedreader_raw_read(self, buf.buf + written, remaining);
958 }
959 else {
960 n = _bufferedreader_fill_buffer(self);
961 if (n > 0) {
962 if (n > remaining)
963 n = remaining;
964 memcpy(buf.buf + written, self->buffer + self->pos, n);
965 self->pos += n;
966 continue; /* short circuit */
967 }
968 }
969 if (n == 0 || (n == -2 && written > 0))
970 break;
971 if (n < 0) {
972 if (n == -2) {
973 Py_INCREF(Py_None);
974 res = Py_None;
975 }
976 goto end;
977 }
978 }
979 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000980
981end:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200982 LEAVE_BUFFERED(self);
983end_unlocked:
984 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000985 return res;
986}
987
988static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000989_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000990{
991 PyObject *res = NULL;
992 PyObject *chunks = NULL;
993 Py_ssize_t n, written = 0;
994 const char *start, *s, *end;
995
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000996 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000997
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000998 /* First, try to find a line in the buffer. This can run unlocked because
999 the calls to the C API are simple enough that they can't trigger
1000 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001001 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1002 if (limit >= 0 && n > limit)
1003 n = limit;
1004 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001005 s = memchr(start, '\n', n);
1006 if (s != NULL) {
1007 res = PyBytes_FromStringAndSize(start, s - start + 1);
1008 if (res != NULL)
1009 self->pos += s - start + 1;
1010 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001011 }
1012 if (n == limit) {
1013 res = PyBytes_FromStringAndSize(start, n);
1014 if (res != NULL)
1015 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001016 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001017 }
1018
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001019 if (!ENTER_BUFFERED(self))
1020 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001021
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001022 /* Now we try to get some more from the raw stream */
1023 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001024 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001025 if (res == NULL)
1026 goto end;
1027 Py_CLEAR(res);
1028 }
1029 chunks = PyList_New(0);
1030 if (chunks == NULL)
1031 goto end;
1032 if (n > 0) {
1033 res = PyBytes_FromStringAndSize(start, n);
1034 if (res == NULL)
1035 goto end;
1036 if (PyList_Append(chunks, res) < 0) {
1037 Py_CLEAR(res);
1038 goto end;
1039 }
1040 Py_CLEAR(res);
1041 written += n;
1042 if (limit >= 0)
1043 limit -= n;
1044 }
1045
1046 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001047 _bufferedreader_reset_buf(self);
1048 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001049 if (n == -1)
1050 goto end;
1051 if (n <= 0)
1052 break;
1053 if (limit >= 0 && n > limit)
1054 n = limit;
1055 start = self->buffer;
1056 end = start + n;
1057 s = start;
1058 while (s < end) {
1059 if (*s++ == '\n') {
1060 res = PyBytes_FromStringAndSize(start, s - start);
1061 if (res == NULL)
1062 goto end;
1063 self->pos = s - start;
1064 goto found;
1065 }
1066 }
1067 res = PyBytes_FromStringAndSize(start, n);
1068 if (res == NULL)
1069 goto end;
1070 if (n == limit) {
1071 self->pos = n;
1072 break;
1073 }
1074 if (PyList_Append(chunks, res) < 0) {
1075 Py_CLEAR(res);
1076 goto end;
1077 }
1078 Py_CLEAR(res);
1079 written += n;
1080 if (limit >= 0)
1081 limit -= n;
1082 }
1083found:
1084 if (res != NULL && PyList_Append(chunks, res) < 0) {
1085 Py_CLEAR(res);
1086 goto end;
1087 }
1088 Py_CLEAR(res);
1089 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1090
1091end:
1092 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001093end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001094 Py_XDECREF(chunks);
1095 return res;
1096}
1097
1098static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001099buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001100{
1101 Py_ssize_t limit = -1;
1102
1103 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001104 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001105 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001106 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001107}
1108
1109
1110static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001111buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001112{
1113 Py_off_t pos;
1114
1115 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001116 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001117 if (pos == -1)
1118 return NULL;
1119 pos -= RAW_OFFSET(self);
1120 /* TODO: sanity check (pos >= 0) */
1121 return PyLong_FromOff_t(pos);
1122}
1123
1124static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001125buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001126{
1127 Py_off_t target, n;
1128 int whence = 0;
1129 PyObject *targetobj, *res = NULL;
1130
1131 CHECK_INITIALIZED(self)
1132 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1133 return NULL;
1134 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001135 if (whence < 0 || whence > 2) {
1136 PyErr_Format(PyExc_ValueError,
1137 "whence must be between 0 and 2, not %d", whence);
1138 return NULL;
1139 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001140
1141 CHECK_CLOSED(self, "seek of closed file")
1142
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001143 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1144 if (target == -1 && PyErr_Occurred())
1145 return NULL;
1146
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001147 if (whence != 2 && self->readable) {
1148 Py_off_t current, avail;
1149 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001150 so as to return quickly if possible. Also, we needn't take the
1151 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001152 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001153 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1154 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001155 current = RAW_TELL(self);
1156 avail = READAHEAD(self);
1157 if (avail > 0) {
1158 Py_off_t offset;
1159 if (whence == 0)
1160 offset = target - (current - RAW_OFFSET(self));
1161 else
1162 offset = target;
1163 if (offset >= -self->pos && offset <= avail) {
1164 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001165 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001166 }
1167 }
1168 }
1169
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001170 if (!ENTER_BUFFERED(self))
1171 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001172
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001173 /* Fallback: invoke raw seek() method and clear buffer */
1174 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001175 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001176 if (res == NULL)
1177 goto end;
1178 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001179 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001180 }
1181
1182 /* TODO: align on block boundary and read buffer if needed? */
1183 if (whence == 1)
1184 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001185 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001186 if (n == -1)
1187 goto end;
1188 self->raw_pos = -1;
1189 res = PyLong_FromOff_t(n);
1190 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001191 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001192
1193end:
1194 LEAVE_BUFFERED(self)
1195 return res;
1196}
1197
1198static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001199buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001200{
1201 PyObject *pos = Py_None;
1202 PyObject *res = NULL;
1203
1204 CHECK_INITIALIZED(self)
1205 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1206 return NULL;
1207 }
1208
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001209 if (!ENTER_BUFFERED(self))
1210 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001211
1212 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001213 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001214 if (res == NULL)
1215 goto end;
1216 Py_CLEAR(res);
1217 }
1218 if (self->readable) {
1219 if (pos == Py_None) {
1220 /* Rewind the raw stream so that its position corresponds to
1221 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001222 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001223 goto end;
1224 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001225 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001226 }
1227 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1228 if (res == NULL)
1229 goto end;
1230 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001231 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001232 PyErr_Clear();
1233
1234end:
1235 LEAVE_BUFFERED(self)
1236 return res;
1237}
1238
1239static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001240buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001241{
1242 PyObject *line;
1243 PyTypeObject *tp;
1244
1245 CHECK_INITIALIZED(self);
1246
1247 tp = Py_TYPE(self);
1248 if (tp == &PyBufferedReader_Type ||
1249 tp == &PyBufferedRandom_Type) {
1250 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001251 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001252 }
1253 else {
1254 line = PyObject_CallMethodObjArgs((PyObject *)self,
1255 _PyIO_str_readline, NULL);
1256 if (line && !PyBytes_Check(line)) {
1257 PyErr_Format(PyExc_IOError,
1258 "readline() should have returned a bytes object, "
1259 "not '%.200s'", Py_TYPE(line)->tp_name);
1260 Py_DECREF(line);
1261 return NULL;
1262 }
1263 }
1264
1265 if (line == NULL)
1266 return NULL;
1267
1268 if (PyBytes_GET_SIZE(line) == 0) {
1269 /* Reached EOF or would have blocked */
1270 Py_DECREF(line);
1271 return NULL;
1272 }
1273
1274 return line;
1275}
1276
Antoine Pitrou716c4442009-05-23 19:04:03 +00001277static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001278buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001279{
1280 PyObject *nameobj, *res;
1281
1282 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1283 if (nameobj == NULL) {
1284 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1285 PyErr_Clear();
1286 else
1287 return NULL;
1288 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1289 }
1290 else {
1291 res = PyUnicode_FromFormat("<%s name=%R>",
1292 Py_TYPE(self)->tp_name, nameobj);
1293 Py_DECREF(nameobj);
1294 }
1295 return res;
1296}
1297
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001298/*
1299 * class BufferedReader
1300 */
1301
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001302PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001303 "Create a new buffered reader using the given readable raw IO object.");
1304
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001305static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001306{
1307 self->read_end = -1;
1308}
1309
1310static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001311bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001312{
1313 char *kwlist[] = {"raw", "buffer_size", NULL};
1314 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1315 PyObject *raw;
1316
1317 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001318 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001319
1320 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1321 &raw, &buffer_size)) {
1322 return -1;
1323 }
1324
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001325 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001326 return -1;
1327
1328 Py_CLEAR(self->raw);
1329 Py_INCREF(raw);
1330 self->raw = raw;
1331 self->buffer_size = buffer_size;
1332 self->readable = 1;
1333 self->writable = 0;
1334
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001335 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001336 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001337 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001338
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001339 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1340 Py_TYPE(raw) == &PyFileIO_Type);
1341
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001342 self->ok = 1;
1343 return 0;
1344}
1345
1346static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001347_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001348{
1349 Py_buffer buf;
1350 PyObject *memobj, *res;
1351 Py_ssize_t n;
1352 /* NOTE: the buffer needn't be released as its object is NULL. */
1353 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1354 return -1;
1355 memobj = PyMemoryView_FromBuffer(&buf);
1356 if (memobj == NULL)
1357 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001358 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1359 occurs so we needn't do it ourselves.
1360 We then retry reading, ignoring the signal if no handler has
1361 raised (see issue #10956).
1362 */
1363 do {
1364 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1365 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001366 Py_DECREF(memobj);
1367 if (res == NULL)
1368 return -1;
1369 if (res == Py_None) {
1370 /* Non-blocking stream would have blocked. Special return code! */
1371 Py_DECREF(res);
1372 return -2;
1373 }
1374 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1375 Py_DECREF(res);
1376 if (n < 0 || n > len) {
1377 PyErr_Format(PyExc_IOError,
1378 "raw readinto() returned invalid length %zd "
1379 "(should have been between 0 and %zd)", n, len);
1380 return -1;
1381 }
1382 if (n > 0 && self->abs_pos != -1)
1383 self->abs_pos += n;
1384 return n;
1385}
1386
1387static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001388_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001389{
1390 Py_ssize_t start, len, n;
1391 if (VALID_READ_BUFFER(self))
1392 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1393 else
1394 start = 0;
1395 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001396 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001397 if (n <= 0)
1398 return n;
1399 self->read_end = start + n;
1400 self->raw_pos = start + n;
1401 return n;
1402}
1403
1404static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001405_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001406{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001407 Py_ssize_t current_size;
1408 PyObject *res, *data = NULL;
1409 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001410
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001411 if (chunks == NULL)
1412 return NULL;
1413
1414 /* First copy what we have in the current buffer. */
1415 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1416 if (current_size) {
1417 data = PyBytes_FromStringAndSize(
1418 self->buffer + self->pos, current_size);
1419 if (data == NULL) {
1420 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001421 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001422 }
1423 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001424 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001425 /* We're going past the buffer's bounds, flush it */
1426 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001427 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001428 if (res == NULL) {
1429 Py_DECREF(chunks);
1430 return NULL;
1431 }
1432 Py_CLEAR(res);
1433 }
1434 while (1) {
1435 if (data) {
1436 if (PyList_Append(chunks, data) < 0) {
1437 Py_DECREF(data);
1438 Py_DECREF(chunks);
1439 return NULL;
1440 }
1441 Py_DECREF(data);
1442 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001443
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001444 /* Read until EOF or until read() would block. */
1445 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1446 if (data == NULL) {
1447 Py_DECREF(chunks);
1448 return NULL;
1449 }
1450 if (data != Py_None && !PyBytes_Check(data)) {
1451 Py_DECREF(data);
1452 Py_DECREF(chunks);
1453 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1454 return NULL;
1455 }
1456 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1457 if (current_size == 0) {
1458 Py_DECREF(chunks);
1459 return data;
1460 }
1461 else {
1462 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1463 Py_DECREF(data);
1464 Py_DECREF(chunks);
1465 return res;
1466 }
1467 }
1468 current_size += PyBytes_GET_SIZE(data);
1469 if (self->abs_pos != -1)
1470 self->abs_pos += PyBytes_GET_SIZE(data);
1471 }
1472}
1473
1474/* Read n bytes from the buffer if it can, otherwise return None.
1475 This function is simple enough that it can run unlocked. */
1476static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001477_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001478{
1479 Py_ssize_t current_size;
1480
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001481 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1482 if (n <= current_size) {
1483 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001484 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1485 if (res != NULL)
1486 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001487 return res;
1488 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001489 Py_RETURN_NONE;
1490}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001491
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001492/* Generic read function: read from the stream until enough bytes are read,
1493 * or until an EOF occurs or until read() would block.
1494 */
1495static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001496_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001497{
1498 PyObject *res = NULL;
1499 Py_ssize_t current_size, remaining, written;
1500 char *out;
1501
1502 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1503 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001504 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001505
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001506 res = PyBytes_FromStringAndSize(NULL, n);
1507 if (res == NULL)
1508 goto error;
1509 out = PyBytes_AS_STRING(res);
1510 remaining = n;
1511 written = 0;
1512 if (current_size > 0) {
1513 memcpy(out, self->buffer + self->pos, current_size);
1514 remaining -= current_size;
1515 written += current_size;
1516 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001517 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001518 while (remaining > 0) {
1519 /* We want to read a whole block at the end into buffer.
1520 If we had readv() we could do this in one pass. */
1521 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1522 if (r == 0)
1523 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001524 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001525 if (r == -1)
1526 goto error;
1527 if (r == 0 || r == -2) {
1528 /* EOF occurred or read() would block. */
1529 if (r == 0 || written > 0) {
1530 if (_PyBytes_Resize(&res, written))
1531 goto error;
1532 return res;
1533 }
1534 Py_DECREF(res);
1535 Py_INCREF(Py_None);
1536 return Py_None;
1537 }
1538 remaining -= r;
1539 written += r;
1540 }
1541 assert(remaining <= self->buffer_size);
1542 self->pos = 0;
1543 self->raw_pos = 0;
1544 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001545 /* NOTE: when the read is satisfied, we avoid issuing any additional
1546 reads, which could block indefinitely (e.g. on a socket).
1547 See issue #9550. */
1548 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001549 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001550 if (r == -1)
1551 goto error;
1552 if (r == 0 || r == -2) {
1553 /* EOF occurred or read() would block. */
1554 if (r == 0 || written > 0) {
1555 if (_PyBytes_Resize(&res, written))
1556 goto error;
1557 return res;
1558 }
1559 Py_DECREF(res);
1560 Py_INCREF(Py_None);
1561 return Py_None;
1562 }
1563 if (remaining > r) {
1564 memcpy(out + written, self->buffer + self->pos, r);
1565 written += r;
1566 self->pos += r;
1567 remaining -= r;
1568 }
1569 else if (remaining > 0) {
1570 memcpy(out + written, self->buffer + self->pos, remaining);
1571 written += remaining;
1572 self->pos += remaining;
1573 remaining = 0;
1574 }
1575 if (remaining == 0)
1576 break;
1577 }
1578
1579 return res;
1580
1581error:
1582 Py_XDECREF(res);
1583 return NULL;
1584}
1585
1586static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001587_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001588{
1589 Py_ssize_t have, r;
1590
1591 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1592 /* Constraints:
1593 1. we don't want to advance the file position.
1594 2. we don't want to lose block alignment, so we can't shift the buffer
1595 to make some place.
1596 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1597 */
1598 if (have > 0) {
1599 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1600 }
1601
1602 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001603 _bufferedreader_reset_buf(self);
1604 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001605 if (r == -1)
1606 return NULL;
1607 if (r == -2)
1608 r = 0;
1609 self->pos = 0;
1610 return PyBytes_FromStringAndSize(self->buffer, r);
1611}
1612
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001613static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001614 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001615 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1616 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1617 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1618 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1619 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1620 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1621 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1622 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001623 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001624 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001625
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001626 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1627 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1628 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001629 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001630 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1631 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1632 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1633 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001634 {NULL, NULL}
1635};
1636
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001637static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001638 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001639 {NULL}
1640};
1641
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001642static PyGetSetDef bufferedreader_getset[] = {
1643 {"closed", (getter)buffered_closed_get, NULL, NULL},
1644 {"name", (getter)buffered_name_get, NULL, NULL},
1645 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001646 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001647};
1648
1649
1650PyTypeObject PyBufferedReader_Type = {
1651 PyVarObject_HEAD_INIT(NULL, 0)
1652 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001653 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001654 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001655 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001656 0, /*tp_print*/
1657 0, /*tp_getattr*/
1658 0, /*tp_setattr*/
1659 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001660 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001661 0, /*tp_as_number*/
1662 0, /*tp_as_sequence*/
1663 0, /*tp_as_mapping*/
1664 0, /*tp_hash */
1665 0, /*tp_call*/
1666 0, /*tp_str*/
1667 0, /*tp_getattro*/
1668 0, /*tp_setattro*/
1669 0, /*tp_as_buffer*/
1670 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1671 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001672 bufferedreader_doc, /* tp_doc */
1673 (traverseproc)buffered_traverse, /* tp_traverse */
1674 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001675 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001676 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001677 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001678 (iternextfunc)buffered_iternext, /* tp_iternext */
1679 bufferedreader_methods, /* tp_methods */
1680 bufferedreader_members, /* tp_members */
1681 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001682 0, /* tp_base */
1683 0, /* tp_dict */
1684 0, /* tp_descr_get */
1685 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001686 offsetof(buffered, dict), /* tp_dictoffset */
1687 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001688 0, /* tp_alloc */
1689 PyType_GenericNew, /* tp_new */
1690};
1691
1692
Benjamin Peterson59406a92009-03-26 17:10:29 +00001693
1694static int
1695complain_about_max_buffer_size(void)
1696{
1697 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1698 "max_buffer_size is deprecated", 1) < 0)
1699 return 0;
1700 return 1;
1701}
1702
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001703/*
1704 * class BufferedWriter
1705 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001706PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001707 "A buffer for a writeable sequential RawIO object.\n"
1708 "\n"
1709 "The constructor creates a BufferedWriter for the given writeable raw\n"
1710 "stream. If the buffer_size is not given, it defaults to\n"
1711 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1712 );
1713
1714static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001715_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001716{
1717 self->write_pos = 0;
1718 self->write_end = -1;
1719}
1720
1721static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001722bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001723{
1724 /* TODO: properly deprecate max_buffer_size */
1725 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1726 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001727 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001728 PyObject *raw;
1729
1730 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001731 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001732
1733 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1734 &raw, &buffer_size, &max_buffer_size)) {
1735 return -1;
1736 }
1737
Benjamin Peterson59406a92009-03-26 17:10:29 +00001738 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1739 return -1;
1740
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001741 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001742 return -1;
1743
1744 Py_CLEAR(self->raw);
1745 Py_INCREF(raw);
1746 self->raw = raw;
1747 self->readable = 0;
1748 self->writable = 1;
1749
1750 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001751 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001752 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001753 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001754 self->pos = 0;
1755
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001756 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1757 Py_TYPE(raw) == &PyFileIO_Type);
1758
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001759 self->ok = 1;
1760 return 0;
1761}
1762
1763static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001764_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001765{
1766 Py_buffer buf;
1767 PyObject *memobj, *res;
1768 Py_ssize_t n;
1769 /* NOTE: the buffer needn't be released as its object is NULL. */
1770 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1771 return -1;
1772 memobj = PyMemoryView_FromBuffer(&buf);
1773 if (memobj == NULL)
1774 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001775 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1776 occurs so we needn't do it ourselves.
1777 We then retry writing, ignoring the signal if no handler has
1778 raised (see issue #10956).
1779 */
1780 do {
1781 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1782 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001783 Py_DECREF(memobj);
1784 if (res == NULL)
1785 return -1;
1786 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1787 Py_DECREF(res);
1788 if (n < 0 || n > len) {
1789 PyErr_Format(PyExc_IOError,
1790 "raw write() returned invalid length %zd "
1791 "(should have been between 0 and %zd)", n, len);
1792 return -1;
1793 }
1794 if (n > 0 && self->abs_pos != -1)
1795 self->abs_pos += n;
1796 return n;
1797}
1798
1799/* `restore_pos` is 1 if we need to restore the raw stream position at
1800 the end, 0 otherwise. */
1801static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001802_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001803{
1804 Py_ssize_t written = 0;
1805 Py_off_t n, rewind;
1806
1807 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1808 goto end;
1809 /* First, rewind */
1810 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1811 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001812 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001813 if (n < 0) {
1814 goto error;
1815 }
1816 self->raw_pos -= rewind;
1817 }
1818 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001819 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001820 self->buffer + self->write_pos,
1821 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1822 Py_off_t, Py_ssize_t));
1823 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001824 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001825 if (w == NULL)
1826 goto error;
1827 self->write_pos += *w;
1828 self->raw_pos = self->write_pos;
1829 written += *w;
1830 *w = written;
1831 /* Already re-raised */
1832 goto error;
1833 }
1834 self->write_pos += n;
1835 self->raw_pos = self->write_pos;
1836 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001837 /* Partial writes can return successfully when interrupted by a
1838 signal (see write(2)). We must run signal handlers before
1839 blocking another time, possibly indefinitely. */
1840 if (PyErr_CheckSignals() < 0)
1841 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001842 }
1843
1844 if (restore_pos) {
1845 Py_off_t forward = rewind - written;
1846 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001847 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001848 if (n < 0) {
1849 goto error;
1850 }
1851 self->raw_pos += forward;
1852 }
1853 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001854 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001855
1856end:
1857 Py_RETURN_NONE;
1858
1859error:
1860 return NULL;
1861}
1862
1863static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001864bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001865{
1866 PyObject *res = NULL;
1867 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001868 Py_ssize_t written, avail, remaining;
1869 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001870
1871 CHECK_INITIALIZED(self)
1872 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1873 return NULL;
1874 }
1875
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001876 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001877 PyErr_SetString(PyExc_ValueError, "write to closed file");
1878 PyBuffer_Release(&buf);
1879 return NULL;
1880 }
1881
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001882 if (!ENTER_BUFFERED(self)) {
1883 PyBuffer_Release(&buf);
1884 return NULL;
1885 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001886
1887 /* Fast path: the data to write can be fully buffered. */
1888 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1889 self->pos = 0;
1890 self->raw_pos = 0;
1891 }
1892 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1893 if (buf.len <= avail) {
1894 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1895 if (!VALID_WRITE_BUFFER(self)) {
1896 self->write_pos = self->pos;
1897 }
1898 ADJUST_POSITION(self, self->pos + buf.len);
1899 if (self->pos > self->write_end)
1900 self->write_end = self->pos;
1901 written = buf.len;
1902 goto end;
1903 }
1904
1905 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001906 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001907 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001908 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001909 if (w == NULL)
1910 goto error;
1911 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001912 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001913 /* Make some place by shifting the buffer. */
1914 assert(VALID_WRITE_BUFFER(self));
1915 memmove(self->buffer, self->buffer + self->write_pos,
1916 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1917 Py_off_t, Py_ssize_t));
1918 self->write_end -= self->write_pos;
1919 self->raw_pos -= self->write_pos;
1920 self->pos -= self->write_pos;
1921 self->write_pos = 0;
1922 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1923 Py_off_t, Py_ssize_t);
1924 if (buf.len <= avail) {
1925 /* Everything can be buffered */
1926 PyErr_Clear();
1927 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1928 self->write_end += buf.len;
1929 written = buf.len;
1930 goto end;
1931 }
1932 /* Buffer as much as possible. */
1933 memcpy(self->buffer + self->write_end, buf.buf, avail);
1934 self->write_end += avail;
1935 /* Already re-raised */
1936 *w = avail;
1937 goto error;
1938 }
1939 Py_CLEAR(res);
1940
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001941 /* Adjust the raw stream position if it is away from the logical stream
1942 position. This happens if the read buffer has been filled but not
1943 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1944 the raw stream by itself).
1945 Fixes issue #6629.
1946 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001947 offset = RAW_OFFSET(self);
1948 if (offset != 0) {
1949 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001950 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001951 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001952 }
1953
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001954 /* Then write buf itself. At this point the buffer has been emptied. */
1955 remaining = buf.len;
1956 written = 0;
1957 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001958 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001959 self, (char *) buf.buf + written, buf.len - written);
1960 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001961 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001962 if (w == NULL)
1963 goto error;
1964 written += *w;
1965 remaining -= *w;
1966 if (remaining > self->buffer_size) {
1967 /* Can't buffer everything, still buffer as much as possible */
1968 memcpy(self->buffer,
1969 (char *) buf.buf + written, self->buffer_size);
1970 self->raw_pos = 0;
1971 ADJUST_POSITION(self, self->buffer_size);
1972 self->write_end = self->buffer_size;
1973 *w = written + self->buffer_size;
1974 /* Already re-raised */
1975 goto error;
1976 }
1977 PyErr_Clear();
1978 break;
1979 }
1980 written += n;
1981 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001982 /* Partial writes can return successfully when interrupted by a
1983 signal (see write(2)). We must run signal handlers before
1984 blocking another time, possibly indefinitely. */
1985 if (PyErr_CheckSignals() < 0)
1986 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001987 }
1988 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001989 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001990 if (remaining > 0) {
1991 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1992 written += remaining;
1993 }
1994 self->write_pos = 0;
1995 /* TODO: sanity check (remaining >= 0) */
1996 self->write_end = remaining;
1997 ADJUST_POSITION(self, remaining);
1998 self->raw_pos = 0;
1999
2000end:
2001 res = PyLong_FromSsize_t(written);
2002
2003error:
2004 LEAVE_BUFFERED(self)
2005 PyBuffer_Release(&buf);
2006 return res;
2007}
2008
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002009static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002010 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002011 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2012 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2013 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2014 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2015 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2016 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2017 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002018 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002019 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002020
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002021 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2022 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2023 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2024 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2025 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002026 {NULL, NULL}
2027};
2028
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002029static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002030 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002031 {NULL}
2032};
2033
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002034static PyGetSetDef bufferedwriter_getset[] = {
2035 {"closed", (getter)buffered_closed_get, NULL, NULL},
2036 {"name", (getter)buffered_name_get, NULL, NULL},
2037 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002038 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002039};
2040
2041
2042PyTypeObject PyBufferedWriter_Type = {
2043 PyVarObject_HEAD_INIT(NULL, 0)
2044 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002045 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002046 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002047 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002048 0, /*tp_print*/
2049 0, /*tp_getattr*/
2050 0, /*tp_setattr*/
2051 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002052 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002053 0, /*tp_as_number*/
2054 0, /*tp_as_sequence*/
2055 0, /*tp_as_mapping*/
2056 0, /*tp_hash */
2057 0, /*tp_call*/
2058 0, /*tp_str*/
2059 0, /*tp_getattro*/
2060 0, /*tp_setattro*/
2061 0, /*tp_as_buffer*/
2062 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2063 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002064 bufferedwriter_doc, /* tp_doc */
2065 (traverseproc)buffered_traverse, /* tp_traverse */
2066 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002067 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002068 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002069 0, /* tp_iter */
2070 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002071 bufferedwriter_methods, /* tp_methods */
2072 bufferedwriter_members, /* tp_members */
2073 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002074 0, /* tp_base */
2075 0, /* tp_dict */
2076 0, /* tp_descr_get */
2077 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002078 offsetof(buffered, dict), /* tp_dictoffset */
2079 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002080 0, /* tp_alloc */
2081 PyType_GenericNew, /* tp_new */
2082};
2083
2084
2085
2086/*
2087 * BufferedRWPair
2088 */
2089
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002090PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002091 "A buffered reader and writer object together.\n"
2092 "\n"
2093 "A buffered reader object and buffered writer object put together to\n"
2094 "form a sequential IO object that can read and write. This is typically\n"
2095 "used with a socket or two-way pipe.\n"
2096 "\n"
2097 "reader and writer are RawIOBase objects that are readable and\n"
2098 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002099 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002100 );
2101
2102/* XXX The usefulness of this (compared to having two separate IO objects) is
2103 * questionable.
2104 */
2105
2106typedef struct {
2107 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002108 buffered *reader;
2109 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002110 PyObject *dict;
2111 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002112} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002113
2114static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002115bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002116{
2117 PyObject *reader, *writer;
2118 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002119 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002120
2121 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2122 &buffer_size, &max_buffer_size)) {
2123 return -1;
2124 }
2125
Benjamin Peterson59406a92009-03-26 17:10:29 +00002126 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2127 return -1;
2128
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002129 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002130 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002131 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002132 return -1;
2133
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002134 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002135 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002136 if (self->reader == NULL)
2137 return -1;
2138
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002139 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002140 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002141 if (self->writer == NULL) {
2142 Py_CLEAR(self->reader);
2143 return -1;
2144 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002145
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002146 return 0;
2147}
2148
2149static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002150bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002151{
2152 Py_VISIT(self->dict);
2153 return 0;
2154}
2155
2156static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002157bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002158{
2159 Py_CLEAR(self->reader);
2160 Py_CLEAR(self->writer);
2161 Py_CLEAR(self->dict);
2162 return 0;
2163}
2164
2165static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002166bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002167{
2168 _PyObject_GC_UNTRACK(self);
2169 Py_CLEAR(self->reader);
2170 Py_CLEAR(self->writer);
2171 Py_CLEAR(self->dict);
2172 Py_TYPE(self)->tp_free((PyObject *) self);
2173}
2174
2175static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002176_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002177{
2178 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2179 PyObject *ret;
2180
2181 if (func == NULL) {
2182 PyErr_SetString(PyExc_AttributeError, name);
2183 return NULL;
2184 }
2185
2186 ret = PyObject_CallObject(func, args);
2187 Py_DECREF(func);
2188 return ret;
2189}
2190
2191static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002192bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002193{
2194 return _forward_call(self->reader, "read", args);
2195}
2196
2197static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002198bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002199{
2200 return _forward_call(self->reader, "peek", args);
2201}
2202
2203static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002204bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002205{
2206 return _forward_call(self->reader, "read1", args);
2207}
2208
2209static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002210bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002211{
2212 return _forward_call(self->reader, "readinto", args);
2213}
2214
2215static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002216bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002217{
2218 return _forward_call(self->writer, "write", args);
2219}
2220
2221static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002222bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002223{
2224 return _forward_call(self->writer, "flush", args);
2225}
2226
2227static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002228bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002229{
2230 return _forward_call(self->reader, "readable", args);
2231}
2232
2233static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002234bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002235{
2236 return _forward_call(self->writer, "writable", args);
2237}
2238
2239static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002240bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002241{
2242 PyObject *ret = _forward_call(self->writer, "close", args);
2243 if (ret == NULL)
2244 return NULL;
2245 Py_DECREF(ret);
2246
2247 return _forward_call(self->reader, "close", args);
2248}
2249
2250static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002251bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002252{
2253 PyObject *ret = _forward_call(self->writer, "isatty", args);
2254
2255 if (ret != Py_False) {
2256 /* either True or exception */
2257 return ret;
2258 }
2259 Py_DECREF(ret);
2260
2261 return _forward_call(self->reader, "isatty", args);
2262}
2263
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002264static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002265bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002266{
2267 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2268}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002269
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002270static PyMethodDef bufferedrwpair_methods[] = {
2271 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2272 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2273 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2274 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002275
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002276 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2277 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002278
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002279 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2280 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002281
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002282 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2283 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002284
Antoine Pitrou243757e2010-11-05 21:15:39 +00002285 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2286
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002287 {NULL, NULL}
2288};
2289
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002290static PyGetSetDef bufferedrwpair_getset[] = {
2291 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002292 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002293};
2294
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002295PyTypeObject PyBufferedRWPair_Type = {
2296 PyVarObject_HEAD_INIT(NULL, 0)
2297 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002298 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002299 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002300 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002301 0, /*tp_print*/
2302 0, /*tp_getattr*/
2303 0, /*tp_setattr*/
2304 0, /*tp_compare */
2305 0, /*tp_repr*/
2306 0, /*tp_as_number*/
2307 0, /*tp_as_sequence*/
2308 0, /*tp_as_mapping*/
2309 0, /*tp_hash */
2310 0, /*tp_call*/
2311 0, /*tp_str*/
2312 0, /*tp_getattro*/
2313 0, /*tp_setattro*/
2314 0, /*tp_as_buffer*/
2315 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2316 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002317 bufferedrwpair_doc, /* tp_doc */
2318 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2319 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002320 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002321 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002322 0, /* tp_iter */
2323 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002324 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002325 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002326 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002327 0, /* tp_base */
2328 0, /* tp_dict */
2329 0, /* tp_descr_get */
2330 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002331 offsetof(rwpair, dict), /* tp_dictoffset */
2332 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002333 0, /* tp_alloc */
2334 PyType_GenericNew, /* tp_new */
2335};
2336
2337
2338
2339/*
2340 * BufferedRandom
2341 */
2342
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002343PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002344 "A buffered interface to random access streams.\n"
2345 "\n"
2346 "The constructor creates a reader and writer for a seekable stream,\n"
2347 "raw, given in the first argument. If the buffer_size is omitted it\n"
2348 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2349 );
2350
2351static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002352bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002353{
2354 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2355 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002356 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002357 PyObject *raw;
2358
2359 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002360 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002361
2362 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2363 &raw, &buffer_size, &max_buffer_size)) {
2364 return -1;
2365 }
2366
Benjamin Peterson59406a92009-03-26 17:10:29 +00002367 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2368 return -1;
2369
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002370 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002371 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002372 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002373 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002374 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002375 return -1;
2376
2377 Py_CLEAR(self->raw);
2378 Py_INCREF(raw);
2379 self->raw = raw;
2380 self->buffer_size = buffer_size;
2381 self->readable = 1;
2382 self->writable = 1;
2383
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002384 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002385 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002386 _bufferedreader_reset_buf(self);
2387 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002388 self->pos = 0;
2389
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002390 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2391 Py_TYPE(raw) == &PyFileIO_Type);
2392
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002393 self->ok = 1;
2394 return 0;
2395}
2396
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002397static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002398 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002399 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2400 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2401 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2402 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2403 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2404 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2405 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002406 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002407 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002408
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002409 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002410
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002411 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2412 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2413 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2414 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2415 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2416 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2417 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2418 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2419 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002420 {NULL, NULL}
2421};
2422
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002423static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002424 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002425 {NULL}
2426};
2427
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002428static PyGetSetDef bufferedrandom_getset[] = {
2429 {"closed", (getter)buffered_closed_get, NULL, NULL},
2430 {"name", (getter)buffered_name_get, NULL, NULL},
2431 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002432 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002433};
2434
2435
2436PyTypeObject PyBufferedRandom_Type = {
2437 PyVarObject_HEAD_INIT(NULL, 0)
2438 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002439 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002440 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002441 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002442 0, /*tp_print*/
2443 0, /*tp_getattr*/
2444 0, /*tp_setattr*/
2445 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002446 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002447 0, /*tp_as_number*/
2448 0, /*tp_as_sequence*/
2449 0, /*tp_as_mapping*/
2450 0, /*tp_hash */
2451 0, /*tp_call*/
2452 0, /*tp_str*/
2453 0, /*tp_getattro*/
2454 0, /*tp_setattro*/
2455 0, /*tp_as_buffer*/
2456 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2457 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002458 bufferedrandom_doc, /* tp_doc */
2459 (traverseproc)buffered_traverse, /* tp_traverse */
2460 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002461 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002462 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002463 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002464 (iternextfunc)buffered_iternext, /* tp_iternext */
2465 bufferedrandom_methods, /* tp_methods */
2466 bufferedrandom_members, /* tp_members */
2467 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002468 0, /* tp_base */
2469 0, /*tp_dict*/
2470 0, /* tp_descr_get */
2471 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002472 offsetof(buffered, dict), /*tp_dictoffset*/
2473 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002474 0, /* tp_alloc */
2475 PyType_GenericNew, /* tp_new */
2476};