blob: 86f7412c26e56604b04311cbeae0ce0c43d05a35 [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 *
Victor Stinnerbc93a112011-06-01 00:01:24 +0200592_bufferedreader_peek_unlocked(buffered *self);
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 *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200756buffered_flush_and_rewind_unlocked(buffered *self)
757{
758 PyObject *res;
759
760 res = _bufferedwriter_flush_unlocked(self, 0);
761 if (res == NULL)
762 return NULL;
763 Py_DECREF(res);
764
765 if (self->readable) {
766 /* Rewind the raw stream so that its position corresponds to
767 the current logical position. */
768 Py_off_t n;
769 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
770 _bufferedreader_reset_buf(self);
771 if (n == -1)
772 return NULL;
773 }
774 Py_RETURN_NONE;
775}
776
777static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000778buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000779{
780 PyObject *res;
781
782 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000783 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000784
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000785 if (!ENTER_BUFFERED(self))
786 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200787 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000788 LEAVE_BUFFERED(self)
789
790 return res;
791}
792
793static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000794buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000795{
796 Py_ssize_t n = 0;
797 PyObject *res = NULL;
798
799 CHECK_INITIALIZED(self)
800 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
801 return NULL;
802 }
803
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000804 if (!ENTER_BUFFERED(self))
805 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000806
807 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200808 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000809 if (res == NULL)
810 goto end;
811 Py_CLEAR(res);
812 }
Victor Stinnerbc93a112011-06-01 00:01:24 +0200813 res = _bufferedreader_peek_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000814
815end:
816 LEAVE_BUFFERED(self)
817 return res;
818}
819
820static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000821buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000822{
823 Py_ssize_t n = -1;
824 PyObject *res;
825
826 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000827 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000828 return NULL;
829 }
830 if (n < -1) {
831 PyErr_SetString(PyExc_ValueError,
832 "read length must be positive or -1");
833 return NULL;
834 }
835
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000836 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000837
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000838 if (n == -1) {
839 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000840 if (!ENTER_BUFFERED(self))
841 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000842 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000843 }
844 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000845 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200846 if (res != Py_None)
847 return res;
848 Py_DECREF(res);
849 if (!ENTER_BUFFERED(self))
850 return NULL;
851 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000852 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000853
Antoine Pitroue05565e2011-08-20 14:39:23 +0200854 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000855 return res;
856}
857
858static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000859buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000860{
861 Py_ssize_t n, have, r;
862 PyObject *res = NULL;
863
864 CHECK_INITIALIZED(self)
865 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
866 return NULL;
867 }
868
869 if (n < 0) {
870 PyErr_SetString(PyExc_ValueError,
871 "read length must be positive");
872 return NULL;
873 }
874 if (n == 0)
875 return PyBytes_FromStringAndSize(NULL, 0);
876
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000877 if (!ENTER_BUFFERED(self))
878 return NULL;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200879
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000880 /* Return up to n bytes. If at least one byte is buffered, we
881 only return buffered bytes. Otherwise, we do one raw read. */
882
883 /* XXX: this mimicks the io.py implementation but is probably wrong.
884 If we need to read from the raw stream, then we could actually read
885 all `n` bytes asked by the caller (and possibly more, so as to fill
886 our buffer for the next reads). */
887
888 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
889 if (have > 0) {
890 if (n > have)
891 n = have;
892 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
893 if (res == NULL)
894 goto end;
895 self->pos += n;
896 goto end;
897 }
898
Antoine Pitroue05565e2011-08-20 14:39:23 +0200899 if (self->writable) {
900 res = buffered_flush_and_rewind_unlocked(self);
901 if (res == NULL)
902 goto end;
903 Py_DECREF(res);
904 }
905
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000906 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000907 _bufferedreader_reset_buf(self);
908 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000909 if (r == -1)
910 goto end;
911 if (r == -2)
912 r = 0;
913 if (n > r)
914 n = r;
915 res = PyBytes_FromStringAndSize(self->buffer, n);
916 if (res == NULL)
917 goto end;
918 self->pos = n;
919
920end:
921 LEAVE_BUFFERED(self)
922 return res;
923}
924
925static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000926buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000927{
Antoine Pitrou3486a982011-05-12 01:57:53 +0200928 Py_buffer buf;
929 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000930 PyObject *res = NULL;
931
932 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +0200933
934 if (!PyArg_ParseTuple(args, "w*:readinto", &buf))
935 return NULL;
936
937 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
938 if (n > 0) {
939 if (n >= buf.len) {
940 memcpy(buf.buf, self->buffer + self->pos, buf.len);
941 self->pos += buf.len;
942 res = PyLong_FromSsize_t(buf.len);
943 goto end_unlocked;
944 }
945 memcpy(buf.buf, self->buffer + self->pos, n);
946 self->pos += n;
947 written = n;
948 }
949
950 if (!ENTER_BUFFERED(self))
951 goto end_unlocked;
952
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000953 if (self->writable) {
Antoine Pitroue8bb1a02011-08-20 14:52:04 +0200954 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000955 if (res == NULL)
956 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200957 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000958 }
Antoine Pitrou3486a982011-05-12 01:57:53 +0200959
960 _bufferedreader_reset_buf(self);
961 self->pos = 0;
962
963 for (remaining = buf.len - written;
964 remaining > 0;
965 written += n, remaining -= n) {
966 /* If remaining bytes is larger than internal buffer size, copy
967 * directly into caller's buffer. */
968 if (remaining > self->buffer_size) {
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200969 n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
970 remaining);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200971 }
972 else {
973 n = _bufferedreader_fill_buffer(self);
974 if (n > 0) {
975 if (n > remaining)
976 n = remaining;
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200977 memcpy((char *) buf.buf + written,
978 self->buffer + self->pos, n);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200979 self->pos += n;
980 continue; /* short circuit */
981 }
982 }
983 if (n == 0 || (n == -2 && written > 0))
984 break;
985 if (n < 0) {
986 if (n == -2) {
987 Py_INCREF(Py_None);
988 res = Py_None;
989 }
990 goto end;
991 }
992 }
993 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000994
995end:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200996 LEAVE_BUFFERED(self);
997end_unlocked:
998 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000999 return res;
1000}
1001
1002static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001003_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001004{
1005 PyObject *res = NULL;
1006 PyObject *chunks = NULL;
1007 Py_ssize_t n, written = 0;
1008 const char *start, *s, *end;
1009
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001010 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001011
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001012 /* First, try to find a line in the buffer. This can run unlocked because
1013 the calls to the C API are simple enough that they can't trigger
1014 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001015 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1016 if (limit >= 0 && n > limit)
1017 n = limit;
1018 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001019 s = memchr(start, '\n', n);
1020 if (s != NULL) {
1021 res = PyBytes_FromStringAndSize(start, s - start + 1);
1022 if (res != NULL)
1023 self->pos += s - start + 1;
1024 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001025 }
1026 if (n == limit) {
1027 res = PyBytes_FromStringAndSize(start, n);
1028 if (res != NULL)
1029 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001030 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001031 }
1032
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001033 if (!ENTER_BUFFERED(self))
1034 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001035
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001036 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001037 chunks = PyList_New(0);
1038 if (chunks == NULL)
1039 goto end;
1040 if (n > 0) {
1041 res = PyBytes_FromStringAndSize(start, n);
1042 if (res == NULL)
1043 goto end;
1044 if (PyList_Append(chunks, res) < 0) {
1045 Py_CLEAR(res);
1046 goto end;
1047 }
1048 Py_CLEAR(res);
1049 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001050 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001051 if (limit >= 0)
1052 limit -= n;
1053 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001054 if (self->writable) {
1055 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1056 if (r == NULL)
1057 goto end;
1058 Py_DECREF(r);
1059 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001060
1061 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001062 _bufferedreader_reset_buf(self);
1063 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001064 if (n == -1)
1065 goto end;
1066 if (n <= 0)
1067 break;
1068 if (limit >= 0 && n > limit)
1069 n = limit;
1070 start = self->buffer;
1071 end = start + n;
1072 s = start;
1073 while (s < end) {
1074 if (*s++ == '\n') {
1075 res = PyBytes_FromStringAndSize(start, s - start);
1076 if (res == NULL)
1077 goto end;
1078 self->pos = s - start;
1079 goto found;
1080 }
1081 }
1082 res = PyBytes_FromStringAndSize(start, n);
1083 if (res == NULL)
1084 goto end;
1085 if (n == limit) {
1086 self->pos = n;
1087 break;
1088 }
1089 if (PyList_Append(chunks, res) < 0) {
1090 Py_CLEAR(res);
1091 goto end;
1092 }
1093 Py_CLEAR(res);
1094 written += n;
1095 if (limit >= 0)
1096 limit -= n;
1097 }
1098found:
1099 if (res != NULL && PyList_Append(chunks, res) < 0) {
1100 Py_CLEAR(res);
1101 goto end;
1102 }
1103 Py_CLEAR(res);
1104 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1105
1106end:
1107 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001108end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001109 Py_XDECREF(chunks);
1110 return res;
1111}
1112
1113static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001114buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001115{
1116 Py_ssize_t limit = -1;
1117
1118 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001119 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001120 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001121 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001122}
1123
1124
1125static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001126buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001127{
1128 Py_off_t pos;
1129
1130 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001131 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001132 if (pos == -1)
1133 return NULL;
1134 pos -= RAW_OFFSET(self);
1135 /* TODO: sanity check (pos >= 0) */
1136 return PyLong_FromOff_t(pos);
1137}
1138
1139static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001140buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001141{
1142 Py_off_t target, n;
1143 int whence = 0;
1144 PyObject *targetobj, *res = NULL;
1145
1146 CHECK_INITIALIZED(self)
1147 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1148 return NULL;
1149 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001150 if (whence < 0 || whence > 2) {
1151 PyErr_Format(PyExc_ValueError,
1152 "whence must be between 0 and 2, not %d", whence);
1153 return NULL;
1154 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001155
1156 CHECK_CLOSED(self, "seek of closed file")
1157
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001158 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1159 return NULL;
1160
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001161 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1162 if (target == -1 && PyErr_Occurred())
1163 return NULL;
1164
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001165 if (whence != 2 && self->readable) {
1166 Py_off_t current, avail;
1167 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001168 so as to return quickly if possible. Also, we needn't take the
1169 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001170 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001171 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1172 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001173 current = RAW_TELL(self);
1174 avail = READAHEAD(self);
1175 if (avail > 0) {
1176 Py_off_t offset;
1177 if (whence == 0)
1178 offset = target - (current - RAW_OFFSET(self));
1179 else
1180 offset = target;
1181 if (offset >= -self->pos && offset <= avail) {
1182 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001183 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001184 }
1185 }
1186 }
1187
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001188 if (!ENTER_BUFFERED(self))
1189 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001190
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001191 /* Fallback: invoke raw seek() method and clear buffer */
1192 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001193 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001194 if (res == NULL)
1195 goto end;
1196 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001197 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001198 }
1199
1200 /* TODO: align on block boundary and read buffer if needed? */
1201 if (whence == 1)
1202 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001203 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001204 if (n == -1)
1205 goto end;
1206 self->raw_pos = -1;
1207 res = PyLong_FromOff_t(n);
1208 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001209 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001210
1211end:
1212 LEAVE_BUFFERED(self)
1213 return res;
1214}
1215
1216static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001217buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001218{
1219 PyObject *pos = Py_None;
1220 PyObject *res = NULL;
1221
1222 CHECK_INITIALIZED(self)
1223 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1224 return NULL;
1225 }
1226
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001227 if (!ENTER_BUFFERED(self))
1228 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001229
1230 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001231 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001232 if (res == NULL)
1233 goto end;
1234 Py_CLEAR(res);
1235 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001236 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1237 if (res == NULL)
1238 goto end;
1239 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001240 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001241 PyErr_Clear();
1242
1243end:
1244 LEAVE_BUFFERED(self)
1245 return res;
1246}
1247
1248static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001249buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001250{
1251 PyObject *line;
1252 PyTypeObject *tp;
1253
1254 CHECK_INITIALIZED(self);
1255
1256 tp = Py_TYPE(self);
1257 if (tp == &PyBufferedReader_Type ||
1258 tp == &PyBufferedRandom_Type) {
1259 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001260 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001261 }
1262 else {
1263 line = PyObject_CallMethodObjArgs((PyObject *)self,
1264 _PyIO_str_readline, NULL);
1265 if (line && !PyBytes_Check(line)) {
1266 PyErr_Format(PyExc_IOError,
1267 "readline() should have returned a bytes object, "
1268 "not '%.200s'", Py_TYPE(line)->tp_name);
1269 Py_DECREF(line);
1270 return NULL;
1271 }
1272 }
1273
1274 if (line == NULL)
1275 return NULL;
1276
1277 if (PyBytes_GET_SIZE(line) == 0) {
1278 /* Reached EOF or would have blocked */
1279 Py_DECREF(line);
1280 return NULL;
1281 }
1282
1283 return line;
1284}
1285
Antoine Pitrou716c4442009-05-23 19:04:03 +00001286static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001287buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001288{
1289 PyObject *nameobj, *res;
1290
1291 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1292 if (nameobj == NULL) {
1293 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1294 PyErr_Clear();
1295 else
1296 return NULL;
1297 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1298 }
1299 else {
1300 res = PyUnicode_FromFormat("<%s name=%R>",
1301 Py_TYPE(self)->tp_name, nameobj);
1302 Py_DECREF(nameobj);
1303 }
1304 return res;
1305}
1306
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001307/*
1308 * class BufferedReader
1309 */
1310
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001311PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001312 "Create a new buffered reader using the given readable raw IO object.");
1313
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001314static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001315{
1316 self->read_end = -1;
1317}
1318
1319static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001320bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001321{
1322 char *kwlist[] = {"raw", "buffer_size", NULL};
1323 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1324 PyObject *raw;
1325
1326 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001327 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001328
1329 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1330 &raw, &buffer_size)) {
1331 return -1;
1332 }
1333
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001334 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001335 return -1;
1336
1337 Py_CLEAR(self->raw);
1338 Py_INCREF(raw);
1339 self->raw = raw;
1340 self->buffer_size = buffer_size;
1341 self->readable = 1;
1342 self->writable = 0;
1343
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001344 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001345 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001346 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001347
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001348 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1349 Py_TYPE(raw) == &PyFileIO_Type);
1350
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001351 self->ok = 1;
1352 return 0;
1353}
1354
1355static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001356_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001357{
1358 Py_buffer buf;
1359 PyObject *memobj, *res;
1360 Py_ssize_t n;
1361 /* NOTE: the buffer needn't be released as its object is NULL. */
1362 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1363 return -1;
1364 memobj = PyMemoryView_FromBuffer(&buf);
1365 if (memobj == NULL)
1366 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001367 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1368 occurs so we needn't do it ourselves.
1369 We then retry reading, ignoring the signal if no handler has
1370 raised (see issue #10956).
1371 */
1372 do {
1373 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1374 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001375 Py_DECREF(memobj);
1376 if (res == NULL)
1377 return -1;
1378 if (res == Py_None) {
1379 /* Non-blocking stream would have blocked. Special return code! */
1380 Py_DECREF(res);
1381 return -2;
1382 }
1383 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1384 Py_DECREF(res);
1385 if (n < 0 || n > len) {
1386 PyErr_Format(PyExc_IOError,
1387 "raw readinto() returned invalid length %zd "
1388 "(should have been between 0 and %zd)", n, len);
1389 return -1;
1390 }
1391 if (n > 0 && self->abs_pos != -1)
1392 self->abs_pos += n;
1393 return n;
1394}
1395
1396static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001397_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001398{
1399 Py_ssize_t start, len, n;
1400 if (VALID_READ_BUFFER(self))
1401 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1402 else
1403 start = 0;
1404 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001405 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001406 if (n <= 0)
1407 return n;
1408 self->read_end = start + n;
1409 self->raw_pos = start + n;
1410 return n;
1411}
1412
1413static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001414_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001415{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001416 Py_ssize_t current_size;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001417 PyObject *res, *data = NULL, *chunk, *chunks;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001418
1419 /* First copy what we have in the current buffer. */
1420 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1421 if (current_size) {
1422 data = PyBytes_FromStringAndSize(
1423 self->buffer + self->pos, current_size);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001424 if (data == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001425 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001426 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001427 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001428 /* We're going past the buffer's bounds, flush it */
1429 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001430 res = buffered_flush_and_rewind_unlocked(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001431 if (res == NULL)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001432 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001433 Py_CLEAR(res);
1434 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001435 _bufferedreader_reset_buf(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001436
1437 if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
1438 chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
1439 if (chunk == NULL)
1440 return NULL;
1441 if (chunk != Py_None && !PyBytes_Check(chunk)) {
1442 Py_XDECREF(data);
1443 Py_DECREF(chunk);
1444 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1445 return NULL;
1446 }
1447 if (chunk == Py_None) {
1448 if (current_size == 0)
1449 return chunk;
1450 else {
1451 Py_DECREF(chunk);
1452 return data;
1453 }
1454 }
1455 else if (current_size) {
1456 PyBytes_Concat(&data, chunk);
1457 Py_DECREF(chunk);
1458 if (data == NULL)
1459 return NULL;
1460 return data;
1461 } else
1462 return chunk;
1463 }
1464
1465 chunks = PyList_New(0);
1466 if (chunks == NULL)
1467 return NULL;
1468
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001469 while (1) {
1470 if (data) {
1471 if (PyList_Append(chunks, data) < 0) {
1472 Py_DECREF(data);
1473 Py_DECREF(chunks);
1474 return NULL;
1475 }
1476 Py_DECREF(data);
1477 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001478
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001479 /* Read until EOF or until read() would block. */
1480 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1481 if (data == NULL) {
1482 Py_DECREF(chunks);
1483 return NULL;
1484 }
1485 if (data != Py_None && !PyBytes_Check(data)) {
1486 Py_DECREF(data);
1487 Py_DECREF(chunks);
1488 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1489 return NULL;
1490 }
1491 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1492 if (current_size == 0) {
1493 Py_DECREF(chunks);
1494 return data;
1495 }
1496 else {
1497 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1498 Py_DECREF(data);
1499 Py_DECREF(chunks);
1500 return res;
1501 }
1502 }
1503 current_size += PyBytes_GET_SIZE(data);
1504 if (self->abs_pos != -1)
1505 self->abs_pos += PyBytes_GET_SIZE(data);
1506 }
1507}
1508
1509/* Read n bytes from the buffer if it can, otherwise return None.
1510 This function is simple enough that it can run unlocked. */
1511static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001512_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001513{
1514 Py_ssize_t current_size;
1515
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001516 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1517 if (n <= current_size) {
1518 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001519 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1520 if (res != NULL)
1521 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001522 return res;
1523 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001524 Py_RETURN_NONE;
1525}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001526
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001527/* Generic read function: read from the stream until enough bytes are read,
1528 * or until an EOF occurs or until read() would block.
1529 */
1530static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001531_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001532{
1533 PyObject *res = NULL;
1534 Py_ssize_t current_size, remaining, written;
1535 char *out;
1536
1537 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1538 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001539 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001540
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001541 res = PyBytes_FromStringAndSize(NULL, n);
1542 if (res == NULL)
1543 goto error;
1544 out = PyBytes_AS_STRING(res);
1545 remaining = n;
1546 written = 0;
1547 if (current_size > 0) {
1548 memcpy(out, self->buffer + self->pos, current_size);
1549 remaining -= current_size;
1550 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001551 self->pos += current_size;
1552 }
1553 /* Flush the write buffer if necessary */
1554 if (self->writable) {
1555 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1556 if (r == NULL)
1557 goto error;
1558 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001559 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001560 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001561 while (remaining > 0) {
1562 /* We want to read a whole block at the end into buffer.
1563 If we had readv() we could do this in one pass. */
1564 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1565 if (r == 0)
1566 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001567 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001568 if (r == -1)
1569 goto error;
1570 if (r == 0 || r == -2) {
1571 /* EOF occurred or read() would block. */
1572 if (r == 0 || written > 0) {
1573 if (_PyBytes_Resize(&res, written))
1574 goto error;
1575 return res;
1576 }
1577 Py_DECREF(res);
1578 Py_INCREF(Py_None);
1579 return Py_None;
1580 }
1581 remaining -= r;
1582 written += r;
1583 }
1584 assert(remaining <= self->buffer_size);
1585 self->pos = 0;
1586 self->raw_pos = 0;
1587 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001588 /* NOTE: when the read is satisfied, we avoid issuing any additional
1589 reads, which could block indefinitely (e.g. on a socket).
1590 See issue #9550. */
1591 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001592 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001593 if (r == -1)
1594 goto error;
1595 if (r == 0 || r == -2) {
1596 /* EOF occurred or read() would block. */
1597 if (r == 0 || written > 0) {
1598 if (_PyBytes_Resize(&res, written))
1599 goto error;
1600 return res;
1601 }
1602 Py_DECREF(res);
1603 Py_INCREF(Py_None);
1604 return Py_None;
1605 }
1606 if (remaining > r) {
1607 memcpy(out + written, self->buffer + self->pos, r);
1608 written += r;
1609 self->pos += r;
1610 remaining -= r;
1611 }
1612 else if (remaining > 0) {
1613 memcpy(out + written, self->buffer + self->pos, remaining);
1614 written += remaining;
1615 self->pos += remaining;
1616 remaining = 0;
1617 }
1618 if (remaining == 0)
1619 break;
1620 }
1621
1622 return res;
1623
1624error:
1625 Py_XDECREF(res);
1626 return NULL;
1627}
1628
1629static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +02001630_bufferedreader_peek_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001631{
1632 Py_ssize_t have, r;
1633
1634 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1635 /* Constraints:
1636 1. we don't want to advance the file position.
1637 2. we don't want to lose block alignment, so we can't shift the buffer
1638 to make some place.
1639 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1640 */
1641 if (have > 0) {
1642 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1643 }
1644
1645 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001646 _bufferedreader_reset_buf(self);
1647 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001648 if (r == -1)
1649 return NULL;
1650 if (r == -2)
1651 r = 0;
1652 self->pos = 0;
1653 return PyBytes_FromStringAndSize(self->buffer, r);
1654}
1655
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001656static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001657 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001658 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1659 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1660 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1661 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1662 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1663 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1664 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1665 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001666 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001667 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001668
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001669 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1670 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1671 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001672 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001673 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1674 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1675 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1676 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001677 {NULL, NULL}
1678};
1679
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001680static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001681 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001682 {NULL}
1683};
1684
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001685static PyGetSetDef bufferedreader_getset[] = {
1686 {"closed", (getter)buffered_closed_get, NULL, NULL},
1687 {"name", (getter)buffered_name_get, NULL, NULL},
1688 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001689 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001690};
1691
1692
1693PyTypeObject PyBufferedReader_Type = {
1694 PyVarObject_HEAD_INIT(NULL, 0)
1695 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001696 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001697 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001698 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001699 0, /*tp_print*/
1700 0, /*tp_getattr*/
1701 0, /*tp_setattr*/
1702 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001703 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001704 0, /*tp_as_number*/
1705 0, /*tp_as_sequence*/
1706 0, /*tp_as_mapping*/
1707 0, /*tp_hash */
1708 0, /*tp_call*/
1709 0, /*tp_str*/
1710 0, /*tp_getattro*/
1711 0, /*tp_setattro*/
1712 0, /*tp_as_buffer*/
1713 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1714 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001715 bufferedreader_doc, /* tp_doc */
1716 (traverseproc)buffered_traverse, /* tp_traverse */
1717 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001718 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001719 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001720 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001721 (iternextfunc)buffered_iternext, /* tp_iternext */
1722 bufferedreader_methods, /* tp_methods */
1723 bufferedreader_members, /* tp_members */
1724 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001725 0, /* tp_base */
1726 0, /* tp_dict */
1727 0, /* tp_descr_get */
1728 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001729 offsetof(buffered, dict), /* tp_dictoffset */
1730 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001731 0, /* tp_alloc */
1732 PyType_GenericNew, /* tp_new */
1733};
1734
1735
Benjamin Peterson59406a92009-03-26 17:10:29 +00001736
1737static int
1738complain_about_max_buffer_size(void)
1739{
1740 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1741 "max_buffer_size is deprecated", 1) < 0)
1742 return 0;
1743 return 1;
1744}
1745
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001746/*
1747 * class BufferedWriter
1748 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001749PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001750 "A buffer for a writeable sequential RawIO object.\n"
1751 "\n"
1752 "The constructor creates a BufferedWriter for the given writeable raw\n"
1753 "stream. If the buffer_size is not given, it defaults to\n"
1754 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1755 );
1756
1757static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001758_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001759{
1760 self->write_pos = 0;
1761 self->write_end = -1;
1762}
1763
1764static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001765bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001766{
1767 /* TODO: properly deprecate max_buffer_size */
1768 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1769 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001770 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001771 PyObject *raw;
1772
1773 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001774 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001775
1776 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1777 &raw, &buffer_size, &max_buffer_size)) {
1778 return -1;
1779 }
1780
Benjamin Peterson59406a92009-03-26 17:10:29 +00001781 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1782 return -1;
1783
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001784 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001785 return -1;
1786
1787 Py_CLEAR(self->raw);
1788 Py_INCREF(raw);
1789 self->raw = raw;
1790 self->readable = 0;
1791 self->writable = 1;
1792
1793 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001794 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001795 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001796 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001797 self->pos = 0;
1798
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001799 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1800 Py_TYPE(raw) == &PyFileIO_Type);
1801
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001802 self->ok = 1;
1803 return 0;
1804}
1805
1806static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001807_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001808{
1809 Py_buffer buf;
1810 PyObject *memobj, *res;
1811 Py_ssize_t n;
1812 /* NOTE: the buffer needn't be released as its object is NULL. */
1813 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1814 return -1;
1815 memobj = PyMemoryView_FromBuffer(&buf);
1816 if (memobj == NULL)
1817 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001818 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1819 occurs so we needn't do it ourselves.
1820 We then retry writing, ignoring the signal if no handler has
1821 raised (see issue #10956).
1822 */
1823 do {
1824 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1825 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001826 Py_DECREF(memobj);
1827 if (res == NULL)
1828 return -1;
1829 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1830 Py_DECREF(res);
1831 if (n < 0 || n > len) {
1832 PyErr_Format(PyExc_IOError,
1833 "raw write() returned invalid length %zd "
1834 "(should have been between 0 and %zd)", n, len);
1835 return -1;
1836 }
1837 if (n > 0 && self->abs_pos != -1)
1838 self->abs_pos += n;
1839 return n;
1840}
1841
1842/* `restore_pos` is 1 if we need to restore the raw stream position at
1843 the end, 0 otherwise. */
1844static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001845_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001846{
1847 Py_ssize_t written = 0;
1848 Py_off_t n, rewind;
1849
1850 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1851 goto end;
1852 /* First, rewind */
1853 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1854 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001855 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001856 if (n < 0) {
1857 goto error;
1858 }
1859 self->raw_pos -= rewind;
1860 }
1861 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001862 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001863 self->buffer + self->write_pos,
1864 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1865 Py_off_t, Py_ssize_t));
1866 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001867 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001868 if (w == NULL)
1869 goto error;
1870 self->write_pos += *w;
1871 self->raw_pos = self->write_pos;
1872 written += *w;
1873 *w = written;
1874 /* Already re-raised */
1875 goto error;
1876 }
1877 self->write_pos += n;
1878 self->raw_pos = self->write_pos;
1879 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001880 /* Partial writes can return successfully when interrupted by a
1881 signal (see write(2)). We must run signal handlers before
1882 blocking another time, possibly indefinitely. */
1883 if (PyErr_CheckSignals() < 0)
1884 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001885 }
1886
1887 if (restore_pos) {
1888 Py_off_t forward = rewind - written;
1889 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001890 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001891 if (n < 0) {
1892 goto error;
1893 }
1894 self->raw_pos += forward;
1895 }
1896 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001897 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001898
1899end:
1900 Py_RETURN_NONE;
1901
1902error:
1903 return NULL;
1904}
1905
1906static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001907bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001908{
1909 PyObject *res = NULL;
1910 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001911 Py_ssize_t written, avail, remaining;
1912 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001913
1914 CHECK_INITIALIZED(self)
1915 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1916 return NULL;
1917 }
1918
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001919 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001920 PyErr_SetString(PyExc_ValueError, "write to closed file");
1921 PyBuffer_Release(&buf);
1922 return NULL;
1923 }
1924
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001925 if (!ENTER_BUFFERED(self)) {
1926 PyBuffer_Release(&buf);
1927 return NULL;
1928 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001929
1930 /* Fast path: the data to write can be fully buffered. */
1931 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1932 self->pos = 0;
1933 self->raw_pos = 0;
1934 }
1935 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1936 if (buf.len <= avail) {
1937 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02001938 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001939 self->write_pos = self->pos;
1940 }
1941 ADJUST_POSITION(self, self->pos + buf.len);
1942 if (self->pos > self->write_end)
1943 self->write_end = self->pos;
1944 written = buf.len;
1945 goto end;
1946 }
1947
1948 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001949 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001950 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001951 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001952 if (w == NULL)
1953 goto error;
1954 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001955 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001956 /* Make some place by shifting the buffer. */
1957 assert(VALID_WRITE_BUFFER(self));
1958 memmove(self->buffer, self->buffer + self->write_pos,
1959 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1960 Py_off_t, Py_ssize_t));
1961 self->write_end -= self->write_pos;
1962 self->raw_pos -= self->write_pos;
1963 self->pos -= self->write_pos;
1964 self->write_pos = 0;
1965 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1966 Py_off_t, Py_ssize_t);
1967 if (buf.len <= avail) {
1968 /* Everything can be buffered */
1969 PyErr_Clear();
1970 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1971 self->write_end += buf.len;
1972 written = buf.len;
1973 goto end;
1974 }
1975 /* Buffer as much as possible. */
1976 memcpy(self->buffer + self->write_end, buf.buf, avail);
1977 self->write_end += avail;
1978 /* Already re-raised */
1979 *w = avail;
1980 goto error;
1981 }
1982 Py_CLEAR(res);
1983
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001984 /* Adjust the raw stream position if it is away from the logical stream
1985 position. This happens if the read buffer has been filled but not
1986 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1987 the raw stream by itself).
1988 Fixes issue #6629.
1989 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001990 offset = RAW_OFFSET(self);
1991 if (offset != 0) {
1992 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001993 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001994 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001995 }
1996
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001997 /* Then write buf itself. At this point the buffer has been emptied. */
1998 remaining = buf.len;
1999 written = 0;
2000 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002001 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002002 self, (char *) buf.buf + written, buf.len - written);
2003 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002004 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002005 if (w == NULL)
2006 goto error;
2007 written += *w;
2008 remaining -= *w;
2009 if (remaining > self->buffer_size) {
2010 /* Can't buffer everything, still buffer as much as possible */
2011 memcpy(self->buffer,
2012 (char *) buf.buf + written, self->buffer_size);
2013 self->raw_pos = 0;
2014 ADJUST_POSITION(self, self->buffer_size);
2015 self->write_end = self->buffer_size;
2016 *w = written + self->buffer_size;
2017 /* Already re-raised */
2018 goto error;
2019 }
2020 PyErr_Clear();
2021 break;
2022 }
2023 written += n;
2024 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002025 /* Partial writes can return successfully when interrupted by a
2026 signal (see write(2)). We must run signal handlers before
2027 blocking another time, possibly indefinitely. */
2028 if (PyErr_CheckSignals() < 0)
2029 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002030 }
2031 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002032 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002033 if (remaining > 0) {
2034 memcpy(self->buffer, (char *) buf.buf + written, remaining);
2035 written += remaining;
2036 }
2037 self->write_pos = 0;
2038 /* TODO: sanity check (remaining >= 0) */
2039 self->write_end = remaining;
2040 ADJUST_POSITION(self, remaining);
2041 self->raw_pos = 0;
2042
2043end:
2044 res = PyLong_FromSsize_t(written);
2045
2046error:
2047 LEAVE_BUFFERED(self)
2048 PyBuffer_Release(&buf);
2049 return res;
2050}
2051
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002052static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002053 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002054 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2055 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2056 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2057 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2058 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2059 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2060 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002061 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002062 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002063
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002064 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2065 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2066 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2067 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2068 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002069 {NULL, NULL}
2070};
2071
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002072static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002073 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002074 {NULL}
2075};
2076
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002077static PyGetSetDef bufferedwriter_getset[] = {
2078 {"closed", (getter)buffered_closed_get, NULL, NULL},
2079 {"name", (getter)buffered_name_get, NULL, NULL},
2080 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002081 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002082};
2083
2084
2085PyTypeObject PyBufferedWriter_Type = {
2086 PyVarObject_HEAD_INIT(NULL, 0)
2087 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002088 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002089 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002090 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002091 0, /*tp_print*/
2092 0, /*tp_getattr*/
2093 0, /*tp_setattr*/
2094 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002095 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002096 0, /*tp_as_number*/
2097 0, /*tp_as_sequence*/
2098 0, /*tp_as_mapping*/
2099 0, /*tp_hash */
2100 0, /*tp_call*/
2101 0, /*tp_str*/
2102 0, /*tp_getattro*/
2103 0, /*tp_setattro*/
2104 0, /*tp_as_buffer*/
2105 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2106 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002107 bufferedwriter_doc, /* tp_doc */
2108 (traverseproc)buffered_traverse, /* tp_traverse */
2109 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002110 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002111 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002112 0, /* tp_iter */
2113 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002114 bufferedwriter_methods, /* tp_methods */
2115 bufferedwriter_members, /* tp_members */
2116 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002117 0, /* tp_base */
2118 0, /* tp_dict */
2119 0, /* tp_descr_get */
2120 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002121 offsetof(buffered, dict), /* tp_dictoffset */
2122 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002123 0, /* tp_alloc */
2124 PyType_GenericNew, /* tp_new */
2125};
2126
2127
2128
2129/*
2130 * BufferedRWPair
2131 */
2132
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002133PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002134 "A buffered reader and writer object together.\n"
2135 "\n"
2136 "A buffered reader object and buffered writer object put together to\n"
2137 "form a sequential IO object that can read and write. This is typically\n"
2138 "used with a socket or two-way pipe.\n"
2139 "\n"
2140 "reader and writer are RawIOBase objects that are readable and\n"
2141 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002142 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002143 );
2144
2145/* XXX The usefulness of this (compared to having two separate IO objects) is
2146 * questionable.
2147 */
2148
2149typedef struct {
2150 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002151 buffered *reader;
2152 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002153 PyObject *dict;
2154 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002155} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002156
2157static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002158bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002159{
2160 PyObject *reader, *writer;
2161 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002162 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002163
2164 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2165 &buffer_size, &max_buffer_size)) {
2166 return -1;
2167 }
2168
Benjamin Peterson59406a92009-03-26 17:10:29 +00002169 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2170 return -1;
2171
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002172 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002173 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002174 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002175 return -1;
2176
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002177 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002178 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002179 if (self->reader == NULL)
2180 return -1;
2181
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002182 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002183 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002184 if (self->writer == NULL) {
2185 Py_CLEAR(self->reader);
2186 return -1;
2187 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002188
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002189 return 0;
2190}
2191
2192static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002193bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002194{
2195 Py_VISIT(self->dict);
2196 return 0;
2197}
2198
2199static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002200bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002201{
2202 Py_CLEAR(self->reader);
2203 Py_CLEAR(self->writer);
2204 Py_CLEAR(self->dict);
2205 return 0;
2206}
2207
2208static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002209bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002210{
2211 _PyObject_GC_UNTRACK(self);
2212 Py_CLEAR(self->reader);
2213 Py_CLEAR(self->writer);
2214 Py_CLEAR(self->dict);
2215 Py_TYPE(self)->tp_free((PyObject *) self);
2216}
2217
2218static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002219_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002220{
2221 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2222 PyObject *ret;
2223
2224 if (func == NULL) {
2225 PyErr_SetString(PyExc_AttributeError, name);
2226 return NULL;
2227 }
2228
2229 ret = PyObject_CallObject(func, args);
2230 Py_DECREF(func);
2231 return ret;
2232}
2233
2234static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002235bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002236{
2237 return _forward_call(self->reader, "read", args);
2238}
2239
2240static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002241bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002242{
2243 return _forward_call(self->reader, "peek", args);
2244}
2245
2246static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002247bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002248{
2249 return _forward_call(self->reader, "read1", args);
2250}
2251
2252static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002253bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002254{
2255 return _forward_call(self->reader, "readinto", args);
2256}
2257
2258static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002259bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002260{
2261 return _forward_call(self->writer, "write", args);
2262}
2263
2264static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002265bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002266{
2267 return _forward_call(self->writer, "flush", args);
2268}
2269
2270static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002271bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002272{
2273 return _forward_call(self->reader, "readable", args);
2274}
2275
2276static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002277bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002278{
2279 return _forward_call(self->writer, "writable", args);
2280}
2281
2282static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002283bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002284{
2285 PyObject *ret = _forward_call(self->writer, "close", args);
2286 if (ret == NULL)
2287 return NULL;
2288 Py_DECREF(ret);
2289
2290 return _forward_call(self->reader, "close", args);
2291}
2292
2293static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002294bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002295{
2296 PyObject *ret = _forward_call(self->writer, "isatty", args);
2297
2298 if (ret != Py_False) {
2299 /* either True or exception */
2300 return ret;
2301 }
2302 Py_DECREF(ret);
2303
2304 return _forward_call(self->reader, "isatty", args);
2305}
2306
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002307static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002308bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002309{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002310 if (self->writer == NULL) {
2311 PyErr_SetString(PyExc_RuntimeError,
2312 "the BufferedRWPair object is being garbage-collected");
2313 return NULL;
2314 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002315 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2316}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002317
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002318static PyMethodDef bufferedrwpair_methods[] = {
2319 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2320 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2321 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2322 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002323
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002324 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2325 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002326
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002327 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2328 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002329
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002330 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2331 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002332
Antoine Pitrou243757e2010-11-05 21:15:39 +00002333 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2334
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002335 {NULL, NULL}
2336};
2337
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002338static PyGetSetDef bufferedrwpair_getset[] = {
2339 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002340 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002341};
2342
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002343PyTypeObject PyBufferedRWPair_Type = {
2344 PyVarObject_HEAD_INIT(NULL, 0)
2345 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002346 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002347 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002348 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002349 0, /*tp_print*/
2350 0, /*tp_getattr*/
2351 0, /*tp_setattr*/
2352 0, /*tp_compare */
2353 0, /*tp_repr*/
2354 0, /*tp_as_number*/
2355 0, /*tp_as_sequence*/
2356 0, /*tp_as_mapping*/
2357 0, /*tp_hash */
2358 0, /*tp_call*/
2359 0, /*tp_str*/
2360 0, /*tp_getattro*/
2361 0, /*tp_setattro*/
2362 0, /*tp_as_buffer*/
2363 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2364 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002365 bufferedrwpair_doc, /* tp_doc */
2366 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2367 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002368 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002369 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002370 0, /* tp_iter */
2371 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002372 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002373 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002374 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002375 0, /* tp_base */
2376 0, /* tp_dict */
2377 0, /* tp_descr_get */
2378 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002379 offsetof(rwpair, dict), /* tp_dictoffset */
2380 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002381 0, /* tp_alloc */
2382 PyType_GenericNew, /* tp_new */
2383};
2384
2385
2386
2387/*
2388 * BufferedRandom
2389 */
2390
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002391PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002392 "A buffered interface to random access streams.\n"
2393 "\n"
2394 "The constructor creates a reader and writer for a seekable stream,\n"
2395 "raw, given in the first argument. If the buffer_size is omitted it\n"
2396 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2397 );
2398
2399static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002400bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002401{
2402 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2403 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002404 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002405 PyObject *raw;
2406
2407 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002408 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002409
2410 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2411 &raw, &buffer_size, &max_buffer_size)) {
2412 return -1;
2413 }
2414
Benjamin Peterson59406a92009-03-26 17:10:29 +00002415 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2416 return -1;
2417
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002418 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002419 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002420 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002421 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002422 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002423 return -1;
2424
2425 Py_CLEAR(self->raw);
2426 Py_INCREF(raw);
2427 self->raw = raw;
2428 self->buffer_size = buffer_size;
2429 self->readable = 1;
2430 self->writable = 1;
2431
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002432 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002433 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002434 _bufferedreader_reset_buf(self);
2435 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002436 self->pos = 0;
2437
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002438 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2439 Py_TYPE(raw) == &PyFileIO_Type);
2440
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002441 self->ok = 1;
2442 return 0;
2443}
2444
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002445static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002446 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002447 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2448 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2449 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2450 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2451 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2452 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2453 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002454 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002455 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002456
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002457 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002458
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002459 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2460 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2461 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2462 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2463 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2464 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2465 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2466 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2467 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002468 {NULL, NULL}
2469};
2470
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002471static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002472 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002473 {NULL}
2474};
2475
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002476static PyGetSetDef bufferedrandom_getset[] = {
2477 {"closed", (getter)buffered_closed_get, NULL, NULL},
2478 {"name", (getter)buffered_name_get, NULL, NULL},
2479 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002480 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002481};
2482
2483
2484PyTypeObject PyBufferedRandom_Type = {
2485 PyVarObject_HEAD_INIT(NULL, 0)
2486 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002487 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002488 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002489 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002490 0, /*tp_print*/
2491 0, /*tp_getattr*/
2492 0, /*tp_setattr*/
2493 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002494 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002495 0, /*tp_as_number*/
2496 0, /*tp_as_sequence*/
2497 0, /*tp_as_mapping*/
2498 0, /*tp_hash */
2499 0, /*tp_call*/
2500 0, /*tp_str*/
2501 0, /*tp_getattro*/
2502 0, /*tp_setattro*/
2503 0, /*tp_as_buffer*/
2504 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2505 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002506 bufferedrandom_doc, /* tp_doc */
2507 (traverseproc)buffered_traverse, /* tp_traverse */
2508 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002509 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002510 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002511 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002512 (iternextfunc)buffered_iternext, /* tp_iternext */
2513 bufferedrandom_methods, /* tp_methods */
2514 bufferedrandom_members, /* tp_members */
2515 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002516 0, /* tp_base */
2517 0, /*tp_dict*/
2518 0, /* tp_descr_get */
2519 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002520 offsetof(buffered, dict), /*tp_dictoffset*/
2521 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002522 0, /* tp_alloc */
2523 PyType_GenericNew, /* tp_new */
2524};