blob: a8278d466ce1d25bc8c4a7458bf1cbe5a25d5824 [file] [log] [blame]
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001/*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
3
4 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
6
7 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8*/
9
10#define PY_SSIZE_T_CLEAN
11#include "Python.h"
12#include "structmember.h"
13#include "pythread.h"
14#include "_iomodule.h"
15
16/*
17 * BufferedIOBase class, inherits from IOBase.
18 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000019PyDoc_STRVAR(bufferediobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000020 "Base class for buffered IO objects.\n"
21 "\n"
22 "The main difference with RawIOBase is that the read() method\n"
23 "supports omitting the size argument, and does not have a default\n"
24 "implementation that defers to readinto().\n"
25 "\n"
26 "In addition, read(), readinto() and write() may raise\n"
27 "BlockingIOError if the underlying raw stream is in non-blocking\n"
28 "mode and not ready; unlike their raw counterparts, they will never\n"
29 "return None.\n"
30 "\n"
31 "A typical implementation should not inherit from a RawIOBase\n"
32 "implementation, but wrap one.\n"
33 );
34
35static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000036bufferediobase_readinto(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000037{
38 Py_buffer buf;
39 Py_ssize_t len;
40 PyObject *data;
41
42 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
43 return NULL;
44 }
45
46 data = PyObject_CallMethod(self, "read", "n", buf.len);
47 if (data == NULL)
48 goto error;
49
50 if (!PyBytes_Check(data)) {
51 Py_DECREF(data);
52 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
53 goto error;
54 }
55
56 len = Py_SIZE(data);
57 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
58
59 PyBuffer_Release(&buf);
60 Py_DECREF(data);
61
62 return PyLong_FromSsize_t(len);
63
64 error:
65 PyBuffer_Release(&buf);
66 return NULL;
67}
68
69static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000070bufferediobase_unsupported(const char *message)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000071{
72 PyErr_SetString(IO_STATE->unsupported_operation, message);
73 return NULL;
74}
75
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000076PyDoc_STRVAR(bufferediobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +000077 "Disconnect this buffer from its underlying raw stream and return it.\n"
78 "\n"
79 "After the raw stream has been detached, the buffer is in an unusable\n"
80 "state.\n");
81
82static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000083bufferediobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +000084{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000085 return bufferediobase_unsupported("detach");
Benjamin Petersond2e0c792009-05-01 20:40:59 +000086}
87
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000088PyDoc_STRVAR(bufferediobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000089 "Read and return up to n bytes.\n"
90 "\n"
91 "If the argument is omitted, None, or negative, reads and\n"
92 "returns all data until EOF.\n"
93 "\n"
94 "If the argument is positive, and the underlying raw stream is\n"
95 "not 'interactive', multiple raw reads may be issued to satisfy\n"
96 "the byte count (unless EOF is reached first). But for\n"
97 "interactive raw streams (as well as sockets and pipes), at most\n"
98 "one raw read will be issued, and a short result does not imply\n"
99 "that EOF is imminent.\n"
100 "\n"
101 "Returns an empty bytes object on EOF.\n"
102 "\n"
103 "Returns None if the underlying raw stream was open in non-blocking\n"
104 "mode and no data is available at the moment.\n");
105
106static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000107bufferediobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000108{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000109 return bufferediobase_unsupported("read");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000110}
111
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000112PyDoc_STRVAR(bufferediobase_read1_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000113 "Read and return up to n bytes, with at most one read() call\n"
114 "to the underlying raw stream. A short result does not imply\n"
115 "that EOF is imminent.\n"
116 "\n"
117 "Returns an empty bytes object on EOF.\n");
118
119static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000120bufferediobase_read1(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000121{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000122 return bufferediobase_unsupported("read1");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000123}
124
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000125PyDoc_STRVAR(bufferediobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000126 "Write the given buffer to the IO stream.\n"
127 "\n"
128 "Returns the number of bytes written, which is never less than\n"
129 "len(b).\n"
130 "\n"
131 "Raises BlockingIOError if the buffer is full and the\n"
132 "underlying raw stream cannot accept more data at the moment.\n");
133
134static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000135bufferediobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000136{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000137 return bufferediobase_unsupported("write");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000138}
139
140
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000141static PyMethodDef bufferediobase_methods[] = {
142 {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
143 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
144 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
145 {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
146 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000147 {NULL, NULL}
148};
149
150PyTypeObject PyBufferedIOBase_Type = {
151 PyVarObject_HEAD_INIT(NULL, 0)
152 "_io._BufferedIOBase", /*tp_name*/
153 0, /*tp_basicsize*/
154 0, /*tp_itemsize*/
155 0, /*tp_dealloc*/
156 0, /*tp_print*/
157 0, /*tp_getattr*/
158 0, /*tp_setattr*/
159 0, /*tp_compare */
160 0, /*tp_repr*/
161 0, /*tp_as_number*/
162 0, /*tp_as_sequence*/
163 0, /*tp_as_mapping*/
164 0, /*tp_hash */
165 0, /*tp_call*/
166 0, /*tp_str*/
167 0, /*tp_getattro*/
168 0, /*tp_setattro*/
169 0, /*tp_as_buffer*/
170 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000171 bufferediobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000172 0, /* tp_traverse */
173 0, /* tp_clear */
174 0, /* tp_richcompare */
175 0, /* tp_weaklistoffset */
176 0, /* tp_iter */
177 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000178 bufferediobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000179 0, /* tp_members */
180 0, /* tp_getset */
181 &PyIOBase_Type, /* tp_base */
182 0, /* tp_dict */
183 0, /* tp_descr_get */
184 0, /* tp_descr_set */
185 0, /* tp_dictoffset */
186 0, /* tp_init */
187 0, /* tp_alloc */
188 0, /* tp_new */
189};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000190
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000191
192typedef struct {
193 PyObject_HEAD
194
195 PyObject *raw;
196 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000197 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000198 int readable;
199 int writable;
Antoine Pitroue033e062010-10-29 10:38:18 +0000200 int deallocating;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000201
202 /* 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:
240
241 * 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.
258
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
Antoine Pitrou10f0c502012-07-29 19:02:46 +0200386static PyObject *
387buffered_sizeof(buffered *self, void *unused)
388{
389 Py_ssize_t res;
390
391 res = sizeof(buffered);
392 if (self->buffer)
393 res += self->buffer_size;
394 return PyLong_FromSsize_t(res);
395}
396
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000397static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000398buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000399{
400 Py_VISIT(self->raw);
401 Py_VISIT(self->dict);
402 return 0;
403}
404
405static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000406buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000407{
408 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
409 return -1;
410 self->ok = 0;
411 Py_CLEAR(self->raw);
412 Py_CLEAR(self->dict);
413 return 0;
414}
415
Antoine Pitroue033e062010-10-29 10:38:18 +0000416/* Because this can call arbitrary code, it shouldn't be called when
417 the refcount is 0 (that is, not directly from tp_dealloc unless
418 the refcount has been temporarily re-incremented). */
Matthias Klosebee33162010-11-16 20:07:51 +0000419static PyObject *
Antoine Pitroue033e062010-10-29 10:38:18 +0000420buffered_dealloc_warn(buffered *self, PyObject *source)
421{
422 if (self->ok && self->raw) {
423 PyObject *r;
424 r = PyObject_CallMethod(self->raw, "_dealloc_warn", "O", source);
425 if (r)
426 Py_DECREF(r);
427 else
428 PyErr_Clear();
429 }
430 Py_RETURN_NONE;
431}
432
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000433/*
434 * _BufferedIOMixin methods
435 * This is not a class, just a collection of methods that will be reused
436 * by BufferedReader and BufferedWriter
437 */
438
439/* Flush and close */
440
441static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000442buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000443{
444 CHECK_INITIALIZED(self)
445 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
446}
447
448static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000449buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000450{
451 int closed;
452 PyObject *res;
453 CHECK_INITIALIZED_INT(self)
454 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
455 if (res == NULL)
456 return -1;
457 closed = PyObject_IsTrue(res);
458 Py_DECREF(res);
459 return closed;
460}
461
462static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000463buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000464{
465 CHECK_INITIALIZED(self)
466 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
467}
468
469static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000470buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000471{
472 PyObject *res = NULL;
473 int r;
474
475 CHECK_INITIALIZED(self)
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000476 if (!ENTER_BUFFERED(self))
477 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000478
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000479 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000480 if (r < 0)
481 goto end;
482 if (r > 0) {
483 res = Py_None;
484 Py_INCREF(res);
485 goto end;
486 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000487
488 if (self->deallocating) {
489 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
490 if (r)
491 Py_DECREF(r);
492 else
493 PyErr_Clear();
494 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000495 /* flush() will most probably re-take the lock, so drop it first */
496 LEAVE_BUFFERED(self)
497 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000498 if (!ENTER_BUFFERED(self))
499 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000500 if (res == NULL) {
Antoine Pitrou6be88762010-05-03 16:48:20 +0000501 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000502 }
503 Py_XDECREF(res);
504
505 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
506
507end:
508 LEAVE_BUFFERED(self)
509 return res;
510}
511
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000512/* detach */
513
514static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000515buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000516{
517 PyObject *raw, *res;
518 CHECK_INITIALIZED(self)
519 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
520 if (res == NULL)
521 return NULL;
522 Py_DECREF(res);
523 raw = self->raw;
524 self->raw = NULL;
525 self->detached = 1;
526 self->ok = 0;
527 return raw;
528}
529
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000530/* Inquiries */
531
532static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000533buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000534{
535 CHECK_INITIALIZED(self)
536 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
537}
538
539static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000540buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000541{
542 CHECK_INITIALIZED(self)
543 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
544}
545
546static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000547buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000548{
549 CHECK_INITIALIZED(self)
550 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
551}
552
553static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000554buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000555{
556 CHECK_INITIALIZED(self)
557 return PyObject_GetAttrString(self->raw, "name");
558}
559
560static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000561buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000562{
563 CHECK_INITIALIZED(self)
564 return PyObject_GetAttrString(self->raw, "mode");
565}
566
567/* Lower-level APIs */
568
569static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000570buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000571{
572 CHECK_INITIALIZED(self)
573 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
574}
575
576static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000577buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000578{
579 CHECK_INITIALIZED(self)
580 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
581}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000582
Antoine Pitrou243757e2010-11-05 21:15:39 +0000583/* Serialization */
584
585static PyObject *
586buffered_getstate(buffered *self, PyObject *args)
587{
588 PyErr_Format(PyExc_TypeError,
589 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
590 return NULL;
591}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000592
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000593/* Forward decls */
594static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100595_bufferedwriter_flush_unlocked(buffered *);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000596static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000597_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000598static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000599_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000600static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000601_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000602static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000603_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000604static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000605_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000606static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000607_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000608static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000609_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000610
611
612/*
613 * Helpers
614 */
615
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100616/* Sets the current error to BlockingIOError */
617static void
618_set_BlockingIOError(char *msg, Py_ssize_t written)
619{
620 PyObject *err;
621 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
622 errno, msg, written);
623 if (err)
624 PyErr_SetObject(PyExc_BlockingIOError, err);
625 Py_XDECREF(err);
626}
627
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000628/* Returns the address of the `written` member if a BlockingIOError was
629 raised, NULL otherwise. The error is always re-raised. */
630static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000631_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000632{
633 PyObject *t, *v, *tb;
634 PyBlockingIOErrorObject *err;
635
636 PyErr_Fetch(&t, &v, &tb);
637 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
638 PyErr_Restore(t, v, tb);
639 return NULL;
640 }
641 err = (PyBlockingIOErrorObject *) v;
642 /* TODO: sanity check (err->written >= 0) */
643 PyErr_Restore(t, v, tb);
644 return &err->written;
645}
646
647static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000648_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000649{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000650 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000651 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000652 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
653 if (res == NULL)
654 return -1;
655 n = PyNumber_AsOff_t(res, PyExc_ValueError);
656 Py_DECREF(res);
657 if (n < 0) {
658 if (!PyErr_Occurred())
659 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000660 "Raw stream returned invalid position %" PY_PRIdOFF,
661 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000662 return -1;
663 }
664 self->abs_pos = n;
665 return n;
666}
667
668static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000669_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000670{
671 PyObject *res, *posobj, *whenceobj;
672 Py_off_t n;
673
674 posobj = PyLong_FromOff_t(target);
675 if (posobj == NULL)
676 return -1;
677 whenceobj = PyLong_FromLong(whence);
678 if (whenceobj == NULL) {
679 Py_DECREF(posobj);
680 return -1;
681 }
682 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
683 posobj, whenceobj, NULL);
684 Py_DECREF(posobj);
685 Py_DECREF(whenceobj);
686 if (res == NULL)
687 return -1;
688 n = PyNumber_AsOff_t(res, PyExc_ValueError);
689 Py_DECREF(res);
690 if (n < 0) {
691 if (!PyErr_Occurred())
692 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000693 "Raw stream returned invalid position %" PY_PRIdOFF,
694 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000695 return -1;
696 }
697 self->abs_pos = n;
698 return n;
699}
700
701static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000702_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000703{
704 Py_ssize_t n;
705 if (self->buffer_size <= 0) {
706 PyErr_SetString(PyExc_ValueError,
707 "buffer size must be strictly positive");
708 return -1;
709 }
710 if (self->buffer)
711 PyMem_Free(self->buffer);
712 self->buffer = PyMem_Malloc(self->buffer_size);
713 if (self->buffer == NULL) {
714 PyErr_NoMemory();
715 return -1;
716 }
Georg Brandldfd73442009-04-05 11:47:34 +0000717#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000718 if (self->lock)
719 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000720 self->lock = PyThread_allocate_lock();
721 if (self->lock == NULL) {
722 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
723 return -1;
724 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000725 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000726#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000727 /* Find out whether buffer_size is a power of 2 */
728 /* XXX is this optimization useful? */
729 for (n = self->buffer_size - 1; n & 1; n >>= 1)
730 ;
731 if (n == 0)
732 self->buffer_mask = self->buffer_size - 1;
733 else
734 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000735 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000736 PyErr_Clear();
737 return 0;
738}
739
Antoine Pitroud843c2d2011-02-25 21:34:39 +0000740/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
741 clears the error indicator), 0 otherwise.
742 Should only be called when PyErr_Occurred() is true.
743*/
Gregory P. Smith51359922012-06-23 23:55:39 -0700744int
745_PyIO_trap_eintr(void)
Antoine Pitroud843c2d2011-02-25 21:34:39 +0000746{
747 static PyObject *eintr_int = NULL;
748 PyObject *typ, *val, *tb;
749 PyEnvironmentErrorObject *env_err;
750
751 if (eintr_int == NULL) {
752 eintr_int = PyLong_FromLong(EINTR);
753 assert(eintr_int != NULL);
754 }
755 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
756 return 0;
757 PyErr_Fetch(&typ, &val, &tb);
758 PyErr_NormalizeException(&typ, &val, &tb);
759 env_err = (PyEnvironmentErrorObject *) val;
760 assert(env_err != NULL);
761 if (env_err->myerrno != NULL &&
762 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
763 Py_DECREF(typ);
764 Py_DECREF(val);
765 Py_XDECREF(tb);
766 return 1;
767 }
768 /* This silences any error set by PyObject_RichCompareBool() */
769 PyErr_Restore(typ, val, tb);
770 return 0;
771}
772
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000773/*
774 * Shared methods and wrappers
775 */
776
777static PyObject *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200778buffered_flush_and_rewind_unlocked(buffered *self)
779{
780 PyObject *res;
781
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100782 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200783 if (res == NULL)
784 return NULL;
785 Py_DECREF(res);
786
787 if (self->readable) {
788 /* Rewind the raw stream so that its position corresponds to
789 the current logical position. */
790 Py_off_t n;
791 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
792 _bufferedreader_reset_buf(self);
793 if (n == -1)
794 return NULL;
795 }
796 Py_RETURN_NONE;
797}
798
799static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000800buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000801{
802 PyObject *res;
803
804 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000805 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000806
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000807 if (!ENTER_BUFFERED(self))
808 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200809 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000810 LEAVE_BUFFERED(self)
811
812 return res;
813}
814
815static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000816buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000817{
818 Py_ssize_t n = 0;
819 PyObject *res = NULL;
820
821 CHECK_INITIALIZED(self)
822 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
823 return NULL;
824 }
825
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000826 if (!ENTER_BUFFERED(self))
827 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000828
829 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200830 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000831 if (res == NULL)
832 goto end;
833 Py_CLEAR(res);
834 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000835 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000836
837end:
838 LEAVE_BUFFERED(self)
839 return res;
840}
841
842static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000843buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000844{
845 Py_ssize_t n = -1;
846 PyObject *res;
847
848 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000849 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000850 return NULL;
851 }
852 if (n < -1) {
853 PyErr_SetString(PyExc_ValueError,
854 "read length must be positive or -1");
855 return NULL;
856 }
857
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000858 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000859
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000860 if (n == -1) {
861 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000862 if (!ENTER_BUFFERED(self))
863 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000864 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000865 }
866 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000867 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200868 if (res != Py_None)
869 return res;
870 Py_DECREF(res);
871 if (!ENTER_BUFFERED(self))
872 return NULL;
873 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000874 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000875
Antoine Pitroue05565e2011-08-20 14:39:23 +0200876 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000877 return res;
878}
879
880static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000881buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000882{
883 Py_ssize_t n, have, r;
884 PyObject *res = NULL;
885
886 CHECK_INITIALIZED(self)
887 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
888 return NULL;
889 }
890
891 if (n < 0) {
892 PyErr_SetString(PyExc_ValueError,
893 "read length must be positive");
894 return NULL;
895 }
896 if (n == 0)
897 return PyBytes_FromStringAndSize(NULL, 0);
898
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000899 if (!ENTER_BUFFERED(self))
900 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000901
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000902 /* Return up to n bytes. If at least one byte is buffered, we
903 only return buffered bytes. Otherwise, we do one raw read. */
904
905 /* XXX: this mimicks the io.py implementation but is probably wrong.
906 If we need to read from the raw stream, then we could actually read
907 all `n` bytes asked by the caller (and possibly more, so as to fill
908 our buffer for the next reads). */
909
910 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
911 if (have > 0) {
912 if (n > have)
913 n = have;
914 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
915 if (res == NULL)
916 goto end;
917 self->pos += n;
918 goto end;
919 }
920
Antoine Pitroue05565e2011-08-20 14:39:23 +0200921 if (self->writable) {
922 res = buffered_flush_and_rewind_unlocked(self);
923 if (res == NULL)
924 goto end;
925 Py_DECREF(res);
926 }
927
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000928 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000929 _bufferedreader_reset_buf(self);
930 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000931 if (r == -1)
932 goto end;
933 if (r == -2)
934 r = 0;
935 if (n > r)
936 n = r;
937 res = PyBytes_FromStringAndSize(self->buffer, n);
938 if (res == NULL)
939 goto end;
940 self->pos = n;
941
942end:
943 LEAVE_BUFFERED(self)
944 return res;
945}
946
947static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000948buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000949{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000950 CHECK_INITIALIZED(self)
951
Antoine Pitroue05565e2011-08-20 14:39:23 +0200952 /* TODO: use raw.readinto() (or a direct copy from our buffer) instead! */
953 return bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000954}
955
956static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000957_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000958{
959 PyObject *res = NULL;
960 PyObject *chunks = NULL;
961 Py_ssize_t n, written = 0;
962 const char *start, *s, *end;
963
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000964 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000965
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000966 /* First, try to find a line in the buffer. This can run unlocked because
967 the calls to the C API are simple enough that they can't trigger
968 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000969 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
970 if (limit >= 0 && n > limit)
971 n = limit;
972 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000973 s = memchr(start, '\n', n);
974 if (s != NULL) {
975 res = PyBytes_FromStringAndSize(start, s - start + 1);
976 if (res != NULL)
977 self->pos += s - start + 1;
978 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000979 }
980 if (n == limit) {
981 res = PyBytes_FromStringAndSize(start, n);
982 if (res != NULL)
983 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000984 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000985 }
986
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000987 if (!ENTER_BUFFERED(self))
988 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000989
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000990 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000991 chunks = PyList_New(0);
992 if (chunks == NULL)
993 goto end;
994 if (n > 0) {
995 res = PyBytes_FromStringAndSize(start, n);
996 if (res == NULL)
997 goto end;
998 if (PyList_Append(chunks, res) < 0) {
999 Py_CLEAR(res);
1000 goto end;
1001 }
1002 Py_CLEAR(res);
1003 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001004 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001005 if (limit >= 0)
1006 limit -= n;
1007 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001008 if (self->writable) {
1009 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1010 if (r == NULL)
1011 goto end;
1012 Py_DECREF(r);
1013 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001014
1015 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001016 _bufferedreader_reset_buf(self);
1017 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001018 if (n == -1)
1019 goto end;
1020 if (n <= 0)
1021 break;
1022 if (limit >= 0 && n > limit)
1023 n = limit;
1024 start = self->buffer;
1025 end = start + n;
1026 s = start;
1027 while (s < end) {
1028 if (*s++ == '\n') {
1029 res = PyBytes_FromStringAndSize(start, s - start);
1030 if (res == NULL)
1031 goto end;
1032 self->pos = s - start;
1033 goto found;
1034 }
1035 }
1036 res = PyBytes_FromStringAndSize(start, n);
1037 if (res == NULL)
1038 goto end;
1039 if (n == limit) {
1040 self->pos = n;
1041 break;
1042 }
1043 if (PyList_Append(chunks, res) < 0) {
1044 Py_CLEAR(res);
1045 goto end;
1046 }
1047 Py_CLEAR(res);
1048 written += n;
1049 if (limit >= 0)
1050 limit -= n;
1051 }
1052found:
1053 if (res != NULL && PyList_Append(chunks, res) < 0) {
1054 Py_CLEAR(res);
1055 goto end;
1056 }
1057 Py_CLEAR(res);
1058 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1059
1060end:
1061 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001062end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001063 Py_XDECREF(chunks);
1064 return res;
1065}
1066
1067static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001068buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001069{
1070 Py_ssize_t limit = -1;
1071
1072 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001073 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001074 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001075 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001076}
1077
1078
1079static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001080buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001081{
1082 Py_off_t pos;
1083
1084 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001085 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001086 if (pos == -1)
1087 return NULL;
1088 pos -= RAW_OFFSET(self);
1089 /* TODO: sanity check (pos >= 0) */
1090 return PyLong_FromOff_t(pos);
1091}
1092
1093static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001094buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001095{
1096 Py_off_t target, n;
1097 int whence = 0;
1098 PyObject *targetobj, *res = NULL;
1099
1100 CHECK_INITIALIZED(self)
1101 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1102 return NULL;
1103 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001104 if (whence < 0 || whence > 2) {
1105 PyErr_Format(PyExc_ValueError,
1106 "whence must be between 0 and 2, not %d", whence);
1107 return NULL;
1108 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001109
1110 CHECK_CLOSED(self, "seek of closed file")
1111
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001112 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1113 return NULL;
1114
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001115 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1116 if (target == -1 && PyErr_Occurred())
1117 return NULL;
1118
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001119 if (whence != 2 && self->readable) {
1120 Py_off_t current, avail;
1121 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001122 so as to return quickly if possible. Also, we needn't take the
1123 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001124 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001125 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1126 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001127 current = RAW_TELL(self);
1128 avail = READAHEAD(self);
1129 if (avail > 0) {
1130 Py_off_t offset;
1131 if (whence == 0)
1132 offset = target - (current - RAW_OFFSET(self));
1133 else
1134 offset = target;
1135 if (offset >= -self->pos && offset <= avail) {
1136 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001137 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001138 }
1139 }
1140 }
1141
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001142 if (!ENTER_BUFFERED(self))
1143 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001144
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001145 /* Fallback: invoke raw seek() method and clear buffer */
1146 if (self->writable) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001147 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001148 if (res == NULL)
1149 goto end;
1150 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001151 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001152 }
1153
1154 /* TODO: align on block boundary and read buffer if needed? */
1155 if (whence == 1)
1156 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001157 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001158 if (n == -1)
1159 goto end;
1160 self->raw_pos = -1;
1161 res = PyLong_FromOff_t(n);
1162 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001163 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001164
1165end:
1166 LEAVE_BUFFERED(self)
1167 return res;
1168}
1169
1170static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001171buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001172{
1173 PyObject *pos = Py_None;
1174 PyObject *res = NULL;
1175
1176 CHECK_INITIALIZED(self)
1177 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1178 return NULL;
1179 }
1180
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001181 if (!ENTER_BUFFERED(self))
1182 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001183
1184 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001185 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001186 if (res == NULL)
1187 goto end;
1188 Py_CLEAR(res);
1189 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001190 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1191 if (res == NULL)
1192 goto end;
1193 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001194 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001195 PyErr_Clear();
1196
1197end:
1198 LEAVE_BUFFERED(self)
1199 return res;
1200}
1201
1202static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001203buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001204{
1205 PyObject *line;
1206 PyTypeObject *tp;
1207
1208 CHECK_INITIALIZED(self);
1209
1210 tp = Py_TYPE(self);
1211 if (tp == &PyBufferedReader_Type ||
1212 tp == &PyBufferedRandom_Type) {
1213 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001214 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001215 }
1216 else {
1217 line = PyObject_CallMethodObjArgs((PyObject *)self,
1218 _PyIO_str_readline, NULL);
1219 if (line && !PyBytes_Check(line)) {
1220 PyErr_Format(PyExc_IOError,
1221 "readline() should have returned a bytes object, "
1222 "not '%.200s'", Py_TYPE(line)->tp_name);
1223 Py_DECREF(line);
1224 return NULL;
1225 }
1226 }
1227
1228 if (line == NULL)
1229 return NULL;
1230
1231 if (PyBytes_GET_SIZE(line) == 0) {
1232 /* Reached EOF or would have blocked */
1233 Py_DECREF(line);
1234 return NULL;
1235 }
1236
1237 return line;
1238}
1239
Antoine Pitrou716c4442009-05-23 19:04:03 +00001240static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001241buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001242{
1243 PyObject *nameobj, *res;
1244
1245 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1246 if (nameobj == NULL) {
1247 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1248 PyErr_Clear();
1249 else
1250 return NULL;
1251 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1252 }
1253 else {
1254 res = PyUnicode_FromFormat("<%s name=%R>",
1255 Py_TYPE(self)->tp_name, nameobj);
1256 Py_DECREF(nameobj);
1257 }
1258 return res;
1259}
1260
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001261/*
1262 * class BufferedReader
1263 */
1264
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001265PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001266 "Create a new buffered reader using the given readable raw IO object.");
1267
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001268static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001269{
1270 self->read_end = -1;
1271}
1272
1273static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001274bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001275{
1276 char *kwlist[] = {"raw", "buffer_size", NULL};
1277 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1278 PyObject *raw;
1279
1280 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001281 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001282
1283 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1284 &raw, &buffer_size)) {
1285 return -1;
1286 }
1287
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001288 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001289 return -1;
1290
1291 Py_CLEAR(self->raw);
1292 Py_INCREF(raw);
1293 self->raw = raw;
1294 self->buffer_size = buffer_size;
1295 self->readable = 1;
1296 self->writable = 0;
1297
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001298 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001299 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001300 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001301
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001302 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1303 Py_TYPE(raw) == &PyFileIO_Type);
1304
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001305 self->ok = 1;
1306 return 0;
1307}
1308
1309static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001310_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001311{
1312 Py_buffer buf;
1313 PyObject *memobj, *res;
1314 Py_ssize_t n;
1315 /* NOTE: the buffer needn't be released as its object is NULL. */
1316 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1317 return -1;
1318 memobj = PyMemoryView_FromBuffer(&buf);
1319 if (memobj == NULL)
1320 return -1;
Antoine Pitroud843c2d2011-02-25 21:34:39 +00001321 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1322 occurs so we needn't do it ourselves.
1323 We then retry reading, ignoring the signal if no handler has
1324 raised (see issue #10956).
1325 */
1326 do {
1327 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
Gregory P. Smith51359922012-06-23 23:55:39 -07001328 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001329 Py_DECREF(memobj);
1330 if (res == NULL)
1331 return -1;
1332 if (res == Py_None) {
1333 /* Non-blocking stream would have blocked. Special return code! */
1334 Py_DECREF(res);
1335 return -2;
1336 }
1337 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1338 Py_DECREF(res);
1339 if (n < 0 || n > len) {
1340 PyErr_Format(PyExc_IOError,
1341 "raw readinto() returned invalid length %zd "
1342 "(should have been between 0 and %zd)", n, len);
1343 return -1;
1344 }
1345 if (n > 0 && self->abs_pos != -1)
1346 self->abs_pos += n;
1347 return n;
1348}
1349
1350static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001351_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001352{
1353 Py_ssize_t start, len, n;
1354 if (VALID_READ_BUFFER(self))
1355 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1356 else
1357 start = 0;
1358 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001359 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001360 if (n <= 0)
1361 return n;
1362 self->read_end = start + n;
1363 self->raw_pos = start + n;
1364 return n;
1365}
1366
1367static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001368_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001369{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001370 Py_ssize_t current_size;
1371 PyObject *res, *data = NULL;
1372 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001373
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001374 if (chunks == NULL)
1375 return NULL;
1376
1377 /* First copy what we have in the current buffer. */
1378 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1379 if (current_size) {
1380 data = PyBytes_FromStringAndSize(
1381 self->buffer + self->pos, current_size);
1382 if (data == NULL) {
1383 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001384 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001385 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001386 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001387 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001388 /* We're going past the buffer's bounds, flush it */
1389 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001390 res = buffered_flush_and_rewind_unlocked(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001391 if (res == NULL) {
1392 Py_DECREF(chunks);
1393 return NULL;
1394 }
1395 Py_CLEAR(res);
1396 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001397 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001398 while (1) {
1399 if (data) {
1400 if (PyList_Append(chunks, data) < 0) {
1401 Py_DECREF(data);
1402 Py_DECREF(chunks);
1403 return NULL;
1404 }
1405 Py_DECREF(data);
1406 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001407
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001408 /* Read until EOF or until read() would block. */
1409 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1410 if (data == NULL) {
1411 Py_DECREF(chunks);
1412 return NULL;
1413 }
1414 if (data != Py_None && !PyBytes_Check(data)) {
1415 Py_DECREF(data);
1416 Py_DECREF(chunks);
1417 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1418 return NULL;
1419 }
1420 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1421 if (current_size == 0) {
1422 Py_DECREF(chunks);
1423 return data;
1424 }
1425 else {
1426 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1427 Py_DECREF(data);
1428 Py_DECREF(chunks);
1429 return res;
1430 }
1431 }
1432 current_size += PyBytes_GET_SIZE(data);
1433 if (self->abs_pos != -1)
1434 self->abs_pos += PyBytes_GET_SIZE(data);
1435 }
1436}
1437
1438/* Read n bytes from the buffer if it can, otherwise return None.
1439 This function is simple enough that it can run unlocked. */
1440static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001441_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001442{
1443 Py_ssize_t current_size;
1444
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001445 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1446 if (n <= current_size) {
1447 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001448 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1449 if (res != NULL)
1450 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001451 return res;
1452 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001453 Py_RETURN_NONE;
1454}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001455
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001456/* Generic read function: read from the stream until enough bytes are read,
1457 * or until an EOF occurs or until read() would block.
1458 */
1459static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001460_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001461{
1462 PyObject *res = NULL;
1463 Py_ssize_t current_size, remaining, written;
1464 char *out;
1465
1466 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1467 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001468 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001469
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001470 res = PyBytes_FromStringAndSize(NULL, n);
1471 if (res == NULL)
1472 goto error;
1473 out = PyBytes_AS_STRING(res);
1474 remaining = n;
1475 written = 0;
1476 if (current_size > 0) {
1477 memcpy(out, self->buffer + self->pos, current_size);
1478 remaining -= current_size;
1479 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001480 self->pos += current_size;
1481 }
1482 /* Flush the write buffer if necessary */
1483 if (self->writable) {
1484 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1485 if (r == NULL)
1486 goto error;
1487 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001488 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001489 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001490 while (remaining > 0) {
1491 /* We want to read a whole block at the end into buffer.
1492 If we had readv() we could do this in one pass. */
1493 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1494 if (r == 0)
1495 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001496 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001497 if (r == -1)
1498 goto error;
1499 if (r == 0 || r == -2) {
1500 /* EOF occurred or read() would block. */
1501 if (r == 0 || written > 0) {
1502 if (_PyBytes_Resize(&res, written))
1503 goto error;
1504 return res;
1505 }
1506 Py_DECREF(res);
1507 Py_INCREF(Py_None);
1508 return Py_None;
1509 }
1510 remaining -= r;
1511 written += r;
1512 }
1513 assert(remaining <= self->buffer_size);
1514 self->pos = 0;
1515 self->raw_pos = 0;
1516 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001517 /* NOTE: when the read is satisfied, we avoid issuing any additional
1518 reads, which could block indefinitely (e.g. on a socket).
1519 See issue #9550. */
1520 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001521 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001522 if (r == -1)
1523 goto error;
1524 if (r == 0 || r == -2) {
1525 /* EOF occurred or read() would block. */
1526 if (r == 0 || written > 0) {
1527 if (_PyBytes_Resize(&res, written))
1528 goto error;
1529 return res;
1530 }
1531 Py_DECREF(res);
1532 Py_INCREF(Py_None);
1533 return Py_None;
1534 }
1535 if (remaining > r) {
1536 memcpy(out + written, self->buffer + self->pos, r);
1537 written += r;
1538 self->pos += r;
1539 remaining -= r;
1540 }
1541 else if (remaining > 0) {
1542 memcpy(out + written, self->buffer + self->pos, remaining);
1543 written += remaining;
1544 self->pos += remaining;
1545 remaining = 0;
1546 }
1547 if (remaining == 0)
1548 break;
1549 }
1550
1551 return res;
1552
1553error:
1554 Py_XDECREF(res);
1555 return NULL;
1556}
1557
1558static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001559_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001560{
1561 Py_ssize_t have, r;
1562
1563 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1564 /* Constraints:
1565 1. we don't want to advance the file position.
1566 2. we don't want to lose block alignment, so we can't shift the buffer
1567 to make some place.
1568 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1569 */
1570 if (have > 0) {
1571 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1572 }
1573
1574 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001575 _bufferedreader_reset_buf(self);
1576 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001577 if (r == -1)
1578 return NULL;
1579 if (r == -2)
1580 r = 0;
1581 self->pos = 0;
1582 return PyBytes_FromStringAndSize(self->buffer, r);
1583}
1584
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001585static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001586 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001587 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1588 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1589 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1590 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1591 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1592 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1593 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1594 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001595 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001596 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001597
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001598 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1599 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1600 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1601 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1602 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1603 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1604 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02001605 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001606 {NULL, NULL}
1607};
1608
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001609static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001610 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001611 {NULL}
1612};
1613
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001614static PyGetSetDef bufferedreader_getset[] = {
1615 {"closed", (getter)buffered_closed_get, NULL, NULL},
1616 {"name", (getter)buffered_name_get, NULL, NULL},
1617 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001618 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001619};
1620
1621
1622PyTypeObject PyBufferedReader_Type = {
1623 PyVarObject_HEAD_INIT(NULL, 0)
1624 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001625 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001626 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001627 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001628 0, /*tp_print*/
1629 0, /*tp_getattr*/
1630 0, /*tp_setattr*/
1631 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001632 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001633 0, /*tp_as_number*/
1634 0, /*tp_as_sequence*/
1635 0, /*tp_as_mapping*/
1636 0, /*tp_hash */
1637 0, /*tp_call*/
1638 0, /*tp_str*/
1639 0, /*tp_getattro*/
1640 0, /*tp_setattro*/
1641 0, /*tp_as_buffer*/
1642 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1643 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001644 bufferedreader_doc, /* tp_doc */
1645 (traverseproc)buffered_traverse, /* tp_traverse */
1646 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001647 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001648 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001649 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001650 (iternextfunc)buffered_iternext, /* tp_iternext */
1651 bufferedreader_methods, /* tp_methods */
1652 bufferedreader_members, /* tp_members */
1653 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001654 0, /* tp_base */
1655 0, /* tp_dict */
1656 0, /* tp_descr_get */
1657 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001658 offsetof(buffered, dict), /* tp_dictoffset */
1659 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001660 0, /* tp_alloc */
1661 PyType_GenericNew, /* tp_new */
1662};
1663
1664
Benjamin Peterson59406a92009-03-26 17:10:29 +00001665
1666static int
1667complain_about_max_buffer_size(void)
1668{
1669 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1670 "max_buffer_size is deprecated", 1) < 0)
1671 return 0;
1672 return 1;
1673}
1674
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001675/*
1676 * class BufferedWriter
1677 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001678PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001679 "A buffer for a writeable sequential RawIO object.\n"
1680 "\n"
1681 "The constructor creates a BufferedWriter for the given writeable raw\n"
1682 "stream. If the buffer_size is not given, it defaults to\n"
1683 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1684 );
1685
1686static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001687_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001688{
1689 self->write_pos = 0;
1690 self->write_end = -1;
1691}
1692
1693static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001694bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001695{
1696 /* TODO: properly deprecate max_buffer_size */
1697 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1698 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001699 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001700 PyObject *raw;
1701
1702 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001703 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001704
R David Murray67bfe802013-02-23 21:51:05 -05001705 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedWriter", kwlist,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001706 &raw, &buffer_size, &max_buffer_size)) {
1707 return -1;
1708 }
1709
Benjamin Peterson59406a92009-03-26 17:10:29 +00001710 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1711 return -1;
1712
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001713 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001714 return -1;
1715
1716 Py_CLEAR(self->raw);
1717 Py_INCREF(raw);
1718 self->raw = raw;
1719 self->readable = 0;
1720 self->writable = 1;
1721
1722 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001723 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001724 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001725 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001726 self->pos = 0;
1727
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001728 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1729 Py_TYPE(raw) == &PyFileIO_Type);
1730
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001731 self->ok = 1;
1732 return 0;
1733}
1734
1735static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001736_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001737{
1738 Py_buffer buf;
1739 PyObject *memobj, *res;
1740 Py_ssize_t n;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001741 int errnum;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001742 /* NOTE: the buffer needn't be released as its object is NULL. */
1743 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1744 return -1;
1745 memobj = PyMemoryView_FromBuffer(&buf);
1746 if (memobj == NULL)
1747 return -1;
Antoine Pitroud843c2d2011-02-25 21:34:39 +00001748 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1749 occurs so we needn't do it ourselves.
1750 We then retry writing, ignoring the signal if no handler has
1751 raised (see issue #10956).
1752 */
1753 do {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001754 errno = 0;
Antoine Pitroud843c2d2011-02-25 21:34:39 +00001755 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001756 errnum = errno;
Gregory P. Smith51359922012-06-23 23:55:39 -07001757 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001758 Py_DECREF(memobj);
1759 if (res == NULL)
1760 return -1;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001761 if (res == Py_None) {
1762 /* Non-blocking stream would have blocked. Special return code!
1763 Being paranoid we reset errno in case it is changed by code
1764 triggered by a decref. errno is used by _set_BlockingIOError(). */
1765 Py_DECREF(res);
1766 errno = errnum;
1767 return -2;
1768 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001769 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1770 Py_DECREF(res);
1771 if (n < 0 || n > len) {
1772 PyErr_Format(PyExc_IOError,
1773 "raw write() returned invalid length %zd "
1774 "(should have been between 0 and %zd)", n, len);
1775 return -1;
1776 }
1777 if (n > 0 && self->abs_pos != -1)
1778 self->abs_pos += n;
1779 return n;
1780}
1781
1782/* `restore_pos` is 1 if we need to restore the raw stream position at
1783 the end, 0 otherwise. */
1784static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001785_bufferedwriter_flush_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001786{
1787 Py_ssize_t written = 0;
1788 Py_off_t n, rewind;
1789
1790 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1791 goto end;
1792 /* First, rewind */
1793 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1794 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001795 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001796 if (n < 0) {
1797 goto error;
1798 }
1799 self->raw_pos -= rewind;
1800 }
1801 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001802 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001803 self->buffer + self->write_pos,
1804 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1805 Py_off_t, Py_ssize_t));
1806 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001807 goto error;
1808 }
1809 else if (n == -2) {
1810 _set_BlockingIOError("write could not complete without blocking",
1811 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001812 goto error;
1813 }
1814 self->write_pos += n;
1815 self->raw_pos = self->write_pos;
1816 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001817 /* Partial writes can return successfully when interrupted by a
1818 signal (see write(2)). We must run signal handlers before
1819 blocking another time, possibly indefinitely. */
1820 if (PyErr_CheckSignals() < 0)
1821 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001822 }
1823
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001824 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001825
1826end:
1827 Py_RETURN_NONE;
1828
1829error:
1830 return NULL;
1831}
1832
1833static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001834bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001835{
1836 PyObject *res = NULL;
1837 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001838 Py_ssize_t written, avail, remaining;
1839 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001840
1841 CHECK_INITIALIZED(self)
1842 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1843 return NULL;
1844 }
1845
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001846 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001847 PyErr_SetString(PyExc_ValueError, "write to closed file");
1848 PyBuffer_Release(&buf);
1849 return NULL;
1850 }
1851
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001852 if (!ENTER_BUFFERED(self)) {
1853 PyBuffer_Release(&buf);
1854 return NULL;
1855 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001856
1857 /* Fast path: the data to write can be fully buffered. */
1858 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1859 self->pos = 0;
1860 self->raw_pos = 0;
1861 }
1862 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1863 if (buf.len <= avail) {
1864 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02001865 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001866 self->write_pos = self->pos;
1867 }
1868 ADJUST_POSITION(self, self->pos + buf.len);
1869 if (self->pos > self->write_end)
1870 self->write_end = self->pos;
1871 written = buf.len;
1872 goto end;
1873 }
1874
1875 /* First write the current buffer */
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001876 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001877 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001878 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001879 if (w == NULL)
1880 goto error;
1881 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001882 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001883 /* Make some place by shifting the buffer. */
1884 assert(VALID_WRITE_BUFFER(self));
1885 memmove(self->buffer, self->buffer + self->write_pos,
1886 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1887 Py_off_t, Py_ssize_t));
1888 self->write_end -= self->write_pos;
1889 self->raw_pos -= self->write_pos;
1890 self->pos -= self->write_pos;
1891 self->write_pos = 0;
1892 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1893 Py_off_t, Py_ssize_t);
1894 if (buf.len <= avail) {
1895 /* Everything can be buffered */
1896 PyErr_Clear();
1897 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1898 self->write_end += buf.len;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001899 self->pos += buf.len;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001900 written = buf.len;
1901 goto end;
1902 }
1903 /* Buffer as much as possible. */
1904 memcpy(self->buffer + self->write_end, buf.buf, avail);
1905 self->write_end += avail;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001906 self->pos += avail;
1907 /* XXX Modifying the existing exception e using the pointer w
1908 will change e.characters_written but not e.args[2].
1909 Therefore we just replace with a new error. */
1910 _set_BlockingIOError("write could not complete without blocking",
1911 avail);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001912 goto error;
1913 }
1914 Py_CLEAR(res);
1915
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001916 /* Adjust the raw stream position if it is away from the logical stream
1917 position. This happens if the read buffer has been filled but not
1918 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1919 the raw stream by itself).
1920 Fixes issue #6629.
1921 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001922 offset = RAW_OFFSET(self);
1923 if (offset != 0) {
1924 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001925 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001926 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001927 }
1928
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001929 /* Then write buf itself. At this point the buffer has been emptied. */
1930 remaining = buf.len;
1931 written = 0;
1932 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001933 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001934 self, (char *) buf.buf + written, buf.len - written);
1935 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001936 goto error;
1937 } else if (n == -2) {
1938 /* Write failed because raw file is non-blocking */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001939 if (remaining > self->buffer_size) {
1940 /* Can't buffer everything, still buffer as much as possible */
1941 memcpy(self->buffer,
1942 (char *) buf.buf + written, self->buffer_size);
1943 self->raw_pos = 0;
1944 ADJUST_POSITION(self, self->buffer_size);
1945 self->write_end = self->buffer_size;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001946 written += self->buffer_size;
1947 _set_BlockingIOError("write could not complete without "
1948 "blocking", written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001949 goto error;
1950 }
1951 PyErr_Clear();
1952 break;
1953 }
1954 written += n;
1955 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001956 /* Partial writes can return successfully when interrupted by a
1957 signal (see write(2)). We must run signal handlers before
1958 blocking another time, possibly indefinitely. */
1959 if (PyErr_CheckSignals() < 0)
1960 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001961 }
1962 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001963 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001964 if (remaining > 0) {
1965 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1966 written += remaining;
1967 }
1968 self->write_pos = 0;
1969 /* TODO: sanity check (remaining >= 0) */
1970 self->write_end = remaining;
1971 ADJUST_POSITION(self, remaining);
1972 self->raw_pos = 0;
1973
1974end:
1975 res = PyLong_FromSsize_t(written);
1976
1977error:
1978 LEAVE_BUFFERED(self)
1979 PyBuffer_Release(&buf);
1980 return res;
1981}
1982
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001983static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001984 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001985 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1986 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1987 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1988 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1989 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1990 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1991 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001992 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001993 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001994
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001995 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1996 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1997 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1998 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1999 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002000 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002001 {NULL, NULL}
2002};
2003
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002004static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002005 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002006 {NULL}
2007};
2008
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002009static PyGetSetDef bufferedwriter_getset[] = {
2010 {"closed", (getter)buffered_closed_get, NULL, NULL},
2011 {"name", (getter)buffered_name_get, NULL, NULL},
2012 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002013 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002014};
2015
2016
2017PyTypeObject PyBufferedWriter_Type = {
2018 PyVarObject_HEAD_INIT(NULL, 0)
2019 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002020 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002021 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002022 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002023 0, /*tp_print*/
2024 0, /*tp_getattr*/
2025 0, /*tp_setattr*/
2026 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002027 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002028 0, /*tp_as_number*/
2029 0, /*tp_as_sequence*/
2030 0, /*tp_as_mapping*/
2031 0, /*tp_hash */
2032 0, /*tp_call*/
2033 0, /*tp_str*/
2034 0, /*tp_getattro*/
2035 0, /*tp_setattro*/
2036 0, /*tp_as_buffer*/
2037 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2038 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002039 bufferedwriter_doc, /* tp_doc */
2040 (traverseproc)buffered_traverse, /* tp_traverse */
2041 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002042 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002043 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002044 0, /* tp_iter */
2045 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002046 bufferedwriter_methods, /* tp_methods */
2047 bufferedwriter_members, /* tp_members */
2048 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002049 0, /* tp_base */
2050 0, /* tp_dict */
2051 0, /* tp_descr_get */
2052 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002053 offsetof(buffered, dict), /* tp_dictoffset */
2054 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002055 0, /* tp_alloc */
2056 PyType_GenericNew, /* tp_new */
2057};
2058
2059
2060
2061/*
2062 * BufferedRWPair
2063 */
2064
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002065PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002066 "A buffered reader and writer object together.\n"
2067 "\n"
2068 "A buffered reader object and buffered writer object put together to\n"
2069 "form a sequential IO object that can read and write. This is typically\n"
2070 "used with a socket or two-way pipe.\n"
2071 "\n"
2072 "reader and writer are RawIOBase objects that are readable and\n"
2073 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002074 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002075 );
2076
2077/* XXX The usefulness of this (compared to having two separate IO objects) is
2078 * questionable.
2079 */
2080
2081typedef struct {
2082 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002083 buffered *reader;
2084 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002085 PyObject *dict;
2086 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002087} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002088
2089static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002090bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002091{
2092 PyObject *reader, *writer;
2093 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002094 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002095
2096 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2097 &buffer_size, &max_buffer_size)) {
2098 return -1;
2099 }
2100
Benjamin Peterson59406a92009-03-26 17:10:29 +00002101 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2102 return -1;
2103
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002104 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002105 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002106 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002107 return -1;
2108
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002109 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002110 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002111 if (self->reader == NULL)
2112 return -1;
2113
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002114 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002115 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002116 if (self->writer == NULL) {
2117 Py_CLEAR(self->reader);
2118 return -1;
2119 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002120
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002121 return 0;
2122}
2123
2124static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002125bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002126{
2127 Py_VISIT(self->dict);
2128 return 0;
2129}
2130
2131static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002132bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002133{
2134 Py_CLEAR(self->reader);
2135 Py_CLEAR(self->writer);
2136 Py_CLEAR(self->dict);
2137 return 0;
2138}
2139
2140static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002141bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002142{
2143 _PyObject_GC_UNTRACK(self);
2144 Py_CLEAR(self->reader);
2145 Py_CLEAR(self->writer);
2146 Py_CLEAR(self->dict);
2147 Py_TYPE(self)->tp_free((PyObject *) self);
2148}
2149
2150static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002151_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002152{
2153 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2154 PyObject *ret;
2155
2156 if (func == NULL) {
2157 PyErr_SetString(PyExc_AttributeError, name);
2158 return NULL;
2159 }
2160
2161 ret = PyObject_CallObject(func, args);
2162 Py_DECREF(func);
2163 return ret;
2164}
2165
2166static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002167bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002168{
2169 return _forward_call(self->reader, "read", args);
2170}
2171
2172static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002173bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002174{
2175 return _forward_call(self->reader, "peek", args);
2176}
2177
2178static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002179bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002180{
2181 return _forward_call(self->reader, "read1", args);
2182}
2183
2184static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002185bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002186{
2187 return _forward_call(self->reader, "readinto", args);
2188}
2189
2190static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002191bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002192{
2193 return _forward_call(self->writer, "write", args);
2194}
2195
2196static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002197bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002198{
2199 return _forward_call(self->writer, "flush", args);
2200}
2201
2202static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002203bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002204{
2205 return _forward_call(self->reader, "readable", args);
2206}
2207
2208static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002209bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002210{
2211 return _forward_call(self->writer, "writable", args);
2212}
2213
2214static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002215bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002216{
2217 PyObject *ret = _forward_call(self->writer, "close", args);
2218 if (ret == NULL)
2219 return NULL;
2220 Py_DECREF(ret);
2221
2222 return _forward_call(self->reader, "close", args);
2223}
2224
2225static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002226bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002227{
2228 PyObject *ret = _forward_call(self->writer, "isatty", args);
2229
2230 if (ret != Py_False) {
2231 /* either True or exception */
2232 return ret;
2233 }
2234 Py_DECREF(ret);
2235
2236 return _forward_call(self->reader, "isatty", args);
2237}
2238
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002239static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002240bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002241{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002242 if (self->writer == NULL) {
2243 PyErr_SetString(PyExc_RuntimeError,
2244 "the BufferedRWPair object is being garbage-collected");
2245 return NULL;
2246 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002247 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2248}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002249
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002250static PyMethodDef bufferedrwpair_methods[] = {
2251 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2252 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2253 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2254 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002255
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002256 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2257 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002258
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002259 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2260 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002261
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002262 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2263 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002264
Antoine Pitrou243757e2010-11-05 21:15:39 +00002265 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2266
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002267 {NULL, NULL}
2268};
2269
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002270static PyGetSetDef bufferedrwpair_getset[] = {
2271 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002272 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002273};
2274
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002275PyTypeObject PyBufferedRWPair_Type = {
2276 PyVarObject_HEAD_INIT(NULL, 0)
2277 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002278 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002279 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002280 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002281 0, /*tp_print*/
2282 0, /*tp_getattr*/
2283 0, /*tp_setattr*/
2284 0, /*tp_compare */
2285 0, /*tp_repr*/
2286 0, /*tp_as_number*/
2287 0, /*tp_as_sequence*/
2288 0, /*tp_as_mapping*/
2289 0, /*tp_hash */
2290 0, /*tp_call*/
2291 0, /*tp_str*/
2292 0, /*tp_getattro*/
2293 0, /*tp_setattro*/
2294 0, /*tp_as_buffer*/
2295 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2296 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002297 bufferedrwpair_doc, /* tp_doc */
2298 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2299 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002300 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002301 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002302 0, /* tp_iter */
2303 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002304 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002305 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002306 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002307 0, /* tp_base */
2308 0, /* tp_dict */
2309 0, /* tp_descr_get */
2310 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002311 offsetof(rwpair, dict), /* tp_dictoffset */
2312 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002313 0, /* tp_alloc */
2314 PyType_GenericNew, /* tp_new */
2315};
2316
2317
2318
2319/*
2320 * BufferedRandom
2321 */
2322
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002323PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002324 "A buffered interface to random access streams.\n"
2325 "\n"
2326 "The constructor creates a reader and writer for a seekable stream,\n"
2327 "raw, given in the first argument. If the buffer_size is omitted it\n"
2328 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2329 );
2330
2331static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002332bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002333{
2334 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2335 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002336 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002337 PyObject *raw;
2338
2339 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002340 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002341
R David Murray67bfe802013-02-23 21:51:05 -05002342 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedRandom", kwlist,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002343 &raw, &buffer_size, &max_buffer_size)) {
2344 return -1;
2345 }
2346
Benjamin Peterson59406a92009-03-26 17:10:29 +00002347 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2348 return -1;
2349
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002350 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002351 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002352 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002353 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002354 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002355 return -1;
2356
2357 Py_CLEAR(self->raw);
2358 Py_INCREF(raw);
2359 self->raw = raw;
2360 self->buffer_size = buffer_size;
2361 self->readable = 1;
2362 self->writable = 1;
2363
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002364 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002365 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002366 _bufferedreader_reset_buf(self);
2367 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002368 self->pos = 0;
2369
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002370 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2371 Py_TYPE(raw) == &PyFileIO_Type);
2372
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002373 self->ok = 1;
2374 return 0;
2375}
2376
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002377static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002378 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002379 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2380 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2381 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2382 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2383 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2384 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2385 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002386 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002387 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002388
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002389 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002390
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002391 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2392 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2393 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2394 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2395 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2396 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2397 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2398 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2399 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002400 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002401 {NULL, NULL}
2402};
2403
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002404static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002405 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002406 {NULL}
2407};
2408
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002409static PyGetSetDef bufferedrandom_getset[] = {
2410 {"closed", (getter)buffered_closed_get, NULL, NULL},
2411 {"name", (getter)buffered_name_get, NULL, NULL},
2412 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002413 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002414};
2415
2416
2417PyTypeObject PyBufferedRandom_Type = {
2418 PyVarObject_HEAD_INIT(NULL, 0)
2419 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002420 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002421 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002422 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002423 0, /*tp_print*/
2424 0, /*tp_getattr*/
2425 0, /*tp_setattr*/
2426 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002427 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002428 0, /*tp_as_number*/
2429 0, /*tp_as_sequence*/
2430 0, /*tp_as_mapping*/
2431 0, /*tp_hash */
2432 0, /*tp_call*/
2433 0, /*tp_str*/
2434 0, /*tp_getattro*/
2435 0, /*tp_setattro*/
2436 0, /*tp_as_buffer*/
2437 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2438 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002439 bufferedrandom_doc, /* tp_doc */
2440 (traverseproc)buffered_traverse, /* tp_traverse */
2441 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002442 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002443 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002444 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002445 (iternextfunc)buffered_iternext, /* tp_iternext */
2446 bufferedrandom_methods, /* tp_methods */
2447 bufferedrandom_members, /* tp_members */
2448 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002449 0, /* tp_base */
2450 0, /*tp_dict*/
2451 0, /* tp_descr_get */
2452 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002453 offsetof(buffered, dict), /*tp_dictoffset*/
2454 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002455 0, /* tp_alloc */
2456 PyType_GenericNew, /* tp_new */
2457};