blob: 63ae1cbd1d8da48536ef7b64859613e23c777dda [file] [log] [blame]
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001/*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
Antoine Pitrou3486a982011-05-12 01:57:53 +02003
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00004 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
Antoine Pitrou3486a982011-05-12 01:57:53 +02006
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00007 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8*/
9
10#define PY_SSIZE_T_CLEAN
11#include "Python.h"
12#include "structmember.h"
13#include "pythread.h"
14#include "_iomodule.h"
15
16/*
17 * BufferedIOBase class, inherits from IOBase.
18 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000019PyDoc_STRVAR(bufferediobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000020 "Base class for buffered IO objects.\n"
21 "\n"
22 "The main difference with RawIOBase is that the read() method\n"
23 "supports omitting the size argument, and does not have a default\n"
24 "implementation that defers to readinto().\n"
25 "\n"
26 "In addition, read(), readinto() and write() may raise\n"
27 "BlockingIOError if the underlying raw stream is in non-blocking\n"
28 "mode and not ready; unlike their raw counterparts, they will never\n"
29 "return None.\n"
30 "\n"
31 "A typical implementation should not inherit from a RawIOBase\n"
32 "implementation, but wrap one.\n"
33 );
34
35static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000036bufferediobase_readinto(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000037{
38 Py_buffer buf;
39 Py_ssize_t len;
40 PyObject *data;
41
42 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
43 return NULL;
44 }
45
46 data = PyObject_CallMethod(self, "read", "n", buf.len);
47 if (data == NULL)
48 goto error;
49
50 if (!PyBytes_Check(data)) {
51 Py_DECREF(data);
52 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
53 goto error;
54 }
55
56 len = Py_SIZE(data);
57 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
58
59 PyBuffer_Release(&buf);
60 Py_DECREF(data);
61
62 return PyLong_FromSsize_t(len);
63
64 error:
65 PyBuffer_Release(&buf);
66 return NULL;
67}
68
69static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000070bufferediobase_unsupported(const char *message)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000071{
72 PyErr_SetString(IO_STATE->unsupported_operation, message);
73 return NULL;
74}
75
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000076PyDoc_STRVAR(bufferediobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +000077 "Disconnect this buffer from its underlying raw stream and return it.\n"
78 "\n"
79 "After the raw stream has been detached, the buffer is in an unusable\n"
80 "state.\n");
81
82static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000083bufferediobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +000084{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000085 return bufferediobase_unsupported("detach");
Benjamin Petersond2e0c792009-05-01 20:40:59 +000086}
87
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000088PyDoc_STRVAR(bufferediobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000089 "Read and return up to n bytes.\n"
90 "\n"
91 "If the argument is omitted, None, or negative, reads and\n"
92 "returns all data until EOF.\n"
93 "\n"
94 "If the argument is positive, and the underlying raw stream is\n"
95 "not 'interactive', multiple raw reads may be issued to satisfy\n"
96 "the byte count (unless EOF is reached first). But for\n"
97 "interactive raw streams (as well as sockets and pipes), at most\n"
98 "one raw read will be issued, and a short result does not imply\n"
99 "that EOF is imminent.\n"
100 "\n"
101 "Returns an empty bytes object on EOF.\n"
102 "\n"
103 "Returns None if the underlying raw stream was open in non-blocking\n"
104 "mode and no data is available at the moment.\n");
105
106static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000107bufferediobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000108{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000109 return bufferediobase_unsupported("read");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000110}
111
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000112PyDoc_STRVAR(bufferediobase_read1_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000113 "Read and return up to n bytes, with at most one read() call\n"
114 "to the underlying raw stream. A short result does not imply\n"
115 "that EOF is imminent.\n"
116 "\n"
117 "Returns an empty bytes object on EOF.\n");
118
119static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000120bufferediobase_read1(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000121{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000122 return bufferediobase_unsupported("read1");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000123}
124
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000125PyDoc_STRVAR(bufferediobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000126 "Write the given buffer to the IO stream.\n"
127 "\n"
128 "Returns the number of bytes written, which is never less than\n"
129 "len(b).\n"
130 "\n"
131 "Raises BlockingIOError if the buffer is full and the\n"
132 "underlying raw stream cannot accept more data at the moment.\n");
133
134static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000135bufferediobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000136{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000137 return bufferediobase_unsupported("write");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000138}
139
140
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000141static PyMethodDef bufferediobase_methods[] = {
142 {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
143 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
144 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
145 {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
146 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000147 {NULL, NULL}
148};
149
150PyTypeObject PyBufferedIOBase_Type = {
151 PyVarObject_HEAD_INIT(NULL, 0)
152 "_io._BufferedIOBase", /*tp_name*/
153 0, /*tp_basicsize*/
154 0, /*tp_itemsize*/
155 0, /*tp_dealloc*/
156 0, /*tp_print*/
157 0, /*tp_getattr*/
158 0, /*tp_setattr*/
159 0, /*tp_compare */
160 0, /*tp_repr*/
161 0, /*tp_as_number*/
162 0, /*tp_as_sequence*/
163 0, /*tp_as_mapping*/
164 0, /*tp_hash */
165 0, /*tp_call*/
166 0, /*tp_str*/
167 0, /*tp_getattro*/
168 0, /*tp_setattro*/
169 0, /*tp_as_buffer*/
170 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000171 bufferediobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000172 0, /* tp_traverse */
173 0, /* tp_clear */
174 0, /* tp_richcompare */
175 0, /* tp_weaklistoffset */
176 0, /* tp_iter */
177 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000178 bufferediobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000179 0, /* tp_members */
180 0, /* tp_getset */
181 &PyIOBase_Type, /* tp_base */
182 0, /* tp_dict */
183 0, /* tp_descr_get */
184 0, /* tp_descr_set */
185 0, /* tp_dictoffset */
186 0, /* tp_init */
187 0, /* tp_alloc */
188 0, /* tp_new */
189};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000190
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000191
192typedef struct {
193 PyObject_HEAD
194
195 PyObject *raw;
196 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000197 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000198 int readable;
199 int writable;
Antoine Pitroue033e062010-10-29 10:38:18 +0000200 int deallocating;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200201
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000202 /* True if this is a vanilla Buffered object (rather than a user derived
203 class) *and* the raw stream is a vanilla FileIO object. */
204 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000205
206 /* Absolute position inside the raw stream (-1 if unknown). */
207 Py_off_t abs_pos;
208
209 /* A static buffer of size `buffer_size` */
210 char *buffer;
211 /* Current logical position in the buffer. */
212 Py_off_t pos;
213 /* Position of the raw stream in the buffer. */
214 Py_off_t raw_pos;
215
216 /* Just after the last buffered byte in the buffer, or -1 if the buffer
217 isn't ready for reading. */
218 Py_off_t read_end;
219
220 /* Just after the last byte actually written */
221 Py_off_t write_pos;
222 /* Just after the last byte waiting to be written, or -1 if the buffer
223 isn't ready for writing. */
224 Py_off_t write_end;
225
Georg Brandldfd73442009-04-05 11:47:34 +0000226#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000227 PyThread_type_lock lock;
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000228 volatile long owner;
Georg Brandldfd73442009-04-05 11:47:34 +0000229#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000230
231 Py_ssize_t buffer_size;
232 Py_ssize_t buffer_mask;
233
234 PyObject *dict;
235 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000236} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000237
238/*
239 Implementation notes:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200240
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000241 * BufferedReader, BufferedWriter and BufferedRandom try to share most
242 methods (this is helped by the members `readable` and `writable`, which
243 are initialized in the respective constructors)
244 * They also share a single buffer for reading and writing. This enables
245 interleaved reads and writes without flushing. It also makes the logic
246 a bit trickier to get right.
247 * The absolute position of the raw stream is cached, if possible, in the
248 `abs_pos` member. It must be updated every time an operation is done
249 on the raw stream. If not sure, it can be reinitialized by calling
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000250 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000251 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000252 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
253 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000254
255 NOTE: we should try to maintain block alignment of reads and writes to the
256 raw stream (according to the buffer size), but for now it is only done
257 in read() and friends.
Antoine Pitrou3486a982011-05-12 01:57:53 +0200258
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000259*/
260
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000261/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000262
Georg Brandldfd73442009-04-05 11:47:34 +0000263#ifdef WITH_THREAD
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000264
265static int
266_enter_buffered_busy(buffered *self)
267{
268 if (self->owner == PyThread_get_thread_ident()) {
269 PyErr_Format(PyExc_RuntimeError,
270 "reentrant call inside %R", self);
271 return 0;
Antoine Pitrou5800b272009-11-01 12:05:48 +0000272 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000273 Py_BEGIN_ALLOW_THREADS
274 PyThread_acquire_lock(self->lock, 1);
275 Py_END_ALLOW_THREADS
276 return 1;
277}
278
279#define ENTER_BUFFERED(self) \
280 ( (PyThread_acquire_lock(self->lock, 0) ? \
281 1 : _enter_buffered_busy(self)) \
282 && (self->owner = PyThread_get_thread_ident(), 1) )
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000283
284#define LEAVE_BUFFERED(self) \
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000285 do { \
286 self->owner = 0; \
287 PyThread_release_lock(self->lock); \
288 } while(0);
289
Georg Brandldfd73442009-04-05 11:47:34 +0000290#else
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000291#define ENTER_BUFFERED(self) 1
Georg Brandldfd73442009-04-05 11:47:34 +0000292#define LEAVE_BUFFERED(self)
293#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000294
295#define CHECK_INITIALIZED(self) \
296 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000297 if (self->detached) { \
298 PyErr_SetString(PyExc_ValueError, \
299 "raw stream has been detached"); \
300 } else { \
301 PyErr_SetString(PyExc_ValueError, \
302 "I/O operation on uninitialized object"); \
303 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000304 return NULL; \
305 }
306
307#define CHECK_INITIALIZED_INT(self) \
308 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000309 if (self->detached) { \
310 PyErr_SetString(PyExc_ValueError, \
311 "raw stream has been detached"); \
312 } else { \
313 PyErr_SetString(PyExc_ValueError, \
314 "I/O operation on uninitialized object"); \
315 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000316 return -1; \
317 }
318
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000319#define IS_CLOSED(self) \
320 (self->fast_closed_checks \
321 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000322 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000323
324#define CHECK_CLOSED(self, error_msg) \
325 if (IS_CLOSED(self)) { \
326 PyErr_SetString(PyExc_ValueError, error_msg); \
327 return NULL; \
328 }
329
330
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000331#define VALID_READ_BUFFER(self) \
332 (self->readable && self->read_end != -1)
333
334#define VALID_WRITE_BUFFER(self) \
335 (self->writable && self->write_end != -1)
336
337#define ADJUST_POSITION(self, _new_pos) \
338 do { \
339 self->pos = _new_pos; \
340 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
341 self->read_end = self->pos; \
342 } while(0)
343
344#define READAHEAD(self) \
345 ((self->readable && VALID_READ_BUFFER(self)) \
346 ? (self->read_end - self->pos) : 0)
347
348#define RAW_OFFSET(self) \
349 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
350 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
351
352#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000353 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000354
355#define MINUS_LAST_BLOCK(self, size) \
356 (self->buffer_mask ? \
357 (size & ~self->buffer_mask) : \
358 (self->buffer_size * (size / self->buffer_size)))
359
360
361static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000362buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000363{
Antoine Pitroue033e062010-10-29 10:38:18 +0000364 self->deallocating = 1;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000365 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
366 return;
367 _PyObject_GC_UNTRACK(self);
368 self->ok = 0;
369 if (self->weakreflist != NULL)
370 PyObject_ClearWeakRefs((PyObject *)self);
371 Py_CLEAR(self->raw);
372 if (self->buffer) {
373 PyMem_Free(self->buffer);
374 self->buffer = NULL;
375 }
Georg Brandldfd73442009-04-05 11:47:34 +0000376#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000377 if (self->lock) {
378 PyThread_free_lock(self->lock);
379 self->lock = NULL;
380 }
Georg Brandldfd73442009-04-05 11:47:34 +0000381#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000382 Py_CLEAR(self->dict);
383 Py_TYPE(self)->tp_free((PyObject *)self);
384}
385
386static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000387buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000388{
389 Py_VISIT(self->raw);
390 Py_VISIT(self->dict);
391 return 0;
392}
393
394static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000395buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000396{
397 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
398 return -1;
399 self->ok = 0;
400 Py_CLEAR(self->raw);
401 Py_CLEAR(self->dict);
402 return 0;
403}
404
Antoine Pitroue033e062010-10-29 10:38:18 +0000405/* Because this can call arbitrary code, it shouldn't be called when
406 the refcount is 0 (that is, not directly from tp_dealloc unless
407 the refcount has been temporarily re-incremented). */
Matthias Klosebee33162010-11-16 20:07:51 +0000408static PyObject *
Antoine Pitroue033e062010-10-29 10:38:18 +0000409buffered_dealloc_warn(buffered *self, PyObject *source)
410{
411 if (self->ok && self->raw) {
412 PyObject *r;
413 r = PyObject_CallMethod(self->raw, "_dealloc_warn", "O", source);
414 if (r)
415 Py_DECREF(r);
416 else
417 PyErr_Clear();
418 }
419 Py_RETURN_NONE;
420}
421
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000422/*
423 * _BufferedIOMixin methods
424 * This is not a class, just a collection of methods that will be reused
425 * by BufferedReader and BufferedWriter
426 */
427
428/* Flush and close */
429
430static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000431buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000432{
433 CHECK_INITIALIZED(self)
434 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
435}
436
437static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000438buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000439{
440 int closed;
441 PyObject *res;
442 CHECK_INITIALIZED_INT(self)
443 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
444 if (res == NULL)
445 return -1;
446 closed = PyObject_IsTrue(res);
447 Py_DECREF(res);
448 return closed;
449}
450
451static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000452buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000453{
454 CHECK_INITIALIZED(self)
455 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
456}
457
458static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000459buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000460{
461 PyObject *res = NULL;
462 int r;
463
464 CHECK_INITIALIZED(self)
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000465 if (!ENTER_BUFFERED(self))
466 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000467
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000468 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000469 if (r < 0)
470 goto end;
471 if (r > 0) {
472 res = Py_None;
473 Py_INCREF(res);
474 goto end;
475 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000476
477 if (self->deallocating) {
478 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
479 if (r)
480 Py_DECREF(r);
481 else
482 PyErr_Clear();
483 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000484 /* flush() will most probably re-take the lock, so drop it first */
485 LEAVE_BUFFERED(self)
486 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000487 if (!ENTER_BUFFERED(self))
488 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000489 if (res == NULL) {
Antoine Pitrou6be88762010-05-03 16:48:20 +0000490 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000491 }
492 Py_XDECREF(res);
493
494 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
495
496end:
497 LEAVE_BUFFERED(self)
498 return res;
499}
500
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000501/* detach */
502
503static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000504buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000505{
506 PyObject *raw, *res;
507 CHECK_INITIALIZED(self)
508 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
509 if (res == NULL)
510 return NULL;
511 Py_DECREF(res);
512 raw = self->raw;
513 self->raw = NULL;
514 self->detached = 1;
515 self->ok = 0;
516 return raw;
517}
518
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000519/* Inquiries */
520
521static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000522buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000523{
524 CHECK_INITIALIZED(self)
525 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
526}
527
528static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000529buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000530{
531 CHECK_INITIALIZED(self)
532 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
533}
534
535static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000536buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000537{
538 CHECK_INITIALIZED(self)
539 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
540}
541
542static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000543buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000544{
545 CHECK_INITIALIZED(self)
546 return PyObject_GetAttrString(self->raw, "name");
547}
548
549static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000550buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000551{
552 CHECK_INITIALIZED(self)
553 return PyObject_GetAttrString(self->raw, "mode");
554}
555
556/* Lower-level APIs */
557
558static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000559buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000560{
561 CHECK_INITIALIZED(self)
562 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
563}
564
565static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000566buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000567{
568 CHECK_INITIALIZED(self)
569 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
570}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000571
Antoine Pitrou243757e2010-11-05 21:15:39 +0000572/* Serialization */
573
574static PyObject *
575buffered_getstate(buffered *self, PyObject *args)
576{
577 PyErr_Format(PyExc_TypeError,
578 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
579 return NULL;
580}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000581
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000582/* Forward decls */
583static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000584_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000585static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000586_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000587static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000588_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000589static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000590_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000591static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000592_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000593static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000594_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000595static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000596_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000597static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000598_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200599static Py_ssize_t
600_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000601
602/*
603 * Helpers
604 */
605
606/* Returns the address of the `written` member if a BlockingIOError was
607 raised, NULL otherwise. The error is always re-raised. */
608static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000609_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000610{
611 PyObject *t, *v, *tb;
612 PyBlockingIOErrorObject *err;
613
614 PyErr_Fetch(&t, &v, &tb);
615 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
616 PyErr_Restore(t, v, tb);
617 return NULL;
618 }
619 err = (PyBlockingIOErrorObject *) v;
620 /* TODO: sanity check (err->written >= 0) */
621 PyErr_Restore(t, v, tb);
622 return &err->written;
623}
624
625static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000626_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000627{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000628 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000629 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000630 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
631 if (res == NULL)
632 return -1;
633 n = PyNumber_AsOff_t(res, PyExc_ValueError);
634 Py_DECREF(res);
635 if (n < 0) {
636 if (!PyErr_Occurred())
637 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000638 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200639 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000640 return -1;
641 }
642 self->abs_pos = n;
643 return n;
644}
645
646static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000647_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000648{
649 PyObject *res, *posobj, *whenceobj;
650 Py_off_t n;
651
652 posobj = PyLong_FromOff_t(target);
653 if (posobj == NULL)
654 return -1;
655 whenceobj = PyLong_FromLong(whence);
656 if (whenceobj == NULL) {
657 Py_DECREF(posobj);
658 return -1;
659 }
660 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
661 posobj, whenceobj, NULL);
662 Py_DECREF(posobj);
663 Py_DECREF(whenceobj);
664 if (res == NULL)
665 return -1;
666 n = PyNumber_AsOff_t(res, PyExc_ValueError);
667 Py_DECREF(res);
668 if (n < 0) {
669 if (!PyErr_Occurred())
670 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000671 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200672 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000673 return -1;
674 }
675 self->abs_pos = n;
676 return n;
677}
678
679static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000680_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000681{
682 Py_ssize_t n;
683 if (self->buffer_size <= 0) {
684 PyErr_SetString(PyExc_ValueError,
685 "buffer size must be strictly positive");
686 return -1;
687 }
688 if (self->buffer)
689 PyMem_Free(self->buffer);
690 self->buffer = PyMem_Malloc(self->buffer_size);
691 if (self->buffer == NULL) {
692 PyErr_NoMemory();
693 return -1;
694 }
Georg Brandldfd73442009-04-05 11:47:34 +0000695#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000696 if (self->lock)
697 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000698 self->lock = PyThread_allocate_lock();
699 if (self->lock == NULL) {
700 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
701 return -1;
702 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000703 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000704#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000705 /* Find out whether buffer_size is a power of 2 */
706 /* XXX is this optimization useful? */
707 for (n = self->buffer_size - 1; n & 1; n >>= 1)
708 ;
709 if (n == 0)
710 self->buffer_mask = self->buffer_size - 1;
711 else
712 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000713 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000714 PyErr_Clear();
715 return 0;
716}
717
Antoine Pitrou707ce822011-02-25 21:24:11 +0000718/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
719 clears the error indicator), 0 otherwise.
720 Should only be called when PyErr_Occurred() is true.
721*/
722static int
723_trap_eintr(void)
724{
725 static PyObject *eintr_int = NULL;
726 PyObject *typ, *val, *tb;
727 PyEnvironmentErrorObject *env_err;
728
729 if (eintr_int == NULL) {
730 eintr_int = PyLong_FromLong(EINTR);
731 assert(eintr_int != NULL);
732 }
733 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
734 return 0;
735 PyErr_Fetch(&typ, &val, &tb);
736 PyErr_NormalizeException(&typ, &val, &tb);
737 env_err = (PyEnvironmentErrorObject *) val;
738 assert(env_err != NULL);
739 if (env_err->myerrno != NULL &&
740 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
741 Py_DECREF(typ);
742 Py_DECREF(val);
743 Py_XDECREF(tb);
744 return 1;
745 }
746 /* This silences any error set by PyObject_RichCompareBool() */
747 PyErr_Restore(typ, val, tb);
748 return 0;
749}
750
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000751/*
752 * Shared methods and wrappers
753 */
754
755static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000756buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000757{
758 PyObject *res;
759
760 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000761 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000762
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000763 if (!ENTER_BUFFERED(self))
764 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000765 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000766 if (res != NULL && self->readable) {
767 /* Rewind the raw stream so that its position corresponds to
768 the current logical position. */
769 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000770 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000771 if (n == -1)
772 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000773 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000774 }
775 LEAVE_BUFFERED(self)
776
777 return res;
778}
779
780static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000781buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000782{
783 Py_ssize_t n = 0;
784 PyObject *res = NULL;
785
786 CHECK_INITIALIZED(self)
787 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
788 return NULL;
789 }
790
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000791 if (!ENTER_BUFFERED(self))
792 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000793
794 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000795 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000796 if (res == NULL)
797 goto end;
798 Py_CLEAR(res);
799 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000800 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000801
802end:
803 LEAVE_BUFFERED(self)
804 return res;
805}
806
807static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000808buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000809{
810 Py_ssize_t n = -1;
811 PyObject *res;
812
813 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000814 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000815 return NULL;
816 }
817 if (n < -1) {
818 PyErr_SetString(PyExc_ValueError,
819 "read length must be positive or -1");
820 return NULL;
821 }
822
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000823 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000824
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000825 if (n == -1) {
826 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000827 if (!ENTER_BUFFERED(self))
828 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000829 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000830 LEAVE_BUFFERED(self)
831 }
832 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000833 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000834 if (res == Py_None) {
835 Py_DECREF(res);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000836 if (!ENTER_BUFFERED(self))
837 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000838 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000839 LEAVE_BUFFERED(self)
840 }
841 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000842
843 return res;
844}
845
846static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000847buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000848{
849 Py_ssize_t n, have, r;
850 PyObject *res = NULL;
851
852 CHECK_INITIALIZED(self)
853 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
854 return NULL;
855 }
856
857 if (n < 0) {
858 PyErr_SetString(PyExc_ValueError,
859 "read length must be positive");
860 return NULL;
861 }
862 if (n == 0)
863 return PyBytes_FromStringAndSize(NULL, 0);
864
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000865 if (!ENTER_BUFFERED(self))
866 return NULL;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200867
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000868 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000869 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000870 if (res == NULL)
871 goto end;
872 Py_CLEAR(res);
873 }
874
875 /* Return up to n bytes. If at least one byte is buffered, we
876 only return buffered bytes. Otherwise, we do one raw read. */
877
878 /* XXX: this mimicks the io.py implementation but is probably wrong.
879 If we need to read from the raw stream, then we could actually read
880 all `n` bytes asked by the caller (and possibly more, so as to fill
881 our buffer for the next reads). */
882
883 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
884 if (have > 0) {
885 if (n > have)
886 n = have;
887 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
888 if (res == NULL)
889 goto end;
890 self->pos += n;
891 goto end;
892 }
893
894 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000895 _bufferedreader_reset_buf(self);
896 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000897 if (r == -1)
898 goto end;
899 if (r == -2)
900 r = 0;
901 if (n > r)
902 n = r;
903 res = PyBytes_FromStringAndSize(self->buffer, n);
904 if (res == NULL)
905 goto end;
906 self->pos = n;
907
908end:
909 LEAVE_BUFFERED(self)
910 return res;
911}
912
913static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000914buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000915{
Antoine Pitrou3486a982011-05-12 01:57:53 +0200916 Py_buffer buf;
917 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000918 PyObject *res = NULL;
919
920 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +0200921
922 if (!PyArg_ParseTuple(args, "w*:readinto", &buf))
923 return NULL;
924
925 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
926 if (n > 0) {
927 if (n >= buf.len) {
928 memcpy(buf.buf, self->buffer + self->pos, buf.len);
929 self->pos += buf.len;
930 res = PyLong_FromSsize_t(buf.len);
931 goto end_unlocked;
932 }
933 memcpy(buf.buf, self->buffer + self->pos, n);
934 self->pos += n;
935 written = n;
936 }
937
938 if (!ENTER_BUFFERED(self))
939 goto end_unlocked;
940
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000941 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000942 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000943 if (res == NULL)
944 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200945 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000946 }
Antoine Pitrou3486a982011-05-12 01:57:53 +0200947
948 _bufferedreader_reset_buf(self);
949 self->pos = 0;
950
951 for (remaining = buf.len - written;
952 remaining > 0;
953 written += n, remaining -= n) {
954 /* If remaining bytes is larger than internal buffer size, copy
955 * directly into caller's buffer. */
956 if (remaining > self->buffer_size) {
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200957 n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
958 remaining);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200959 }
960 else {
961 n = _bufferedreader_fill_buffer(self);
962 if (n > 0) {
963 if (n > remaining)
964 n = remaining;
Antoine Pitrou4e19e112011-05-12 02:07:00 +0200965 memcpy((char *) buf.buf + written,
966 self->buffer + self->pos, n);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200967 self->pos += n;
968 continue; /* short circuit */
969 }
970 }
971 if (n == 0 || (n == -2 && written > 0))
972 break;
973 if (n < 0) {
974 if (n == -2) {
975 Py_INCREF(Py_None);
976 res = Py_None;
977 }
978 goto end;
979 }
980 }
981 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000982
983end:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200984 LEAVE_BUFFERED(self);
985end_unlocked:
986 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000987 return res;
988}
989
990static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000991_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000992{
993 PyObject *res = NULL;
994 PyObject *chunks = NULL;
995 Py_ssize_t n, written = 0;
996 const char *start, *s, *end;
997
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000998 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000999
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001000 /* First, try to find a line in the buffer. This can run unlocked because
1001 the calls to the C API are simple enough that they can't trigger
1002 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001003 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1004 if (limit >= 0 && n > limit)
1005 n = limit;
1006 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001007 s = memchr(start, '\n', n);
1008 if (s != NULL) {
1009 res = PyBytes_FromStringAndSize(start, s - start + 1);
1010 if (res != NULL)
1011 self->pos += s - start + 1;
1012 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001013 }
1014 if (n == limit) {
1015 res = PyBytes_FromStringAndSize(start, n);
1016 if (res != NULL)
1017 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001018 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001019 }
1020
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001021 if (!ENTER_BUFFERED(self))
1022 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001023
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001024 /* Now we try to get some more from the raw stream */
1025 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001026 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001027 if (res == NULL)
1028 goto end;
1029 Py_CLEAR(res);
1030 }
1031 chunks = PyList_New(0);
1032 if (chunks == NULL)
1033 goto end;
1034 if (n > 0) {
1035 res = PyBytes_FromStringAndSize(start, n);
1036 if (res == NULL)
1037 goto end;
1038 if (PyList_Append(chunks, res) < 0) {
1039 Py_CLEAR(res);
1040 goto end;
1041 }
1042 Py_CLEAR(res);
1043 written += n;
1044 if (limit >= 0)
1045 limit -= n;
1046 }
1047
1048 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001049 _bufferedreader_reset_buf(self);
1050 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001051 if (n == -1)
1052 goto end;
1053 if (n <= 0)
1054 break;
1055 if (limit >= 0 && n > limit)
1056 n = limit;
1057 start = self->buffer;
1058 end = start + n;
1059 s = start;
1060 while (s < end) {
1061 if (*s++ == '\n') {
1062 res = PyBytes_FromStringAndSize(start, s - start);
1063 if (res == NULL)
1064 goto end;
1065 self->pos = s - start;
1066 goto found;
1067 }
1068 }
1069 res = PyBytes_FromStringAndSize(start, n);
1070 if (res == NULL)
1071 goto end;
1072 if (n == limit) {
1073 self->pos = n;
1074 break;
1075 }
1076 if (PyList_Append(chunks, res) < 0) {
1077 Py_CLEAR(res);
1078 goto end;
1079 }
1080 Py_CLEAR(res);
1081 written += n;
1082 if (limit >= 0)
1083 limit -= n;
1084 }
1085found:
1086 if (res != NULL && PyList_Append(chunks, res) < 0) {
1087 Py_CLEAR(res);
1088 goto end;
1089 }
1090 Py_CLEAR(res);
1091 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1092
1093end:
1094 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001095end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001096 Py_XDECREF(chunks);
1097 return res;
1098}
1099
1100static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001101buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001102{
1103 Py_ssize_t limit = -1;
1104
1105 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001106 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001107 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001108 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001109}
1110
1111
1112static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001113buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001114{
1115 Py_off_t pos;
1116
1117 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001118 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001119 if (pos == -1)
1120 return NULL;
1121 pos -= RAW_OFFSET(self);
1122 /* TODO: sanity check (pos >= 0) */
1123 return PyLong_FromOff_t(pos);
1124}
1125
1126static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001127buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001128{
1129 Py_off_t target, n;
1130 int whence = 0;
1131 PyObject *targetobj, *res = NULL;
1132
1133 CHECK_INITIALIZED(self)
1134 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1135 return NULL;
1136 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001137 if (whence < 0 || whence > 2) {
1138 PyErr_Format(PyExc_ValueError,
1139 "whence must be between 0 and 2, not %d", whence);
1140 return NULL;
1141 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001142
1143 CHECK_CLOSED(self, "seek of closed file")
1144
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001145 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1146 if (target == -1 && PyErr_Occurred())
1147 return NULL;
1148
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001149 if (whence != 2 && self->readable) {
1150 Py_off_t current, avail;
1151 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001152 so as to return quickly if possible. Also, we needn't take the
1153 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001154 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001155 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1156 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001157 current = RAW_TELL(self);
1158 avail = READAHEAD(self);
1159 if (avail > 0) {
1160 Py_off_t offset;
1161 if (whence == 0)
1162 offset = target - (current - RAW_OFFSET(self));
1163 else
1164 offset = target;
1165 if (offset >= -self->pos && offset <= avail) {
1166 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001167 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001168 }
1169 }
1170 }
1171
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001172 if (!ENTER_BUFFERED(self))
1173 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001174
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001175 /* Fallback: invoke raw seek() method and clear buffer */
1176 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001177 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001178 if (res == NULL)
1179 goto end;
1180 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001181 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001182 }
1183
1184 /* TODO: align on block boundary and read buffer if needed? */
1185 if (whence == 1)
1186 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001187 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001188 if (n == -1)
1189 goto end;
1190 self->raw_pos = -1;
1191 res = PyLong_FromOff_t(n);
1192 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001193 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001194
1195end:
1196 LEAVE_BUFFERED(self)
1197 return res;
1198}
1199
1200static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001201buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001202{
1203 PyObject *pos = Py_None;
1204 PyObject *res = NULL;
1205
1206 CHECK_INITIALIZED(self)
1207 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1208 return NULL;
1209 }
1210
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001211 if (!ENTER_BUFFERED(self))
1212 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001213
1214 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001215 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001216 if (res == NULL)
1217 goto end;
1218 Py_CLEAR(res);
1219 }
1220 if (self->readable) {
1221 if (pos == Py_None) {
1222 /* Rewind the raw stream so that its position corresponds to
1223 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001224 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001225 goto end;
1226 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001227 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001228 }
1229 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1230 if (res == NULL)
1231 goto end;
1232 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001233 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001234 PyErr_Clear();
1235
1236end:
1237 LEAVE_BUFFERED(self)
1238 return res;
1239}
1240
1241static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001242buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001243{
1244 PyObject *line;
1245 PyTypeObject *tp;
1246
1247 CHECK_INITIALIZED(self);
1248
1249 tp = Py_TYPE(self);
1250 if (tp == &PyBufferedReader_Type ||
1251 tp == &PyBufferedRandom_Type) {
1252 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001253 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001254 }
1255 else {
1256 line = PyObject_CallMethodObjArgs((PyObject *)self,
1257 _PyIO_str_readline, NULL);
1258 if (line && !PyBytes_Check(line)) {
1259 PyErr_Format(PyExc_IOError,
1260 "readline() should have returned a bytes object, "
1261 "not '%.200s'", Py_TYPE(line)->tp_name);
1262 Py_DECREF(line);
1263 return NULL;
1264 }
1265 }
1266
1267 if (line == NULL)
1268 return NULL;
1269
1270 if (PyBytes_GET_SIZE(line) == 0) {
1271 /* Reached EOF or would have blocked */
1272 Py_DECREF(line);
1273 return NULL;
1274 }
1275
1276 return line;
1277}
1278
Antoine Pitrou716c4442009-05-23 19:04:03 +00001279static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001280buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001281{
1282 PyObject *nameobj, *res;
1283
1284 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1285 if (nameobj == NULL) {
1286 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1287 PyErr_Clear();
1288 else
1289 return NULL;
1290 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1291 }
1292 else {
1293 res = PyUnicode_FromFormat("<%s name=%R>",
1294 Py_TYPE(self)->tp_name, nameobj);
1295 Py_DECREF(nameobj);
1296 }
1297 return res;
1298}
1299
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001300/*
1301 * class BufferedReader
1302 */
1303
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001304PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001305 "Create a new buffered reader using the given readable raw IO object.");
1306
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001307static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001308{
1309 self->read_end = -1;
1310}
1311
1312static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001313bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001314{
1315 char *kwlist[] = {"raw", "buffer_size", NULL};
1316 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1317 PyObject *raw;
1318
1319 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001320 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001321
1322 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1323 &raw, &buffer_size)) {
1324 return -1;
1325 }
1326
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001327 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001328 return -1;
1329
1330 Py_CLEAR(self->raw);
1331 Py_INCREF(raw);
1332 self->raw = raw;
1333 self->buffer_size = buffer_size;
1334 self->readable = 1;
1335 self->writable = 0;
1336
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001337 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001338 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001339 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001340
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001341 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1342 Py_TYPE(raw) == &PyFileIO_Type);
1343
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001344 self->ok = 1;
1345 return 0;
1346}
1347
1348static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001349_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001350{
1351 Py_buffer buf;
1352 PyObject *memobj, *res;
1353 Py_ssize_t n;
1354 /* NOTE: the buffer needn't be released as its object is NULL. */
1355 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1356 return -1;
1357 memobj = PyMemoryView_FromBuffer(&buf);
1358 if (memobj == NULL)
1359 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001360 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1361 occurs so we needn't do it ourselves.
1362 We then retry reading, ignoring the signal if no handler has
1363 raised (see issue #10956).
1364 */
1365 do {
1366 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1367 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001368 Py_DECREF(memobj);
1369 if (res == NULL)
1370 return -1;
1371 if (res == Py_None) {
1372 /* Non-blocking stream would have blocked. Special return code! */
1373 Py_DECREF(res);
1374 return -2;
1375 }
1376 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1377 Py_DECREF(res);
1378 if (n < 0 || n > len) {
1379 PyErr_Format(PyExc_IOError,
1380 "raw readinto() returned invalid length %zd "
1381 "(should have been between 0 and %zd)", n, len);
1382 return -1;
1383 }
1384 if (n > 0 && self->abs_pos != -1)
1385 self->abs_pos += n;
1386 return n;
1387}
1388
1389static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001390_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001391{
1392 Py_ssize_t start, len, n;
1393 if (VALID_READ_BUFFER(self))
1394 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1395 else
1396 start = 0;
1397 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001398 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001399 if (n <= 0)
1400 return n;
1401 self->read_end = start + n;
1402 self->raw_pos = start + n;
1403 return n;
1404}
1405
1406static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001407_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001408{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001409 Py_ssize_t current_size;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001410 PyObject *res, *data = NULL, *chunk, *chunks;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001411
1412 /* First copy what we have in the current buffer. */
1413 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1414 if (current_size) {
1415 data = PyBytes_FromStringAndSize(
1416 self->buffer + self->pos, current_size);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001417 if (data == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001418 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001419 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001420 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001421 /* We're going past the buffer's bounds, flush it */
1422 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001423 res = _bufferedwriter_flush_unlocked(self, 1);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001424 if (res == NULL)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001425 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001426 Py_CLEAR(res);
1427 }
Victor Stinnerb57f1082011-05-26 00:19:38 +02001428
1429 if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
1430 chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
1431 if (chunk == NULL)
1432 return NULL;
1433 if (chunk != Py_None && !PyBytes_Check(chunk)) {
1434 Py_XDECREF(data);
1435 Py_DECREF(chunk);
1436 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1437 return NULL;
1438 }
1439 if (chunk == Py_None) {
1440 if (current_size == 0)
1441 return chunk;
1442 else {
1443 Py_DECREF(chunk);
1444 return data;
1445 }
1446 }
1447 else if (current_size) {
1448 PyBytes_Concat(&data, chunk);
1449 Py_DECREF(chunk);
1450 if (data == NULL)
1451 return NULL;
1452 return data;
1453 } else
1454 return chunk;
1455 }
1456
1457 chunks = PyList_New(0);
1458 if (chunks == NULL)
1459 return NULL;
1460
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001461 while (1) {
1462 if (data) {
1463 if (PyList_Append(chunks, data) < 0) {
1464 Py_DECREF(data);
1465 Py_DECREF(chunks);
1466 return NULL;
1467 }
1468 Py_DECREF(data);
1469 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001470
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001471 /* Read until EOF or until read() would block. */
1472 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1473 if (data == NULL) {
1474 Py_DECREF(chunks);
1475 return NULL;
1476 }
1477 if (data != Py_None && !PyBytes_Check(data)) {
1478 Py_DECREF(data);
1479 Py_DECREF(chunks);
1480 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1481 return NULL;
1482 }
1483 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1484 if (current_size == 0) {
1485 Py_DECREF(chunks);
1486 return data;
1487 }
1488 else {
1489 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1490 Py_DECREF(data);
1491 Py_DECREF(chunks);
1492 return res;
1493 }
1494 }
1495 current_size += PyBytes_GET_SIZE(data);
1496 if (self->abs_pos != -1)
1497 self->abs_pos += PyBytes_GET_SIZE(data);
1498 }
1499}
1500
1501/* Read n bytes from the buffer if it can, otherwise return None.
1502 This function is simple enough that it can run unlocked. */
1503static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001504_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001505{
1506 Py_ssize_t current_size;
1507
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001508 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1509 if (n <= current_size) {
1510 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001511 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1512 if (res != NULL)
1513 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001514 return res;
1515 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001516 Py_RETURN_NONE;
1517}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001518
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001519/* Generic read function: read from the stream until enough bytes are read,
1520 * or until an EOF occurs or until read() would block.
1521 */
1522static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001523_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001524{
1525 PyObject *res = NULL;
1526 Py_ssize_t current_size, remaining, written;
1527 char *out;
1528
1529 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1530 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001531 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001532
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001533 res = PyBytes_FromStringAndSize(NULL, n);
1534 if (res == NULL)
1535 goto error;
1536 out = PyBytes_AS_STRING(res);
1537 remaining = n;
1538 written = 0;
1539 if (current_size > 0) {
1540 memcpy(out, self->buffer + self->pos, current_size);
1541 remaining -= current_size;
1542 written += current_size;
1543 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001544 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001545 while (remaining > 0) {
1546 /* We want to read a whole block at the end into buffer.
1547 If we had readv() we could do this in one pass. */
1548 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1549 if (r == 0)
1550 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001551 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001552 if (r == -1)
1553 goto error;
1554 if (r == 0 || r == -2) {
1555 /* EOF occurred or read() would block. */
1556 if (r == 0 || written > 0) {
1557 if (_PyBytes_Resize(&res, written))
1558 goto error;
1559 return res;
1560 }
1561 Py_DECREF(res);
1562 Py_INCREF(Py_None);
1563 return Py_None;
1564 }
1565 remaining -= r;
1566 written += r;
1567 }
1568 assert(remaining <= self->buffer_size);
1569 self->pos = 0;
1570 self->raw_pos = 0;
1571 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001572 /* NOTE: when the read is satisfied, we avoid issuing any additional
1573 reads, which could block indefinitely (e.g. on a socket).
1574 See issue #9550. */
1575 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001576 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001577 if (r == -1)
1578 goto error;
1579 if (r == 0 || r == -2) {
1580 /* EOF occurred or read() would block. */
1581 if (r == 0 || written > 0) {
1582 if (_PyBytes_Resize(&res, written))
1583 goto error;
1584 return res;
1585 }
1586 Py_DECREF(res);
1587 Py_INCREF(Py_None);
1588 return Py_None;
1589 }
1590 if (remaining > r) {
1591 memcpy(out + written, self->buffer + self->pos, r);
1592 written += r;
1593 self->pos += r;
1594 remaining -= r;
1595 }
1596 else if (remaining > 0) {
1597 memcpy(out + written, self->buffer + self->pos, remaining);
1598 written += remaining;
1599 self->pos += remaining;
1600 remaining = 0;
1601 }
1602 if (remaining == 0)
1603 break;
1604 }
1605
1606 return res;
1607
1608error:
1609 Py_XDECREF(res);
1610 return NULL;
1611}
1612
1613static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001614_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001615{
1616 Py_ssize_t have, r;
1617
1618 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1619 /* Constraints:
1620 1. we don't want to advance the file position.
1621 2. we don't want to lose block alignment, so we can't shift the buffer
1622 to make some place.
1623 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1624 */
1625 if (have > 0) {
1626 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1627 }
1628
1629 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001630 _bufferedreader_reset_buf(self);
1631 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001632 if (r == -1)
1633 return NULL;
1634 if (r == -2)
1635 r = 0;
1636 self->pos = 0;
1637 return PyBytes_FromStringAndSize(self->buffer, r);
1638}
1639
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001640static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001641 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001642 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1643 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1644 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1645 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1646 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1647 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1648 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1649 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001650 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001651 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001652
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001653 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1654 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1655 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001656 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001657 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1658 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1659 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1660 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001661 {NULL, NULL}
1662};
1663
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001664static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001665 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001666 {NULL}
1667};
1668
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001669static PyGetSetDef bufferedreader_getset[] = {
1670 {"closed", (getter)buffered_closed_get, NULL, NULL},
1671 {"name", (getter)buffered_name_get, NULL, NULL},
1672 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001673 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001674};
1675
1676
1677PyTypeObject PyBufferedReader_Type = {
1678 PyVarObject_HEAD_INIT(NULL, 0)
1679 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001680 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001681 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001682 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001683 0, /*tp_print*/
1684 0, /*tp_getattr*/
1685 0, /*tp_setattr*/
1686 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001687 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001688 0, /*tp_as_number*/
1689 0, /*tp_as_sequence*/
1690 0, /*tp_as_mapping*/
1691 0, /*tp_hash */
1692 0, /*tp_call*/
1693 0, /*tp_str*/
1694 0, /*tp_getattro*/
1695 0, /*tp_setattro*/
1696 0, /*tp_as_buffer*/
1697 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1698 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001699 bufferedreader_doc, /* tp_doc */
1700 (traverseproc)buffered_traverse, /* tp_traverse */
1701 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001702 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001703 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001704 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001705 (iternextfunc)buffered_iternext, /* tp_iternext */
1706 bufferedreader_methods, /* tp_methods */
1707 bufferedreader_members, /* tp_members */
1708 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001709 0, /* tp_base */
1710 0, /* tp_dict */
1711 0, /* tp_descr_get */
1712 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001713 offsetof(buffered, dict), /* tp_dictoffset */
1714 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001715 0, /* tp_alloc */
1716 PyType_GenericNew, /* tp_new */
1717};
1718
1719
Benjamin Peterson59406a92009-03-26 17:10:29 +00001720
1721static int
1722complain_about_max_buffer_size(void)
1723{
1724 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1725 "max_buffer_size is deprecated", 1) < 0)
1726 return 0;
1727 return 1;
1728}
1729
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001730/*
1731 * class BufferedWriter
1732 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001733PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001734 "A buffer for a writeable sequential RawIO object.\n"
1735 "\n"
1736 "The constructor creates a BufferedWriter for the given writeable raw\n"
1737 "stream. If the buffer_size is not given, it defaults to\n"
1738 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1739 );
1740
1741static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001742_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001743{
1744 self->write_pos = 0;
1745 self->write_end = -1;
1746}
1747
1748static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001749bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001750{
1751 /* TODO: properly deprecate max_buffer_size */
1752 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1753 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001754 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001755 PyObject *raw;
1756
1757 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001758 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001759
1760 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1761 &raw, &buffer_size, &max_buffer_size)) {
1762 return -1;
1763 }
1764
Benjamin Peterson59406a92009-03-26 17:10:29 +00001765 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1766 return -1;
1767
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001768 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001769 return -1;
1770
1771 Py_CLEAR(self->raw);
1772 Py_INCREF(raw);
1773 self->raw = raw;
1774 self->readable = 0;
1775 self->writable = 1;
1776
1777 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001778 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001779 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001780 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001781 self->pos = 0;
1782
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001783 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1784 Py_TYPE(raw) == &PyFileIO_Type);
1785
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001786 self->ok = 1;
1787 return 0;
1788}
1789
1790static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001791_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001792{
1793 Py_buffer buf;
1794 PyObject *memobj, *res;
1795 Py_ssize_t n;
1796 /* NOTE: the buffer needn't be released as its object is NULL. */
1797 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1798 return -1;
1799 memobj = PyMemoryView_FromBuffer(&buf);
1800 if (memobj == NULL)
1801 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001802 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1803 occurs so we needn't do it ourselves.
1804 We then retry writing, ignoring the signal if no handler has
1805 raised (see issue #10956).
1806 */
1807 do {
1808 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1809 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001810 Py_DECREF(memobj);
1811 if (res == NULL)
1812 return -1;
1813 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1814 Py_DECREF(res);
1815 if (n < 0 || n > len) {
1816 PyErr_Format(PyExc_IOError,
1817 "raw write() returned invalid length %zd "
1818 "(should have been between 0 and %zd)", n, len);
1819 return -1;
1820 }
1821 if (n > 0 && self->abs_pos != -1)
1822 self->abs_pos += n;
1823 return n;
1824}
1825
1826/* `restore_pos` is 1 if we need to restore the raw stream position at
1827 the end, 0 otherwise. */
1828static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001829_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001830{
1831 Py_ssize_t written = 0;
1832 Py_off_t n, rewind;
1833
1834 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1835 goto end;
1836 /* First, rewind */
1837 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1838 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001839 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001840 if (n < 0) {
1841 goto error;
1842 }
1843 self->raw_pos -= rewind;
1844 }
1845 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001846 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001847 self->buffer + self->write_pos,
1848 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1849 Py_off_t, Py_ssize_t));
1850 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001851 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001852 if (w == NULL)
1853 goto error;
1854 self->write_pos += *w;
1855 self->raw_pos = self->write_pos;
1856 written += *w;
1857 *w = written;
1858 /* Already re-raised */
1859 goto error;
1860 }
1861 self->write_pos += n;
1862 self->raw_pos = self->write_pos;
1863 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001864 /* Partial writes can return successfully when interrupted by a
1865 signal (see write(2)). We must run signal handlers before
1866 blocking another time, possibly indefinitely. */
1867 if (PyErr_CheckSignals() < 0)
1868 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001869 }
1870
1871 if (restore_pos) {
1872 Py_off_t forward = rewind - written;
1873 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001874 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001875 if (n < 0) {
1876 goto error;
1877 }
1878 self->raw_pos += forward;
1879 }
1880 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001881 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001882
1883end:
1884 Py_RETURN_NONE;
1885
1886error:
1887 return NULL;
1888}
1889
1890static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001891bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001892{
1893 PyObject *res = NULL;
1894 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001895 Py_ssize_t written, avail, remaining;
1896 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001897
1898 CHECK_INITIALIZED(self)
1899 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1900 return NULL;
1901 }
1902
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001903 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001904 PyErr_SetString(PyExc_ValueError, "write to closed file");
1905 PyBuffer_Release(&buf);
1906 return NULL;
1907 }
1908
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001909 if (!ENTER_BUFFERED(self)) {
1910 PyBuffer_Release(&buf);
1911 return NULL;
1912 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001913
1914 /* Fast path: the data to write can be fully buffered. */
1915 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1916 self->pos = 0;
1917 self->raw_pos = 0;
1918 }
1919 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1920 if (buf.len <= avail) {
1921 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02001922 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001923 self->write_pos = self->pos;
1924 }
1925 ADJUST_POSITION(self, self->pos + buf.len);
1926 if (self->pos > self->write_end)
1927 self->write_end = self->pos;
1928 written = buf.len;
1929 goto end;
1930 }
1931
1932 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001933 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001934 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001935 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001936 if (w == NULL)
1937 goto error;
1938 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001939 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001940 /* Make some place by shifting the buffer. */
1941 assert(VALID_WRITE_BUFFER(self));
1942 memmove(self->buffer, self->buffer + self->write_pos,
1943 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1944 Py_off_t, Py_ssize_t));
1945 self->write_end -= self->write_pos;
1946 self->raw_pos -= self->write_pos;
1947 self->pos -= self->write_pos;
1948 self->write_pos = 0;
1949 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1950 Py_off_t, Py_ssize_t);
1951 if (buf.len <= avail) {
1952 /* Everything can be buffered */
1953 PyErr_Clear();
1954 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1955 self->write_end += buf.len;
1956 written = buf.len;
1957 goto end;
1958 }
1959 /* Buffer as much as possible. */
1960 memcpy(self->buffer + self->write_end, buf.buf, avail);
1961 self->write_end += avail;
1962 /* Already re-raised */
1963 *w = avail;
1964 goto error;
1965 }
1966 Py_CLEAR(res);
1967
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001968 /* Adjust the raw stream position if it is away from the logical stream
1969 position. This happens if the read buffer has been filled but not
1970 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1971 the raw stream by itself).
1972 Fixes issue #6629.
1973 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001974 offset = RAW_OFFSET(self);
1975 if (offset != 0) {
1976 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001977 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001978 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001979 }
1980
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001981 /* Then write buf itself. At this point the buffer has been emptied. */
1982 remaining = buf.len;
1983 written = 0;
1984 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001985 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001986 self, (char *) buf.buf + written, buf.len - written);
1987 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001988 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001989 if (w == NULL)
1990 goto error;
1991 written += *w;
1992 remaining -= *w;
1993 if (remaining > self->buffer_size) {
1994 /* Can't buffer everything, still buffer as much as possible */
1995 memcpy(self->buffer,
1996 (char *) buf.buf + written, self->buffer_size);
1997 self->raw_pos = 0;
1998 ADJUST_POSITION(self, self->buffer_size);
1999 self->write_end = self->buffer_size;
2000 *w = written + self->buffer_size;
2001 /* Already re-raised */
2002 goto error;
2003 }
2004 PyErr_Clear();
2005 break;
2006 }
2007 written += n;
2008 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002009 /* Partial writes can return successfully when interrupted by a
2010 signal (see write(2)). We must run signal handlers before
2011 blocking another time, possibly indefinitely. */
2012 if (PyErr_CheckSignals() < 0)
2013 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002014 }
2015 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002016 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002017 if (remaining > 0) {
2018 memcpy(self->buffer, (char *) buf.buf + written, remaining);
2019 written += remaining;
2020 }
2021 self->write_pos = 0;
2022 /* TODO: sanity check (remaining >= 0) */
2023 self->write_end = remaining;
2024 ADJUST_POSITION(self, remaining);
2025 self->raw_pos = 0;
2026
2027end:
2028 res = PyLong_FromSsize_t(written);
2029
2030error:
2031 LEAVE_BUFFERED(self)
2032 PyBuffer_Release(&buf);
2033 return res;
2034}
2035
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002036static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002037 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002038 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2039 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2040 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2041 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2042 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2043 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2044 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002045 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002046 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002047
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002048 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2049 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2050 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2051 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2052 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002053 {NULL, NULL}
2054};
2055
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002056static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002057 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002058 {NULL}
2059};
2060
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002061static PyGetSetDef bufferedwriter_getset[] = {
2062 {"closed", (getter)buffered_closed_get, NULL, NULL},
2063 {"name", (getter)buffered_name_get, NULL, NULL},
2064 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002065 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002066};
2067
2068
2069PyTypeObject PyBufferedWriter_Type = {
2070 PyVarObject_HEAD_INIT(NULL, 0)
2071 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002072 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002073 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002074 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002075 0, /*tp_print*/
2076 0, /*tp_getattr*/
2077 0, /*tp_setattr*/
2078 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002079 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002080 0, /*tp_as_number*/
2081 0, /*tp_as_sequence*/
2082 0, /*tp_as_mapping*/
2083 0, /*tp_hash */
2084 0, /*tp_call*/
2085 0, /*tp_str*/
2086 0, /*tp_getattro*/
2087 0, /*tp_setattro*/
2088 0, /*tp_as_buffer*/
2089 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2090 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002091 bufferedwriter_doc, /* tp_doc */
2092 (traverseproc)buffered_traverse, /* tp_traverse */
2093 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002094 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002095 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002096 0, /* tp_iter */
2097 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002098 bufferedwriter_methods, /* tp_methods */
2099 bufferedwriter_members, /* tp_members */
2100 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002101 0, /* tp_base */
2102 0, /* tp_dict */
2103 0, /* tp_descr_get */
2104 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002105 offsetof(buffered, dict), /* tp_dictoffset */
2106 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002107 0, /* tp_alloc */
2108 PyType_GenericNew, /* tp_new */
2109};
2110
2111
2112
2113/*
2114 * BufferedRWPair
2115 */
2116
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002117PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002118 "A buffered reader and writer object together.\n"
2119 "\n"
2120 "A buffered reader object and buffered writer object put together to\n"
2121 "form a sequential IO object that can read and write. This is typically\n"
2122 "used with a socket or two-way pipe.\n"
2123 "\n"
2124 "reader and writer are RawIOBase objects that are readable and\n"
2125 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002126 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002127 );
2128
2129/* XXX The usefulness of this (compared to having two separate IO objects) is
2130 * questionable.
2131 */
2132
2133typedef struct {
2134 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002135 buffered *reader;
2136 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002137 PyObject *dict;
2138 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002139} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002140
2141static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002142bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002143{
2144 PyObject *reader, *writer;
2145 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002146 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002147
2148 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2149 &buffer_size, &max_buffer_size)) {
2150 return -1;
2151 }
2152
Benjamin Peterson59406a92009-03-26 17:10:29 +00002153 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2154 return -1;
2155
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002156 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002157 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002158 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002159 return -1;
2160
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002161 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002162 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002163 if (self->reader == NULL)
2164 return -1;
2165
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002166 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002167 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002168 if (self->writer == NULL) {
2169 Py_CLEAR(self->reader);
2170 return -1;
2171 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002172
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002173 return 0;
2174}
2175
2176static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002177bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002178{
2179 Py_VISIT(self->dict);
2180 return 0;
2181}
2182
2183static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002184bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002185{
2186 Py_CLEAR(self->reader);
2187 Py_CLEAR(self->writer);
2188 Py_CLEAR(self->dict);
2189 return 0;
2190}
2191
2192static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002193bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002194{
2195 _PyObject_GC_UNTRACK(self);
2196 Py_CLEAR(self->reader);
2197 Py_CLEAR(self->writer);
2198 Py_CLEAR(self->dict);
2199 Py_TYPE(self)->tp_free((PyObject *) self);
2200}
2201
2202static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002203_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002204{
2205 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2206 PyObject *ret;
2207
2208 if (func == NULL) {
2209 PyErr_SetString(PyExc_AttributeError, name);
2210 return NULL;
2211 }
2212
2213 ret = PyObject_CallObject(func, args);
2214 Py_DECREF(func);
2215 return ret;
2216}
2217
2218static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002219bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002220{
2221 return _forward_call(self->reader, "read", args);
2222}
2223
2224static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002225bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002226{
2227 return _forward_call(self->reader, "peek", args);
2228}
2229
2230static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002231bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002232{
2233 return _forward_call(self->reader, "read1", args);
2234}
2235
2236static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002237bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002238{
2239 return _forward_call(self->reader, "readinto", args);
2240}
2241
2242static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002243bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002244{
2245 return _forward_call(self->writer, "write", args);
2246}
2247
2248static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002249bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002250{
2251 return _forward_call(self->writer, "flush", args);
2252}
2253
2254static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002255bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002256{
2257 return _forward_call(self->reader, "readable", args);
2258}
2259
2260static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002261bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002262{
2263 return _forward_call(self->writer, "writable", args);
2264}
2265
2266static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002267bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002268{
2269 PyObject *ret = _forward_call(self->writer, "close", args);
2270 if (ret == NULL)
2271 return NULL;
2272 Py_DECREF(ret);
2273
2274 return _forward_call(self->reader, "close", args);
2275}
2276
2277static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002278bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002279{
2280 PyObject *ret = _forward_call(self->writer, "isatty", args);
2281
2282 if (ret != Py_False) {
2283 /* either True or exception */
2284 return ret;
2285 }
2286 Py_DECREF(ret);
2287
2288 return _forward_call(self->reader, "isatty", args);
2289}
2290
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002291static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002292bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002293{
2294 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2295}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002296
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002297static PyMethodDef bufferedrwpair_methods[] = {
2298 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2299 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2300 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2301 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002302
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002303 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2304 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002305
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002306 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2307 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002308
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002309 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2310 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002311
Antoine Pitrou243757e2010-11-05 21:15:39 +00002312 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2313
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002314 {NULL, NULL}
2315};
2316
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002317static PyGetSetDef bufferedrwpair_getset[] = {
2318 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002319 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002320};
2321
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002322PyTypeObject PyBufferedRWPair_Type = {
2323 PyVarObject_HEAD_INIT(NULL, 0)
2324 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002325 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002326 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002327 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002328 0, /*tp_print*/
2329 0, /*tp_getattr*/
2330 0, /*tp_setattr*/
2331 0, /*tp_compare */
2332 0, /*tp_repr*/
2333 0, /*tp_as_number*/
2334 0, /*tp_as_sequence*/
2335 0, /*tp_as_mapping*/
2336 0, /*tp_hash */
2337 0, /*tp_call*/
2338 0, /*tp_str*/
2339 0, /*tp_getattro*/
2340 0, /*tp_setattro*/
2341 0, /*tp_as_buffer*/
2342 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2343 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002344 bufferedrwpair_doc, /* tp_doc */
2345 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2346 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002347 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002348 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002349 0, /* tp_iter */
2350 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002351 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002352 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002353 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002354 0, /* tp_base */
2355 0, /* tp_dict */
2356 0, /* tp_descr_get */
2357 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002358 offsetof(rwpair, dict), /* tp_dictoffset */
2359 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002360 0, /* tp_alloc */
2361 PyType_GenericNew, /* tp_new */
2362};
2363
2364
2365
2366/*
2367 * BufferedRandom
2368 */
2369
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002370PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002371 "A buffered interface to random access streams.\n"
2372 "\n"
2373 "The constructor creates a reader and writer for a seekable stream,\n"
2374 "raw, given in the first argument. If the buffer_size is omitted it\n"
2375 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2376 );
2377
2378static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002379bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002380{
2381 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2382 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002383 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002384 PyObject *raw;
2385
2386 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002387 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002388
2389 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2390 &raw, &buffer_size, &max_buffer_size)) {
2391 return -1;
2392 }
2393
Benjamin Peterson59406a92009-03-26 17:10:29 +00002394 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2395 return -1;
2396
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002397 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002398 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002399 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002400 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002401 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002402 return -1;
2403
2404 Py_CLEAR(self->raw);
2405 Py_INCREF(raw);
2406 self->raw = raw;
2407 self->buffer_size = buffer_size;
2408 self->readable = 1;
2409 self->writable = 1;
2410
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002411 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002412 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002413 _bufferedreader_reset_buf(self);
2414 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002415 self->pos = 0;
2416
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002417 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2418 Py_TYPE(raw) == &PyFileIO_Type);
2419
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002420 self->ok = 1;
2421 return 0;
2422}
2423
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002424static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002425 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002426 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2427 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2428 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2429 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2430 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2431 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2432 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002433 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002434 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002435
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002436 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002437
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002438 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2439 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2440 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2441 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2442 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2443 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2444 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2445 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2446 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002447 {NULL, NULL}
2448};
2449
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002450static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002451 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002452 {NULL}
2453};
2454
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002455static PyGetSetDef bufferedrandom_getset[] = {
2456 {"closed", (getter)buffered_closed_get, NULL, NULL},
2457 {"name", (getter)buffered_name_get, NULL, NULL},
2458 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002459 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002460};
2461
2462
2463PyTypeObject PyBufferedRandom_Type = {
2464 PyVarObject_HEAD_INIT(NULL, 0)
2465 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002466 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002467 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002468 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002469 0, /*tp_print*/
2470 0, /*tp_getattr*/
2471 0, /*tp_setattr*/
2472 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002473 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002474 0, /*tp_as_number*/
2475 0, /*tp_as_sequence*/
2476 0, /*tp_as_mapping*/
2477 0, /*tp_hash */
2478 0, /*tp_call*/
2479 0, /*tp_str*/
2480 0, /*tp_getattro*/
2481 0, /*tp_setattro*/
2482 0, /*tp_as_buffer*/
2483 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2484 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002485 bufferedrandom_doc, /* tp_doc */
2486 (traverseproc)buffered_traverse, /* tp_traverse */
2487 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002488 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002489 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002490 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002491 (iternextfunc)buffered_iternext, /* tp_iternext */
2492 bufferedrandom_methods, /* tp_methods */
2493 bufferedrandom_members, /* tp_members */
2494 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002495 0, /* tp_base */
2496 0, /*tp_dict*/
2497 0, /* tp_descr_get */
2498 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002499 offsetof(buffered, dict), /*tp_dictoffset*/
2500 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002501 0, /* tp_alloc */
2502 PyType_GenericNew, /* tp_new */
2503};