blob: 358a94dce270c0158b29ee48898af9d7dd79e06d [file] [log] [blame]
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001/*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
Antoine Pitrou3486a982011-05-12 01:57:53 +02003
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00004 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
Antoine Pitrou3486a982011-05-12 01:57:53 +02006
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00007 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8*/
9
10#define PY_SSIZE_T_CLEAN
11#include "Python.h"
12#include "structmember.h"
13#include "pythread.h"
14#include "_iomodule.h"
15
Martin v. Löwisbd928fe2011-10-14 10:20:37 +020016_Py_IDENTIFIER(close);
17_Py_IDENTIFIER(_dealloc_warn);
18_Py_IDENTIFIER(flush);
19_Py_IDENTIFIER(isatty);
Martin v. Löwis767046a2011-10-14 15:35:36 +020020_Py_IDENTIFIER(mode);
21_Py_IDENTIFIER(name);
Martin v. Löwisbd928fe2011-10-14 10:20:37 +020022_Py_IDENTIFIER(peek);
23_Py_IDENTIFIER(read);
24_Py_IDENTIFIER(read1);
25_Py_IDENTIFIER(readable);
26_Py_IDENTIFIER(readinto);
Benjamin Petersona96fea02014-06-22 14:17:44 -070027_Py_IDENTIFIER(readinto1);
Martin v. Löwisbd928fe2011-10-14 10:20:37 +020028_Py_IDENTIFIER(writable);
29_Py_IDENTIFIER(write);
Martin v. Löwisafe55bb2011-10-09 10:38:36 +020030
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000031/*
32 * BufferedIOBase class, inherits from IOBase.
33 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000034PyDoc_STRVAR(bufferediobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000035 "Base class for buffered IO objects.\n"
36 "\n"
37 "The main difference with RawIOBase is that the read() method\n"
38 "supports omitting the size argument, and does not have a default\n"
39 "implementation that defers to readinto().\n"
40 "\n"
41 "In addition, read(), readinto() and write() may raise\n"
42 "BlockingIOError if the underlying raw stream is in non-blocking\n"
43 "mode and not ready; unlike their raw counterparts, they will never\n"
44 "return None.\n"
45 "\n"
46 "A typical implementation should not inherit from a RawIOBase\n"
47 "implementation, but wrap one.\n"
48 );
49
50static PyObject *
Benjamin Petersona96fea02014-06-22 14:17:44 -070051_bufferediobase_readinto_generic(PyObject *self, PyObject *args, char readinto1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000052{
53 Py_buffer buf;
54 Py_ssize_t len;
55 PyObject *data;
56
Benjamin Petersona96fea02014-06-22 14:17:44 -070057 if (!PyArg_ParseTuple(args,
58 readinto1 ? "w*:readinto1" : "w*:readinto",
59 &buf)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000060 return NULL;
61 }
62
Benjamin Petersona96fea02014-06-22 14:17:44 -070063 data = _PyObject_CallMethodId(self,
64 readinto1 ? &PyId_read1 : &PyId_read,
65 "n", buf.len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000066 if (data == NULL)
67 goto error;
68
69 if (!PyBytes_Check(data)) {
70 Py_DECREF(data);
71 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
72 goto error;
73 }
74
75 len = Py_SIZE(data);
Serhiy Storchaka37a79a12013-05-28 16:24:45 +030076 if (len > buf.len) {
77 PyErr_Format(PyExc_ValueError,
78 "read() returned too much data: "
79 "%zd bytes requested, %zd returned",
80 buf.len, len);
81 Py_DECREF(data);
82 goto error;
83 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000084 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
85
86 PyBuffer_Release(&buf);
87 Py_DECREF(data);
88
89 return PyLong_FromSsize_t(len);
90
91 error:
92 PyBuffer_Release(&buf);
93 return NULL;
94}
95
96static PyObject *
Benjamin Petersona96fea02014-06-22 14:17:44 -070097bufferediobase_readinto(PyObject *self, PyObject *args)
98{
99 return _bufferediobase_readinto_generic(self, args, 0);
100}
101
102static PyObject *
103bufferediobase_readinto1(PyObject *self, PyObject *args)
104{
105 return _bufferediobase_readinto_generic(self, args, 1);
106}
107
108static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000109bufferediobase_unsupported(const char *message)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000110{
Antoine Pitrou712cb732013-12-21 15:51:54 +0100111 _PyIO_State *state = IO_STATE();
112 if (state != NULL)
113 PyErr_SetString(state->unsupported_operation, message);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000114 return NULL;
115}
116
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000117PyDoc_STRVAR(bufferediobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000118 "Disconnect this buffer from its underlying raw stream and return it.\n"
119 "\n"
120 "After the raw stream has been detached, the buffer is in an unusable\n"
121 "state.\n");
122
123static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000124bufferediobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000125{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000126 return bufferediobase_unsupported("detach");
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000127}
128
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000129PyDoc_STRVAR(bufferediobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000130 "Read and return up to n bytes.\n"
131 "\n"
132 "If the argument is omitted, None, or negative, reads and\n"
133 "returns all data until EOF.\n"
134 "\n"
135 "If the argument is positive, and the underlying raw stream is\n"
136 "not 'interactive', multiple raw reads may be issued to satisfy\n"
137 "the byte count (unless EOF is reached first). But for\n"
138 "interactive raw streams (as well as sockets and pipes), at most\n"
139 "one raw read will be issued, and a short result does not imply\n"
140 "that EOF is imminent.\n"
141 "\n"
142 "Returns an empty bytes object on EOF.\n"
143 "\n"
144 "Returns None if the underlying raw stream was open in non-blocking\n"
145 "mode and no data is available at the moment.\n");
146
147static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000148bufferediobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000149{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000150 return bufferediobase_unsupported("read");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000151}
152
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000153PyDoc_STRVAR(bufferediobase_read1_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000154 "Read and return up to n bytes, with at most one read() call\n"
155 "to the underlying raw stream. A short result does not imply\n"
156 "that EOF is imminent.\n"
157 "\n"
158 "Returns an empty bytes object on EOF.\n");
159
160static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000161bufferediobase_read1(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000162{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000163 return bufferediobase_unsupported("read1");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000164}
165
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000166PyDoc_STRVAR(bufferediobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000167 "Write the given buffer to the IO stream.\n"
168 "\n"
169 "Returns the number of bytes written, which is never less than\n"
170 "len(b).\n"
171 "\n"
172 "Raises BlockingIOError if the buffer is full and the\n"
173 "underlying raw stream cannot accept more data at the moment.\n");
174
175static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000176bufferediobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000177{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000178 return bufferediobase_unsupported("write");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000179}
180
181
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000182static PyMethodDef bufferediobase_methods[] = {
183 {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
184 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
185 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
186 {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
Benjamin Petersona96fea02014-06-22 14:17:44 -0700187 {"readinto1", bufferediobase_readinto1, METH_VARARGS, NULL},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000188 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000189 {NULL, NULL}
190};
191
192PyTypeObject PyBufferedIOBase_Type = {
193 PyVarObject_HEAD_INIT(NULL, 0)
194 "_io._BufferedIOBase", /*tp_name*/
195 0, /*tp_basicsize*/
196 0, /*tp_itemsize*/
197 0, /*tp_dealloc*/
198 0, /*tp_print*/
199 0, /*tp_getattr*/
200 0, /*tp_setattr*/
201 0, /*tp_compare */
202 0, /*tp_repr*/
203 0, /*tp_as_number*/
204 0, /*tp_as_sequence*/
205 0, /*tp_as_mapping*/
206 0, /*tp_hash */
207 0, /*tp_call*/
208 0, /*tp_str*/
209 0, /*tp_getattro*/
210 0, /*tp_setattro*/
211 0, /*tp_as_buffer*/
Antoine Pitrou796564c2013-07-30 19:59:21 +0200212 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
213 | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000214 bufferediobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000215 0, /* tp_traverse */
216 0, /* tp_clear */
217 0, /* tp_richcompare */
218 0, /* tp_weaklistoffset */
219 0, /* tp_iter */
220 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000221 bufferediobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000222 0, /* tp_members */
223 0, /* tp_getset */
224 &PyIOBase_Type, /* tp_base */
225 0, /* tp_dict */
226 0, /* tp_descr_get */
227 0, /* tp_descr_set */
228 0, /* tp_dictoffset */
229 0, /* tp_init */
230 0, /* tp_alloc */
231 0, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +0200232 0, /* tp_free */
233 0, /* tp_is_gc */
234 0, /* tp_bases */
235 0, /* tp_mro */
236 0, /* tp_cache */
237 0, /* tp_subclasses */
238 0, /* tp_weaklist */
239 0, /* tp_del */
240 0, /* tp_version_tag */
241 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000242};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000243
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000244
245typedef struct {
246 PyObject_HEAD
247
248 PyObject *raw;
249 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000250 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000251 int readable;
252 int writable;
Antoine Pitrou796564c2013-07-30 19:59:21 +0200253 char finalizing;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200254
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000255 /* True if this is a vanilla Buffered object (rather than a user derived
256 class) *and* the raw stream is a vanilla FileIO object. */
257 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000258
259 /* Absolute position inside the raw stream (-1 if unknown). */
260 Py_off_t abs_pos;
261
262 /* A static buffer of size `buffer_size` */
263 char *buffer;
264 /* Current logical position in the buffer. */
265 Py_off_t pos;
266 /* Position of the raw stream in the buffer. */
267 Py_off_t raw_pos;
268
269 /* Just after the last buffered byte in the buffer, or -1 if the buffer
270 isn't ready for reading. */
271 Py_off_t read_end;
272
273 /* Just after the last byte actually written */
274 Py_off_t write_pos;
275 /* Just after the last byte waiting to be written, or -1 if the buffer
276 isn't ready for writing. */
277 Py_off_t write_end;
278
Georg Brandldfd73442009-04-05 11:47:34 +0000279#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000280 PyThread_type_lock lock;
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000281 volatile long owner;
Georg Brandldfd73442009-04-05 11:47:34 +0000282#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000283
284 Py_ssize_t buffer_size;
285 Py_ssize_t buffer_mask;
286
287 PyObject *dict;
288 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000289} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000290
291/*
292 Implementation notes:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200293
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000294 * BufferedReader, BufferedWriter and BufferedRandom try to share most
295 methods (this is helped by the members `readable` and `writable`, which
296 are initialized in the respective constructors)
297 * They also share a single buffer for reading and writing. This enables
298 interleaved reads and writes without flushing. It also makes the logic
299 a bit trickier to get right.
300 * The absolute position of the raw stream is cached, if possible, in the
301 `abs_pos` member. It must be updated every time an operation is done
302 on the raw stream. If not sure, it can be reinitialized by calling
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000303 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000304 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000305 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
306 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000307
308 NOTE: we should try to maintain block alignment of reads and writes to the
309 raw stream (according to the buffer size), but for now it is only done
310 in read() and friends.
Antoine Pitrou3486a982011-05-12 01:57:53 +0200311
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000312*/
313
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000314/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000315
Georg Brandldfd73442009-04-05 11:47:34 +0000316#ifdef WITH_THREAD
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000317
318static int
319_enter_buffered_busy(buffered *self)
320{
321 if (self->owner == PyThread_get_thread_ident()) {
322 PyErr_Format(PyExc_RuntimeError,
323 "reentrant call inside %R", self);
324 return 0;
Antoine Pitrou5800b272009-11-01 12:05:48 +0000325 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000326 Py_BEGIN_ALLOW_THREADS
327 PyThread_acquire_lock(self->lock, 1);
328 Py_END_ALLOW_THREADS
329 return 1;
330}
331
332#define ENTER_BUFFERED(self) \
333 ( (PyThread_acquire_lock(self->lock, 0) ? \
334 1 : _enter_buffered_busy(self)) \
335 && (self->owner = PyThread_get_thread_ident(), 1) )
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000336
337#define LEAVE_BUFFERED(self) \
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000338 do { \
339 self->owner = 0; \
340 PyThread_release_lock(self->lock); \
341 } while(0);
342
Georg Brandldfd73442009-04-05 11:47:34 +0000343#else
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000344#define ENTER_BUFFERED(self) 1
Georg Brandldfd73442009-04-05 11:47:34 +0000345#define LEAVE_BUFFERED(self)
346#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000347
348#define CHECK_INITIALIZED(self) \
349 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000350 if (self->detached) { \
351 PyErr_SetString(PyExc_ValueError, \
352 "raw stream has been detached"); \
353 } else { \
354 PyErr_SetString(PyExc_ValueError, \
355 "I/O operation on uninitialized object"); \
356 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000357 return NULL; \
358 }
359
360#define CHECK_INITIALIZED_INT(self) \
361 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000362 if (self->detached) { \
363 PyErr_SetString(PyExc_ValueError, \
364 "raw stream has been detached"); \
365 } else { \
366 PyErr_SetString(PyExc_ValueError, \
367 "I/O operation on uninitialized object"); \
368 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000369 return -1; \
370 }
371
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000372#define IS_CLOSED(self) \
373 (self->fast_closed_checks \
374 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000375 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000376
377#define CHECK_CLOSED(self, error_msg) \
378 if (IS_CLOSED(self)) { \
379 PyErr_SetString(PyExc_ValueError, error_msg); \
380 return NULL; \
381 }
382
383
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000384#define VALID_READ_BUFFER(self) \
385 (self->readable && self->read_end != -1)
386
387#define VALID_WRITE_BUFFER(self) \
388 (self->writable && self->write_end != -1)
389
390#define ADJUST_POSITION(self, _new_pos) \
391 do { \
392 self->pos = _new_pos; \
393 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
394 self->read_end = self->pos; \
395 } while(0)
396
397#define READAHEAD(self) \
398 ((self->readable && VALID_READ_BUFFER(self)) \
399 ? (self->read_end - self->pos) : 0)
400
401#define RAW_OFFSET(self) \
402 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
403 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
404
405#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000406 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000407
408#define MINUS_LAST_BLOCK(self, size) \
409 (self->buffer_mask ? \
410 (size & ~self->buffer_mask) : \
411 (self->buffer_size * (size / self->buffer_size)))
412
413
414static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000415buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000416{
Antoine Pitrou796564c2013-07-30 19:59:21 +0200417 self->finalizing = 1;
418 if (_PyIOBase_finalize((PyObject *) self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000419 return;
420 _PyObject_GC_UNTRACK(self);
421 self->ok = 0;
422 if (self->weakreflist != NULL)
423 PyObject_ClearWeakRefs((PyObject *)self);
424 Py_CLEAR(self->raw);
425 if (self->buffer) {
426 PyMem_Free(self->buffer);
427 self->buffer = NULL;
428 }
Georg Brandldfd73442009-04-05 11:47:34 +0000429#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000430 if (self->lock) {
431 PyThread_free_lock(self->lock);
432 self->lock = NULL;
433 }
Georg Brandldfd73442009-04-05 11:47:34 +0000434#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000435 Py_CLEAR(self->dict);
436 Py_TYPE(self)->tp_free((PyObject *)self);
437}
438
Antoine Pitrou10f0c502012-07-29 19:02:46 +0200439static PyObject *
440buffered_sizeof(buffered *self, void *unused)
441{
442 Py_ssize_t res;
443
444 res = sizeof(buffered);
445 if (self->buffer)
446 res += self->buffer_size;
447 return PyLong_FromSsize_t(res);
448}
449
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000450static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000451buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000452{
453 Py_VISIT(self->raw);
454 Py_VISIT(self->dict);
455 return 0;
456}
457
458static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000459buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000460{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000461 self->ok = 0;
462 Py_CLEAR(self->raw);
463 Py_CLEAR(self->dict);
464 return 0;
465}
466
Antoine Pitroue033e062010-10-29 10:38:18 +0000467/* Because this can call arbitrary code, it shouldn't be called when
468 the refcount is 0 (that is, not directly from tp_dealloc unless
469 the refcount has been temporarily re-incremented). */
Matthias Klosebee33162010-11-16 20:07:51 +0000470static PyObject *
Antoine Pitroue033e062010-10-29 10:38:18 +0000471buffered_dealloc_warn(buffered *self, PyObject *source)
472{
473 if (self->ok && self->raw) {
474 PyObject *r;
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200475 r = _PyObject_CallMethodId(self->raw, &PyId__dealloc_warn, "O", source);
Antoine Pitroue033e062010-10-29 10:38:18 +0000476 if (r)
477 Py_DECREF(r);
478 else
479 PyErr_Clear();
480 }
481 Py_RETURN_NONE;
482}
483
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000484/*
485 * _BufferedIOMixin methods
486 * This is not a class, just a collection of methods that will be reused
487 * by BufferedReader and BufferedWriter
488 */
489
490/* Flush and close */
491
492static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000493buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000494{
495 CHECK_INITIALIZED(self)
496 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
497}
498
499static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000500buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000501{
502 int closed;
503 PyObject *res;
504 CHECK_INITIALIZED_INT(self)
505 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
506 if (res == NULL)
507 return -1;
508 closed = PyObject_IsTrue(res);
509 Py_DECREF(res);
510 return closed;
511}
512
513static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000514buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000515{
516 CHECK_INITIALIZED(self)
517 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
518}
519
520static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000521buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000522{
Benjamin Peterson68623612012-12-20 11:53:11 -0600523 PyObject *res = NULL, *exc = NULL, *val, *tb;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000524 int r;
525
526 CHECK_INITIALIZED(self)
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000527 if (!ENTER_BUFFERED(self))
528 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000529
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000530 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000531 if (r < 0)
532 goto end;
533 if (r > 0) {
534 res = Py_None;
535 Py_INCREF(res);
536 goto end;
537 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000538
Antoine Pitrou796564c2013-07-30 19:59:21 +0200539 if (self->finalizing) {
Antoine Pitroue033e062010-10-29 10:38:18 +0000540 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
541 if (r)
542 Py_DECREF(r);
543 else
544 PyErr_Clear();
545 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000546 /* flush() will most probably re-take the lock, so drop it first */
547 LEAVE_BUFFERED(self)
548 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000549 if (!ENTER_BUFFERED(self))
550 return NULL;
Benjamin Peterson68623612012-12-20 11:53:11 -0600551 if (res == NULL)
552 PyErr_Fetch(&exc, &val, &tb);
553 else
554 Py_DECREF(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000555
556 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
557
Jesus Ceadc469452012-10-04 12:37:56 +0200558 if (self->buffer) {
559 PyMem_Free(self->buffer);
560 self->buffer = NULL;
561 }
562
Benjamin Peterson68623612012-12-20 11:53:11 -0600563 if (exc != NULL) {
Serhiy Storchakae2bd2a72014-10-08 22:31:52 +0300564 _PyErr_ChainExceptions(exc, val, tb);
565 Py_CLEAR(res);
Benjamin Peterson68623612012-12-20 11:53:11 -0600566 }
567
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000568end:
569 LEAVE_BUFFERED(self)
570 return res;
571}
572
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000573/* detach */
574
575static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000576buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000577{
578 PyObject *raw, *res;
579 CHECK_INITIALIZED(self)
580 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
581 if (res == NULL)
582 return NULL;
583 Py_DECREF(res);
584 raw = self->raw;
585 self->raw = NULL;
586 self->detached = 1;
587 self->ok = 0;
588 return raw;
589}
590
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000591/* Inquiries */
592
593static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000594buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000595{
596 CHECK_INITIALIZED(self)
597 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
598}
599
600static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000601buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000602{
603 CHECK_INITIALIZED(self)
604 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
605}
606
607static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000608buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000609{
610 CHECK_INITIALIZED(self)
611 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
612}
613
614static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000615buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000616{
617 CHECK_INITIALIZED(self)
Martin v. Löwis767046a2011-10-14 15:35:36 +0200618 return _PyObject_GetAttrId(self->raw, &PyId_name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000619}
620
621static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000622buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000623{
624 CHECK_INITIALIZED(self)
Martin v. Löwis767046a2011-10-14 15:35:36 +0200625 return _PyObject_GetAttrId(self->raw, &PyId_mode);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000626}
627
628/* Lower-level APIs */
629
630static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000631buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000632{
633 CHECK_INITIALIZED(self)
634 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
635}
636
637static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000638buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000639{
640 CHECK_INITIALIZED(self)
641 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
642}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000643
Antoine Pitrou243757e2010-11-05 21:15:39 +0000644/* Serialization */
645
646static PyObject *
647buffered_getstate(buffered *self, PyObject *args)
648{
649 PyErr_Format(PyExc_TypeError,
650 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
651 return NULL;
652}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000653
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000654/* Forward decls */
655static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100656_bufferedwriter_flush_unlocked(buffered *);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000657static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000658_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000659static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000660_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000661static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000662_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000663static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +0200664_bufferedreader_peek_unlocked(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000665static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000666_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000667static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000668_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000669static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000670_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200671static Py_ssize_t
672_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000673
674/*
675 * Helpers
676 */
677
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100678/* Sets the current error to BlockingIOError */
679static void
680_set_BlockingIOError(char *msg, Py_ssize_t written)
681{
682 PyObject *err;
Victor Stinnerace47d72013-07-18 01:41:08 +0200683 PyErr_Clear();
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100684 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
685 errno, msg, written);
686 if (err)
687 PyErr_SetObject(PyExc_BlockingIOError, err);
688 Py_XDECREF(err);
689}
690
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000691/* Returns the address of the `written` member if a BlockingIOError was
692 raised, NULL otherwise. The error is always re-raised. */
693static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000694_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000695{
696 PyObject *t, *v, *tb;
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200697 PyOSErrorObject *err;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000698
699 PyErr_Fetch(&t, &v, &tb);
700 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
701 PyErr_Restore(t, v, tb);
702 return NULL;
703 }
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200704 err = (PyOSErrorObject *) v;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000705 /* TODO: sanity check (err->written >= 0) */
706 PyErr_Restore(t, v, tb);
707 return &err->written;
708}
709
710static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000711_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000712{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000713 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000714 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000715 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
716 if (res == NULL)
717 return -1;
718 n = PyNumber_AsOff_t(res, PyExc_ValueError);
719 Py_DECREF(res);
720 if (n < 0) {
721 if (!PyErr_Occurred())
722 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000723 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200724 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000725 return -1;
726 }
727 self->abs_pos = n;
728 return n;
729}
730
731static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000732_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000733{
734 PyObject *res, *posobj, *whenceobj;
735 Py_off_t n;
736
737 posobj = PyLong_FromOff_t(target);
738 if (posobj == NULL)
739 return -1;
740 whenceobj = PyLong_FromLong(whence);
741 if (whenceobj == NULL) {
742 Py_DECREF(posobj);
743 return -1;
744 }
745 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
746 posobj, whenceobj, NULL);
747 Py_DECREF(posobj);
748 Py_DECREF(whenceobj);
749 if (res == NULL)
750 return -1;
751 n = PyNumber_AsOff_t(res, PyExc_ValueError);
752 Py_DECREF(res);
753 if (n < 0) {
754 if (!PyErr_Occurred())
755 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000756 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200757 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000758 return -1;
759 }
760 self->abs_pos = n;
761 return n;
762}
763
764static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000765_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000766{
767 Py_ssize_t n;
768 if (self->buffer_size <= 0) {
769 PyErr_SetString(PyExc_ValueError,
770 "buffer size must be strictly positive");
771 return -1;
772 }
773 if (self->buffer)
774 PyMem_Free(self->buffer);
775 self->buffer = PyMem_Malloc(self->buffer_size);
776 if (self->buffer == NULL) {
777 PyErr_NoMemory();
778 return -1;
779 }
Georg Brandldfd73442009-04-05 11:47:34 +0000780#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000781 if (self->lock)
782 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000783 self->lock = PyThread_allocate_lock();
784 if (self->lock == NULL) {
785 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
786 return -1;
787 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000788 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000789#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000790 /* Find out whether buffer_size is a power of 2 */
791 /* XXX is this optimization useful? */
792 for (n = self->buffer_size - 1; n & 1; n >>= 1)
793 ;
794 if (n == 0)
795 self->buffer_mask = self->buffer_size - 1;
796 else
797 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000798 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000799 PyErr_Clear();
800 return 0;
801}
802
Antoine Pitrou707ce822011-02-25 21:24:11 +0000803/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
804 clears the error indicator), 0 otherwise.
805 Should only be called when PyErr_Occurred() is true.
806*/
Gregory P. Smith51359922012-06-23 23:55:39 -0700807int
808_PyIO_trap_eintr(void)
Antoine Pitrou707ce822011-02-25 21:24:11 +0000809{
810 static PyObject *eintr_int = NULL;
811 PyObject *typ, *val, *tb;
812 PyEnvironmentErrorObject *env_err;
813
814 if (eintr_int == NULL) {
815 eintr_int = PyLong_FromLong(EINTR);
816 assert(eintr_int != NULL);
817 }
818 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
819 return 0;
820 PyErr_Fetch(&typ, &val, &tb);
821 PyErr_NormalizeException(&typ, &val, &tb);
822 env_err = (PyEnvironmentErrorObject *) val;
823 assert(env_err != NULL);
824 if (env_err->myerrno != NULL &&
825 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
826 Py_DECREF(typ);
827 Py_DECREF(val);
828 Py_XDECREF(tb);
829 return 1;
830 }
831 /* This silences any error set by PyObject_RichCompareBool() */
832 PyErr_Restore(typ, val, tb);
833 return 0;
834}
835
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000836/*
837 * Shared methods and wrappers
838 */
839
840static PyObject *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200841buffered_flush_and_rewind_unlocked(buffered *self)
842{
843 PyObject *res;
844
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100845 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200846 if (res == NULL)
847 return NULL;
848 Py_DECREF(res);
849
850 if (self->readable) {
851 /* Rewind the raw stream so that its position corresponds to
852 the current logical position. */
853 Py_off_t n;
854 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
855 _bufferedreader_reset_buf(self);
856 if (n == -1)
857 return NULL;
858 }
859 Py_RETURN_NONE;
860}
861
862static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000863buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000864{
865 PyObject *res;
866
867 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000868 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000869
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000870 if (!ENTER_BUFFERED(self))
871 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200872 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000873 LEAVE_BUFFERED(self)
874
875 return res;
876}
877
878static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000879buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000880{
881 Py_ssize_t n = 0;
882 PyObject *res = NULL;
883
884 CHECK_INITIALIZED(self)
885 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
886 return NULL;
887 }
888
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000889 if (!ENTER_BUFFERED(self))
890 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000891
892 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200893 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000894 if (res == NULL)
895 goto end;
896 Py_CLEAR(res);
897 }
Victor Stinnerbc93a112011-06-01 00:01:24 +0200898 res = _bufferedreader_peek_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000899
900end:
901 LEAVE_BUFFERED(self)
902 return res;
903}
904
905static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000906buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000907{
908 Py_ssize_t n = -1;
909 PyObject *res;
910
911 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000912 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000913 return NULL;
914 }
915 if (n < -1) {
916 PyErr_SetString(PyExc_ValueError,
917 "read length must be positive or -1");
918 return NULL;
919 }
920
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000921 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000922
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000923 if (n == -1) {
924 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000925 if (!ENTER_BUFFERED(self))
926 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000927 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000928 }
929 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000930 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200931 if (res != Py_None)
932 return res;
933 Py_DECREF(res);
934 if (!ENTER_BUFFERED(self))
935 return NULL;
936 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000937 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000938
Antoine Pitroue05565e2011-08-20 14:39:23 +0200939 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000940 return res;
941}
942
943static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000944buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000945{
946 Py_ssize_t n, have, r;
947 PyObject *res = NULL;
948
949 CHECK_INITIALIZED(self)
950 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
951 return NULL;
952 }
953
954 if (n < 0) {
955 PyErr_SetString(PyExc_ValueError,
956 "read length must be positive");
957 return NULL;
958 }
959 if (n == 0)
960 return PyBytes_FromStringAndSize(NULL, 0);
961
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000962 /* Return up to n bytes. If at least one byte is buffered, we
963 only return buffered bytes. Otherwise, we do one raw read. */
964
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000965 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
966 if (have > 0) {
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100967 n = Py_MIN(have, n);
968 res = _bufferedreader_read_fast(self, n);
969 assert(res != Py_None);
970 return res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000971 }
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100972 res = PyBytes_FromStringAndSize(NULL, n);
973 if (res == NULL)
974 return NULL;
975 if (!ENTER_BUFFERED(self)) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200976 Py_DECREF(res);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100977 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200978 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000979 _bufferedreader_reset_buf(self);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100980 r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
981 LEAVE_BUFFERED(self)
982 if (r == -1) {
983 Py_DECREF(res);
984 return NULL;
985 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000986 if (r == -2)
987 r = 0;
988 if (n > r)
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100989 _PyBytes_Resize(&res, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000990 return res;
991}
992
993static PyObject *
Benjamin Petersona96fea02014-06-22 14:17:44 -0700994_buffered_readinto_generic(buffered *self, PyObject *args, char readinto1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000995{
Antoine Pitrou3486a982011-05-12 01:57:53 +0200996 Py_buffer buf;
997 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000998 PyObject *res = NULL;
999
1000 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +02001001
Benjamin Petersona96fea02014-06-22 14:17:44 -07001002 if (!PyArg_ParseTuple(args,
1003 readinto1 ? "w*:readinto1" : "w*:readinto",
1004 &buf))
Antoine Pitrou3486a982011-05-12 01:57:53 +02001005 return NULL;
1006
1007 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1008 if (n > 0) {
1009 if (n >= buf.len) {
1010 memcpy(buf.buf, self->buffer + self->pos, buf.len);
1011 self->pos += buf.len;
1012 res = PyLong_FromSsize_t(buf.len);
1013 goto end_unlocked;
1014 }
1015 memcpy(buf.buf, self->buffer + self->pos, n);
1016 self->pos += n;
1017 written = n;
1018 }
1019
1020 if (!ENTER_BUFFERED(self))
1021 goto end_unlocked;
1022
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001023 if (self->writable) {
Antoine Pitroue8bb1a02011-08-20 14:52:04 +02001024 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001025 if (res == NULL)
1026 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +02001027 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001028 }
Antoine Pitrou3486a982011-05-12 01:57:53 +02001029
1030 _bufferedreader_reset_buf(self);
1031 self->pos = 0;
1032
1033 for (remaining = buf.len - written;
1034 remaining > 0;
1035 written += n, remaining -= n) {
1036 /* If remaining bytes is larger than internal buffer size, copy
1037 * directly into caller's buffer. */
1038 if (remaining > self->buffer_size) {
Antoine Pitrou4e19e112011-05-12 02:07:00 +02001039 n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
1040 remaining);
Antoine Pitrou3486a982011-05-12 01:57:53 +02001041 }
Benjamin Petersona96fea02014-06-22 14:17:44 -07001042
1043 /* In readinto1 mode, we do not want to fill the internal
1044 buffer if we already have some data to return */
1045 else if (!(readinto1 && written)) {
Antoine Pitrou3486a982011-05-12 01:57:53 +02001046 n = _bufferedreader_fill_buffer(self);
1047 if (n > 0) {
1048 if (n > remaining)
1049 n = remaining;
Antoine Pitrou4e19e112011-05-12 02:07:00 +02001050 memcpy((char *) buf.buf + written,
1051 self->buffer + self->pos, n);
Antoine Pitrou3486a982011-05-12 01:57:53 +02001052 self->pos += n;
1053 continue; /* short circuit */
1054 }
1055 }
Benjamin Petersona96fea02014-06-22 14:17:44 -07001056 else
1057 n = 0;
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001058
Antoine Pitrou3486a982011-05-12 01:57:53 +02001059 if (n == 0 || (n == -2 && written > 0))
1060 break;
1061 if (n < 0) {
1062 if (n == -2) {
1063 Py_INCREF(Py_None);
1064 res = Py_None;
1065 }
1066 goto end;
1067 }
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001068
Benjamin Petersona96fea02014-06-22 14:17:44 -07001069 /* At most one read in readinto1 mode */
1070 if (readinto1) {
1071 written += n;
1072 break;
1073 }
Antoine Pitrou3486a982011-05-12 01:57:53 +02001074 }
1075 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001076
1077end:
Antoine Pitrou3486a982011-05-12 01:57:53 +02001078 LEAVE_BUFFERED(self);
1079end_unlocked:
1080 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001081 return res;
1082}
1083
1084static PyObject *
Benjamin Petersona96fea02014-06-22 14:17:44 -07001085buffered_readinto(buffered *self, PyObject *args)
1086{
1087 return _buffered_readinto_generic(self, args, 0);
1088}
1089
1090static PyObject *
1091buffered_readinto1(buffered *self, PyObject *args)
1092{
1093 return _buffered_readinto_generic(self, args, 1);
1094}
1095
1096
1097static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001098_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001099{
1100 PyObject *res = NULL;
1101 PyObject *chunks = NULL;
1102 Py_ssize_t n, written = 0;
1103 const char *start, *s, *end;
1104
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001105 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001106
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001107 /* First, try to find a line in the buffer. This can run unlocked because
1108 the calls to the C API are simple enough that they can't trigger
1109 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001110 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1111 if (limit >= 0 && n > limit)
1112 n = limit;
1113 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001114 s = memchr(start, '\n', n);
1115 if (s != NULL) {
1116 res = PyBytes_FromStringAndSize(start, s - start + 1);
1117 if (res != NULL)
1118 self->pos += s - start + 1;
1119 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001120 }
1121 if (n == limit) {
1122 res = PyBytes_FromStringAndSize(start, n);
1123 if (res != NULL)
1124 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001125 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001126 }
1127
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001128 if (!ENTER_BUFFERED(self))
1129 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001130
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001131 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001132 chunks = PyList_New(0);
1133 if (chunks == NULL)
1134 goto end;
1135 if (n > 0) {
1136 res = PyBytes_FromStringAndSize(start, n);
1137 if (res == NULL)
1138 goto end;
1139 if (PyList_Append(chunks, res) < 0) {
1140 Py_CLEAR(res);
1141 goto end;
1142 }
1143 Py_CLEAR(res);
1144 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001145 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001146 if (limit >= 0)
1147 limit -= n;
1148 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001149 if (self->writable) {
1150 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1151 if (r == NULL)
1152 goto end;
1153 Py_DECREF(r);
1154 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001155
1156 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001157 _bufferedreader_reset_buf(self);
1158 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001159 if (n == -1)
1160 goto end;
1161 if (n <= 0)
1162 break;
1163 if (limit >= 0 && n > limit)
1164 n = limit;
1165 start = self->buffer;
1166 end = start + n;
1167 s = start;
1168 while (s < end) {
1169 if (*s++ == '\n') {
1170 res = PyBytes_FromStringAndSize(start, s - start);
1171 if (res == NULL)
1172 goto end;
1173 self->pos = s - start;
1174 goto found;
1175 }
1176 }
1177 res = PyBytes_FromStringAndSize(start, n);
1178 if (res == NULL)
1179 goto end;
1180 if (n == limit) {
1181 self->pos = n;
1182 break;
1183 }
1184 if (PyList_Append(chunks, res) < 0) {
1185 Py_CLEAR(res);
1186 goto end;
1187 }
1188 Py_CLEAR(res);
1189 written += n;
1190 if (limit >= 0)
1191 limit -= n;
1192 }
1193found:
1194 if (res != NULL && PyList_Append(chunks, res) < 0) {
1195 Py_CLEAR(res);
1196 goto end;
1197 }
1198 Py_CLEAR(res);
1199 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1200
1201end:
1202 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001203end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001204 Py_XDECREF(chunks);
1205 return res;
1206}
1207
1208static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001209buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001210{
1211 Py_ssize_t limit = -1;
1212
1213 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001214 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001215 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001216 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001217}
1218
1219
1220static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001221buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001222{
1223 Py_off_t pos;
1224
1225 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001226 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001227 if (pos == -1)
1228 return NULL;
1229 pos -= RAW_OFFSET(self);
1230 /* TODO: sanity check (pos >= 0) */
1231 return PyLong_FromOff_t(pos);
1232}
1233
1234static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001235buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001236{
1237 Py_off_t target, n;
1238 int whence = 0;
1239 PyObject *targetobj, *res = NULL;
1240
1241 CHECK_INITIALIZED(self)
1242 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1243 return NULL;
1244 }
Jesus Cea94363612012-06-22 18:32:07 +02001245
1246 /* Do some error checking instead of trusting OS 'seek()'
1247 ** error detection, just in case.
1248 */
1249 if ((whence < 0 || whence >2)
1250#ifdef SEEK_HOLE
1251 && (whence != SEEK_HOLE)
1252#endif
1253#ifdef SEEK_DATA
1254 && (whence != SEEK_DATA)
1255#endif
1256 ) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001257 PyErr_Format(PyExc_ValueError,
Jesus Cea94363612012-06-22 18:32:07 +02001258 "whence value %d unsupported", whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001259 return NULL;
1260 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001261
1262 CHECK_CLOSED(self, "seek of closed file")
1263
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001264 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1265 return NULL;
1266
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001267 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1268 if (target == -1 && PyErr_Occurred())
1269 return NULL;
1270
Jesus Cea94363612012-06-22 18:32:07 +02001271 /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1272 buffer. Other whence values must be managed without this optimization.
1273 Some Operating Systems can provide additional values, like
1274 SEEK_HOLE/SEEK_DATA. */
1275 if (((whence == 0) || (whence == 1)) && self->readable) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001276 Py_off_t current, avail;
1277 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001278 so as to return quickly if possible. Also, we needn't take the
1279 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001280 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001281 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1282 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001283 current = RAW_TELL(self);
1284 avail = READAHEAD(self);
1285 if (avail > 0) {
1286 Py_off_t offset;
1287 if (whence == 0)
1288 offset = target - (current - RAW_OFFSET(self));
1289 else
1290 offset = target;
1291 if (offset >= -self->pos && offset <= avail) {
1292 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001293 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001294 }
1295 }
1296 }
1297
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001298 if (!ENTER_BUFFERED(self))
1299 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001300
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001301 /* Fallback: invoke raw seek() method and clear buffer */
1302 if (self->writable) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001303 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001304 if (res == NULL)
1305 goto end;
1306 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001307 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001308 }
1309
1310 /* TODO: align on block boundary and read buffer if needed? */
1311 if (whence == 1)
1312 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001313 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001314 if (n == -1)
1315 goto end;
1316 self->raw_pos = -1;
1317 res = PyLong_FromOff_t(n);
1318 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001319 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001320
1321end:
1322 LEAVE_BUFFERED(self)
1323 return res;
1324}
1325
1326static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001327buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001328{
1329 PyObject *pos = Py_None;
1330 PyObject *res = NULL;
1331
1332 CHECK_INITIALIZED(self)
1333 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1334 return NULL;
1335 }
1336
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001337 if (!ENTER_BUFFERED(self))
1338 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001339
1340 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001341 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001342 if (res == NULL)
1343 goto end;
1344 Py_CLEAR(res);
1345 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001346 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1347 if (res == NULL)
1348 goto end;
1349 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001350 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001351 PyErr_Clear();
1352
1353end:
1354 LEAVE_BUFFERED(self)
1355 return res;
1356}
1357
1358static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001359buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001360{
1361 PyObject *line;
1362 PyTypeObject *tp;
1363
1364 CHECK_INITIALIZED(self);
1365
1366 tp = Py_TYPE(self);
1367 if (tp == &PyBufferedReader_Type ||
1368 tp == &PyBufferedRandom_Type) {
1369 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001370 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001371 }
1372 else {
1373 line = PyObject_CallMethodObjArgs((PyObject *)self,
1374 _PyIO_str_readline, NULL);
1375 if (line && !PyBytes_Check(line)) {
1376 PyErr_Format(PyExc_IOError,
1377 "readline() should have returned a bytes object, "
1378 "not '%.200s'", Py_TYPE(line)->tp_name);
1379 Py_DECREF(line);
1380 return NULL;
1381 }
1382 }
1383
1384 if (line == NULL)
1385 return NULL;
1386
1387 if (PyBytes_GET_SIZE(line) == 0) {
1388 /* Reached EOF or would have blocked */
1389 Py_DECREF(line);
1390 return NULL;
1391 }
1392
1393 return line;
1394}
1395
Antoine Pitrou716c4442009-05-23 19:04:03 +00001396static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001397buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001398{
1399 PyObject *nameobj, *res;
1400
Martin v. Löwis767046a2011-10-14 15:35:36 +02001401 nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
Antoine Pitrou716c4442009-05-23 19:04:03 +00001402 if (nameobj == NULL) {
Benjamin Peterson10e76b62014-12-21 20:51:50 -06001403 if (PyErr_ExceptionMatches(PyExc_Exception))
Antoine Pitrou716c4442009-05-23 19:04:03 +00001404 PyErr_Clear();
1405 else
1406 return NULL;
1407 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1408 }
1409 else {
1410 res = PyUnicode_FromFormat("<%s name=%R>",
1411 Py_TYPE(self)->tp_name, nameobj);
1412 Py_DECREF(nameobj);
1413 }
1414 return res;
1415}
1416
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001417/*
1418 * class BufferedReader
1419 */
1420
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001421PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001422 "Create a new buffered reader using the given readable raw IO object.");
1423
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001424static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001425{
1426 self->read_end = -1;
1427}
1428
1429static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001430bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001431{
1432 char *kwlist[] = {"raw", "buffer_size", NULL};
1433 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1434 PyObject *raw;
1435
1436 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001437 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001438
1439 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1440 &raw, &buffer_size)) {
1441 return -1;
1442 }
1443
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001444 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001445 return -1;
1446
1447 Py_CLEAR(self->raw);
1448 Py_INCREF(raw);
1449 self->raw = raw;
1450 self->buffer_size = buffer_size;
1451 self->readable = 1;
1452 self->writable = 0;
1453
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001454 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001455 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001456 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001457
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001458 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1459 Py_TYPE(raw) == &PyFileIO_Type);
1460
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001461 self->ok = 1;
1462 return 0;
1463}
1464
1465static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001466_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001467{
1468 Py_buffer buf;
1469 PyObject *memobj, *res;
1470 Py_ssize_t n;
1471 /* NOTE: the buffer needn't be released as its object is NULL. */
1472 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1473 return -1;
1474 memobj = PyMemoryView_FromBuffer(&buf);
1475 if (memobj == NULL)
1476 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001477 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1478 occurs so we needn't do it ourselves.
1479 We then retry reading, ignoring the signal if no handler has
1480 raised (see issue #10956).
1481 */
1482 do {
1483 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
Gregory P. Smith51359922012-06-23 23:55:39 -07001484 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001485 Py_DECREF(memobj);
1486 if (res == NULL)
1487 return -1;
1488 if (res == Py_None) {
1489 /* Non-blocking stream would have blocked. Special return code! */
1490 Py_DECREF(res);
1491 return -2;
1492 }
1493 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1494 Py_DECREF(res);
1495 if (n < 0 || n > len) {
1496 PyErr_Format(PyExc_IOError,
1497 "raw readinto() returned invalid length %zd "
1498 "(should have been between 0 and %zd)", n, len);
1499 return -1;
1500 }
1501 if (n > 0 && self->abs_pos != -1)
1502 self->abs_pos += n;
1503 return n;
1504}
1505
1506static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001507_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001508{
1509 Py_ssize_t start, len, n;
1510 if (VALID_READ_BUFFER(self))
1511 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1512 else
1513 start = 0;
1514 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001515 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001516 if (n <= 0)
1517 return n;
1518 self->read_end = start + n;
1519 self->raw_pos = start + n;
1520 return n;
1521}
1522
1523static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001524_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001525{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001526 Py_ssize_t current_size;
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001527 PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001528
1529 /* First copy what we have in the current buffer. */
1530 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1531 if (current_size) {
1532 data = PyBytes_FromStringAndSize(
1533 self->buffer + self->pos, current_size);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001534 if (data == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001535 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001536 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001537 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001538 /* We're going past the buffer's bounds, flush it */
1539 if (self->writable) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001540 tmp = buffered_flush_and_rewind_unlocked(self);
1541 if (tmp == NULL)
1542 goto cleanup;
1543 Py_CLEAR(tmp);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001544 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001545 _bufferedreader_reset_buf(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001546
1547 if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001548 tmp = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
1549 if (tmp == NULL)
1550 goto cleanup;
1551 if (tmp != Py_None && !PyBytes_Check(tmp)) {
Victor Stinnerb57f1082011-05-26 00:19:38 +02001552 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001553 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001554 }
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001555 if (tmp == Py_None) {
1556 if (current_size == 0) {
1557 res = Py_None;
1558 goto cleanup;
1559 } else {
1560 res = data;
1561 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001562 }
1563 }
1564 else if (current_size) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001565 PyBytes_Concat(&data, tmp);
1566 res = data;
1567 goto cleanup;
1568 }
1569 else {
1570 res = tmp;
1571 goto cleanup;
1572 }
Victor Stinnerb57f1082011-05-26 00:19:38 +02001573 }
1574
1575 chunks = PyList_New(0);
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001576 if (chunks == NULL)
1577 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001578
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001579 while (1) {
1580 if (data) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001581 if (PyList_Append(chunks, data) < 0)
1582 goto cleanup;
1583 Py_CLEAR(data);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001584 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001585
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001586 /* Read until EOF or until read() would block. */
1587 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001588 if (data == NULL)
1589 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001590 if (data != Py_None && !PyBytes_Check(data)) {
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001591 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001592 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001593 }
1594 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1595 if (current_size == 0) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001596 res = data;
1597 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001598 }
1599 else {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001600 tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1601 res = tmp;
1602 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001603 }
1604 }
1605 current_size += PyBytes_GET_SIZE(data);
1606 if (self->abs_pos != -1)
1607 self->abs_pos += PyBytes_GET_SIZE(data);
1608 }
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001609cleanup:
1610 /* res is either NULL or a borrowed ref */
1611 Py_XINCREF(res);
1612 Py_XDECREF(data);
1613 Py_XDECREF(tmp);
1614 Py_XDECREF(chunks);
1615 return res;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001616}
1617
1618/* Read n bytes from the buffer if it can, otherwise return None.
1619 This function is simple enough that it can run unlocked. */
1620static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001621_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001622{
1623 Py_ssize_t current_size;
1624
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001625 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1626 if (n <= current_size) {
1627 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001628 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1629 if (res != NULL)
1630 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001631 return res;
1632 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001633 Py_RETURN_NONE;
1634}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001635
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001636/* Generic read function: read from the stream until enough bytes are read,
1637 * or until an EOF occurs or until read() would block.
1638 */
1639static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001640_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001641{
1642 PyObject *res = NULL;
1643 Py_ssize_t current_size, remaining, written;
1644 char *out;
1645
1646 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1647 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001648 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001649
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001650 res = PyBytes_FromStringAndSize(NULL, n);
1651 if (res == NULL)
1652 goto error;
1653 out = PyBytes_AS_STRING(res);
1654 remaining = n;
1655 written = 0;
1656 if (current_size > 0) {
1657 memcpy(out, self->buffer + self->pos, current_size);
1658 remaining -= current_size;
1659 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001660 self->pos += current_size;
1661 }
1662 /* Flush the write buffer if necessary */
1663 if (self->writable) {
1664 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1665 if (r == NULL)
1666 goto error;
1667 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001668 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001669 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001670 while (remaining > 0) {
1671 /* We want to read a whole block at the end into buffer.
1672 If we had readv() we could do this in one pass. */
1673 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1674 if (r == 0)
1675 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001676 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001677 if (r == -1)
1678 goto error;
1679 if (r == 0 || r == -2) {
1680 /* EOF occurred or read() would block. */
1681 if (r == 0 || written > 0) {
1682 if (_PyBytes_Resize(&res, written))
1683 goto error;
1684 return res;
1685 }
1686 Py_DECREF(res);
1687 Py_INCREF(Py_None);
1688 return Py_None;
1689 }
1690 remaining -= r;
1691 written += r;
1692 }
1693 assert(remaining <= self->buffer_size);
1694 self->pos = 0;
1695 self->raw_pos = 0;
1696 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001697 /* NOTE: when the read is satisfied, we avoid issuing any additional
1698 reads, which could block indefinitely (e.g. on a socket).
1699 See issue #9550. */
1700 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001701 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001702 if (r == -1)
1703 goto error;
1704 if (r == 0 || r == -2) {
1705 /* EOF occurred or read() would block. */
1706 if (r == 0 || written > 0) {
1707 if (_PyBytes_Resize(&res, written))
1708 goto error;
1709 return res;
1710 }
1711 Py_DECREF(res);
1712 Py_INCREF(Py_None);
1713 return Py_None;
1714 }
1715 if (remaining > r) {
1716 memcpy(out + written, self->buffer + self->pos, r);
1717 written += r;
1718 self->pos += r;
1719 remaining -= r;
1720 }
1721 else if (remaining > 0) {
1722 memcpy(out + written, self->buffer + self->pos, remaining);
1723 written += remaining;
1724 self->pos += remaining;
1725 remaining = 0;
1726 }
1727 if (remaining == 0)
1728 break;
1729 }
1730
1731 return res;
1732
1733error:
1734 Py_XDECREF(res);
1735 return NULL;
1736}
1737
1738static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +02001739_bufferedreader_peek_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001740{
1741 Py_ssize_t have, r;
1742
1743 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1744 /* Constraints:
1745 1. we don't want to advance the file position.
1746 2. we don't want to lose block alignment, so we can't shift the buffer
1747 to make some place.
1748 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1749 */
1750 if (have > 0) {
1751 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1752 }
1753
1754 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001755 _bufferedreader_reset_buf(self);
1756 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001757 if (r == -1)
1758 return NULL;
1759 if (r == -2)
1760 r = 0;
1761 self->pos = 0;
1762 return PyBytes_FromStringAndSize(self->buffer, r);
1763}
1764
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001765static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001766 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001767 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1768 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1769 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1770 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1771 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1772 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1773 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1774 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001775 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001776 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001777
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001778 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1779 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1780 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001781 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Petersona96fea02014-06-22 14:17:44 -07001782 {"readinto1", (PyCFunction)buffered_readinto1, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001783 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1784 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1785 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1786 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02001787 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001788 {NULL, NULL}
1789};
1790
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001791static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001792 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02001793 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001794 {NULL}
1795};
1796
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001797static PyGetSetDef bufferedreader_getset[] = {
1798 {"closed", (getter)buffered_closed_get, NULL, NULL},
1799 {"name", (getter)buffered_name_get, NULL, NULL},
1800 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001801 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001802};
1803
1804
1805PyTypeObject PyBufferedReader_Type = {
1806 PyVarObject_HEAD_INIT(NULL, 0)
1807 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001808 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001809 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001810 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001811 0, /*tp_print*/
1812 0, /*tp_getattr*/
1813 0, /*tp_setattr*/
1814 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001815 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001816 0, /*tp_as_number*/
1817 0, /*tp_as_sequence*/
1818 0, /*tp_as_mapping*/
1819 0, /*tp_hash */
1820 0, /*tp_call*/
1821 0, /*tp_str*/
1822 0, /*tp_getattro*/
1823 0, /*tp_setattro*/
1824 0, /*tp_as_buffer*/
1825 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02001826 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001827 bufferedreader_doc, /* tp_doc */
1828 (traverseproc)buffered_traverse, /* tp_traverse */
1829 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001830 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001831 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001832 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001833 (iternextfunc)buffered_iternext, /* tp_iternext */
1834 bufferedreader_methods, /* tp_methods */
1835 bufferedreader_members, /* tp_members */
1836 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001837 0, /* tp_base */
1838 0, /* tp_dict */
1839 0, /* tp_descr_get */
1840 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001841 offsetof(buffered, dict), /* tp_dictoffset */
1842 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001843 0, /* tp_alloc */
1844 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02001845 0, /* tp_free */
1846 0, /* tp_is_gc */
1847 0, /* tp_bases */
1848 0, /* tp_mro */
1849 0, /* tp_cache */
1850 0, /* tp_subclasses */
1851 0, /* tp_weaklist */
1852 0, /* tp_del */
1853 0, /* tp_version_tag */
1854 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001855};
1856
1857
Benjamin Peterson59406a92009-03-26 17:10:29 +00001858
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001859/*
1860 * class BufferedWriter
1861 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001862PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001863 "A buffer for a writeable sequential RawIO object.\n"
1864 "\n"
1865 "The constructor creates a BufferedWriter for the given writeable raw\n"
1866 "stream. If the buffer_size is not given, it defaults to\n"
Florent Xicluna109d5732012-07-07 17:03:22 +02001867 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001868 );
1869
1870static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001871_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001872{
1873 self->write_pos = 0;
1874 self->write_end = -1;
1875}
1876
1877static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001878bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001879{
Florent Xicluna109d5732012-07-07 17:03:22 +02001880 char *kwlist[] = {"raw", "buffer_size", NULL};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001881 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001882 PyObject *raw;
1883
1884 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001885 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001886
R David Murray9f10f562013-02-23 22:07:55 -05001887 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedWriter", kwlist,
Florent Xicluna109d5732012-07-07 17:03:22 +02001888 &raw, &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001889 return -1;
1890 }
1891
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001892 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001893 return -1;
1894
1895 Py_CLEAR(self->raw);
1896 Py_INCREF(raw);
1897 self->raw = raw;
1898 self->readable = 0;
1899 self->writable = 1;
1900
1901 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001902 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001903 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001904 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001905 self->pos = 0;
1906
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001907 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1908 Py_TYPE(raw) == &PyFileIO_Type);
1909
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001910 self->ok = 1;
1911 return 0;
1912}
1913
1914static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001915_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001916{
1917 Py_buffer buf;
1918 PyObject *memobj, *res;
1919 Py_ssize_t n;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001920 int errnum;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001921 /* NOTE: the buffer needn't be released as its object is NULL. */
1922 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1923 return -1;
1924 memobj = PyMemoryView_FromBuffer(&buf);
1925 if (memobj == NULL)
1926 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001927 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1928 occurs so we needn't do it ourselves.
1929 We then retry writing, ignoring the signal if no handler has
1930 raised (see issue #10956).
1931 */
1932 do {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001933 errno = 0;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001934 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001935 errnum = errno;
Gregory P. Smith51359922012-06-23 23:55:39 -07001936 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001937 Py_DECREF(memobj);
1938 if (res == NULL)
1939 return -1;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001940 if (res == Py_None) {
1941 /* Non-blocking stream would have blocked. Special return code!
1942 Being paranoid we reset errno in case it is changed by code
1943 triggered by a decref. errno is used by _set_BlockingIOError(). */
1944 Py_DECREF(res);
1945 errno = errnum;
1946 return -2;
1947 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001948 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1949 Py_DECREF(res);
1950 if (n < 0 || n > len) {
1951 PyErr_Format(PyExc_IOError,
1952 "raw write() returned invalid length %zd "
1953 "(should have been between 0 and %zd)", n, len);
1954 return -1;
1955 }
1956 if (n > 0 && self->abs_pos != -1)
1957 self->abs_pos += n;
1958 return n;
1959}
1960
1961/* `restore_pos` is 1 if we need to restore the raw stream position at
1962 the end, 0 otherwise. */
1963static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001964_bufferedwriter_flush_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001965{
1966 Py_ssize_t written = 0;
1967 Py_off_t n, rewind;
1968
1969 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1970 goto end;
1971 /* First, rewind */
1972 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1973 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001974 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001975 if (n < 0) {
1976 goto error;
1977 }
1978 self->raw_pos -= rewind;
1979 }
1980 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001981 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001982 self->buffer + self->write_pos,
1983 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1984 Py_off_t, Py_ssize_t));
1985 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001986 goto error;
1987 }
1988 else if (n == -2) {
1989 _set_BlockingIOError("write could not complete without blocking",
1990 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001991 goto error;
1992 }
1993 self->write_pos += n;
1994 self->raw_pos = self->write_pos;
1995 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001996 /* Partial writes can return successfully when interrupted by a
1997 signal (see write(2)). We must run signal handlers before
1998 blocking another time, possibly indefinitely. */
1999 if (PyErr_CheckSignals() < 0)
2000 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002001 }
2002
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002003 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002004
2005end:
2006 Py_RETURN_NONE;
2007
2008error:
2009 return NULL;
2010}
2011
2012static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002013bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002014{
2015 PyObject *res = NULL;
2016 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002017 Py_ssize_t written, avail, remaining;
2018 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002019
2020 CHECK_INITIALIZED(self)
2021 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
2022 return NULL;
2023 }
2024
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002025 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002026 PyErr_SetString(PyExc_ValueError, "write to closed file");
2027 PyBuffer_Release(&buf);
2028 return NULL;
2029 }
2030
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00002031 if (!ENTER_BUFFERED(self)) {
2032 PyBuffer_Release(&buf);
2033 return NULL;
2034 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002035
2036 /* Fast path: the data to write can be fully buffered. */
2037 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
2038 self->pos = 0;
2039 self->raw_pos = 0;
2040 }
2041 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
2042 if (buf.len <= avail) {
2043 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02002044 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002045 self->write_pos = self->pos;
2046 }
2047 ADJUST_POSITION(self, self->pos + buf.len);
2048 if (self->pos > self->write_end)
2049 self->write_end = self->pos;
2050 written = buf.len;
2051 goto end;
2052 }
2053
2054 /* First write the current buffer */
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002055 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002056 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002057 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002058 if (w == NULL)
2059 goto error;
2060 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002061 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002062 /* Make some place by shifting the buffer. */
2063 assert(VALID_WRITE_BUFFER(self));
2064 memmove(self->buffer, self->buffer + self->write_pos,
2065 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2066 Py_off_t, Py_ssize_t));
2067 self->write_end -= self->write_pos;
2068 self->raw_pos -= self->write_pos;
2069 self->pos -= self->write_pos;
2070 self->write_pos = 0;
2071 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
2072 Py_off_t, Py_ssize_t);
2073 if (buf.len <= avail) {
2074 /* Everything can be buffered */
2075 PyErr_Clear();
2076 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
2077 self->write_end += buf.len;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002078 self->pos += buf.len;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002079 written = buf.len;
2080 goto end;
2081 }
2082 /* Buffer as much as possible. */
2083 memcpy(self->buffer + self->write_end, buf.buf, avail);
2084 self->write_end += avail;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002085 self->pos += avail;
2086 /* XXX Modifying the existing exception e using the pointer w
2087 will change e.characters_written but not e.args[2].
2088 Therefore we just replace with a new error. */
2089 _set_BlockingIOError("write could not complete without blocking",
2090 avail);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002091 goto error;
2092 }
2093 Py_CLEAR(res);
2094
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002095 /* Adjust the raw stream position if it is away from the logical stream
2096 position. This happens if the read buffer has been filled but not
2097 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2098 the raw stream by itself).
2099 Fixes issue #6629.
2100 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002101 offset = RAW_OFFSET(self);
2102 if (offset != 0) {
2103 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002104 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002105 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002106 }
2107
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002108 /* Then write buf itself. At this point the buffer has been emptied. */
2109 remaining = buf.len;
2110 written = 0;
2111 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002112 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002113 self, (char *) buf.buf + written, buf.len - written);
2114 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002115 goto error;
2116 } else if (n == -2) {
2117 /* Write failed because raw file is non-blocking */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002118 if (remaining > self->buffer_size) {
2119 /* Can't buffer everything, still buffer as much as possible */
2120 memcpy(self->buffer,
2121 (char *) buf.buf + written, self->buffer_size);
2122 self->raw_pos = 0;
2123 ADJUST_POSITION(self, self->buffer_size);
2124 self->write_end = self->buffer_size;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002125 written += self->buffer_size;
2126 _set_BlockingIOError("write could not complete without "
2127 "blocking", written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002128 goto error;
2129 }
2130 PyErr_Clear();
2131 break;
2132 }
2133 written += n;
2134 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002135 /* Partial writes can return successfully when interrupted by a
2136 signal (see write(2)). We must run signal handlers before
2137 blocking another time, possibly indefinitely. */
2138 if (PyErr_CheckSignals() < 0)
2139 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002140 }
2141 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002142 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002143 if (remaining > 0) {
2144 memcpy(self->buffer, (char *) buf.buf + written, remaining);
2145 written += remaining;
2146 }
2147 self->write_pos = 0;
2148 /* TODO: sanity check (remaining >= 0) */
2149 self->write_end = remaining;
2150 ADJUST_POSITION(self, remaining);
2151 self->raw_pos = 0;
2152
2153end:
2154 res = PyLong_FromSsize_t(written);
2155
2156error:
2157 LEAVE_BUFFERED(self)
2158 PyBuffer_Release(&buf);
2159 return res;
2160}
2161
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002162static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002163 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002164 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2165 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2166 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2167 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2168 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2169 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2170 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002171 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002172 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002173
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002174 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2175 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2176 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2177 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2178 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002179 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002180 {NULL, NULL}
2181};
2182
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002183static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002184 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02002185 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002186 {NULL}
2187};
2188
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002189static PyGetSetDef bufferedwriter_getset[] = {
2190 {"closed", (getter)buffered_closed_get, NULL, NULL},
2191 {"name", (getter)buffered_name_get, NULL, NULL},
2192 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002193 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002194};
2195
2196
2197PyTypeObject PyBufferedWriter_Type = {
2198 PyVarObject_HEAD_INIT(NULL, 0)
2199 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002200 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002201 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002202 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002203 0, /*tp_print*/
2204 0, /*tp_getattr*/
2205 0, /*tp_setattr*/
2206 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002207 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002208 0, /*tp_as_number*/
2209 0, /*tp_as_sequence*/
2210 0, /*tp_as_mapping*/
2211 0, /*tp_hash */
2212 0, /*tp_call*/
2213 0, /*tp_str*/
2214 0, /*tp_getattro*/
2215 0, /*tp_setattro*/
2216 0, /*tp_as_buffer*/
2217 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002218 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002219 bufferedwriter_doc, /* tp_doc */
2220 (traverseproc)buffered_traverse, /* tp_traverse */
2221 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002222 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002223 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002224 0, /* tp_iter */
2225 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002226 bufferedwriter_methods, /* tp_methods */
2227 bufferedwriter_members, /* tp_members */
2228 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002229 0, /* tp_base */
2230 0, /* tp_dict */
2231 0, /* tp_descr_get */
2232 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002233 offsetof(buffered, dict), /* tp_dictoffset */
2234 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002235 0, /* tp_alloc */
2236 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002237 0, /* tp_free */
2238 0, /* tp_is_gc */
2239 0, /* tp_bases */
2240 0, /* tp_mro */
2241 0, /* tp_cache */
2242 0, /* tp_subclasses */
2243 0, /* tp_weaklist */
2244 0, /* tp_del */
2245 0, /* tp_version_tag */
2246 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002247};
2248
2249
2250
2251/*
2252 * BufferedRWPair
2253 */
2254
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002255PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002256 "A buffered reader and writer object together.\n"
2257 "\n"
2258 "A buffered reader object and buffered writer object put together to\n"
2259 "form a sequential IO object that can read and write. This is typically\n"
2260 "used with a socket or two-way pipe.\n"
2261 "\n"
2262 "reader and writer are RawIOBase objects that are readable and\n"
2263 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002264 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002265 );
2266
2267/* XXX The usefulness of this (compared to having two separate IO objects) is
2268 * questionable.
2269 */
2270
2271typedef struct {
2272 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002273 buffered *reader;
2274 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002275 PyObject *dict;
2276 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002277} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002278
2279static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002280bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002281{
2282 PyObject *reader, *writer;
2283 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002284
Florent Xicluna109d5732012-07-07 17:03:22 +02002285 if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer,
2286 &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002287 return -1;
2288 }
2289
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002290 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002291 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002292 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002293 return -1;
2294
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002295 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002296 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002297 if (self->reader == NULL)
2298 return -1;
2299
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002300 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002301 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002302 if (self->writer == NULL) {
2303 Py_CLEAR(self->reader);
2304 return -1;
2305 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002306
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002307 return 0;
2308}
2309
2310static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002311bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002312{
2313 Py_VISIT(self->dict);
2314 return 0;
2315}
2316
2317static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002318bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002319{
2320 Py_CLEAR(self->reader);
2321 Py_CLEAR(self->writer);
2322 Py_CLEAR(self->dict);
2323 return 0;
2324}
2325
2326static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002327bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002328{
2329 _PyObject_GC_UNTRACK(self);
Benjamin Petersonbbd0a322014-09-29 22:46:57 -04002330 if (self->weakreflist != NULL)
2331 PyObject_ClearWeakRefs((PyObject *)self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002332 Py_CLEAR(self->reader);
2333 Py_CLEAR(self->writer);
2334 Py_CLEAR(self->dict);
2335 Py_TYPE(self)->tp_free((PyObject *) self);
2336}
2337
2338static PyObject *
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002339_forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002340{
Serhiy Storchaka61e24932014-02-12 10:52:35 +02002341 PyObject *func, *ret;
2342 if (self == NULL) {
2343 PyErr_SetString(PyExc_ValueError,
2344 "I/O operation on uninitialized object");
2345 return NULL;
2346 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002347
Serhiy Storchaka61e24932014-02-12 10:52:35 +02002348 func = _PyObject_GetAttrId((PyObject *)self, name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002349 if (func == NULL) {
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002350 PyErr_SetString(PyExc_AttributeError, name->string);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002351 return NULL;
2352 }
2353
2354 ret = PyObject_CallObject(func, args);
2355 Py_DECREF(func);
2356 return ret;
2357}
2358
2359static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002360bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002361{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002362 return _forward_call(self->reader, &PyId_read, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002363}
2364
2365static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002366bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002367{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002368 return _forward_call(self->reader, &PyId_peek, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002369}
2370
2371static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002372bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002373{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002374 return _forward_call(self->reader, &PyId_read1, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002375}
2376
2377static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002378bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002379{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002380 return _forward_call(self->reader, &PyId_readinto, args);
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002381}
2382
2383static PyObject *
Benjamin Petersona96fea02014-06-22 14:17:44 -07002384bufferedrwpair_readinto1(rwpair *self, PyObject *args)
2385{
2386 return _forward_call(self->reader, &PyId_readinto1, args);
2387}
2388
2389static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002390bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002391{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002392 return _forward_call(self->writer, &PyId_write, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002393}
2394
2395static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002396bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002397{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002398 return _forward_call(self->writer, &PyId_flush, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002399}
2400
2401static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002402bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002403{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002404 return _forward_call(self->reader, &PyId_readable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002405}
2406
2407static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002408bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002409{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002410 return _forward_call(self->writer, &PyId_writable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002411}
2412
2413static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002414bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002415{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002416 PyObject *ret = _forward_call(self->writer, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002417 if (ret == NULL)
2418 return NULL;
2419 Py_DECREF(ret);
2420
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002421 return _forward_call(self->reader, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002422}
2423
2424static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002425bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002426{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002427 PyObject *ret = _forward_call(self->writer, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002428
2429 if (ret != Py_False) {
2430 /* either True or exception */
2431 return ret;
2432 }
2433 Py_DECREF(ret);
2434
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002435 return _forward_call(self->reader, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002436}
2437
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002438static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002439bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002440{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002441 if (self->writer == NULL) {
2442 PyErr_SetString(PyExc_RuntimeError,
2443 "the BufferedRWPair object is being garbage-collected");
2444 return NULL;
2445 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002446 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2447}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002448
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002449static PyMethodDef bufferedrwpair_methods[] = {
2450 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2451 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2452 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2453 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Petersona96fea02014-06-22 14:17:44 -07002454 {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002455
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002456 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2457 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002458
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002459 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2460 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002461
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002462 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2463 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002464
Antoine Pitrou243757e2010-11-05 21:15:39 +00002465 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2466
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002467 {NULL, NULL}
2468};
2469
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002470static PyGetSetDef bufferedrwpair_getset[] = {
2471 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002472 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002473};
2474
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002475PyTypeObject PyBufferedRWPair_Type = {
2476 PyVarObject_HEAD_INIT(NULL, 0)
2477 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002478 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002479 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002480 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002481 0, /*tp_print*/
2482 0, /*tp_getattr*/
2483 0, /*tp_setattr*/
2484 0, /*tp_compare */
2485 0, /*tp_repr*/
2486 0, /*tp_as_number*/
2487 0, /*tp_as_sequence*/
2488 0, /*tp_as_mapping*/
2489 0, /*tp_hash */
2490 0, /*tp_call*/
2491 0, /*tp_str*/
2492 0, /*tp_getattro*/
2493 0, /*tp_setattro*/
2494 0, /*tp_as_buffer*/
2495 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002496 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002497 bufferedrwpair_doc, /* tp_doc */
2498 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2499 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002500 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002501 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002502 0, /* tp_iter */
2503 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002504 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002505 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002506 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002507 0, /* tp_base */
2508 0, /* tp_dict */
2509 0, /* tp_descr_get */
2510 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002511 offsetof(rwpair, dict), /* tp_dictoffset */
2512 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002513 0, /* tp_alloc */
2514 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002515 0, /* tp_free */
2516 0, /* tp_is_gc */
2517 0, /* tp_bases */
2518 0, /* tp_mro */
2519 0, /* tp_cache */
2520 0, /* tp_subclasses */
2521 0, /* tp_weaklist */
2522 0, /* tp_del */
2523 0, /* tp_version_tag */
2524 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002525};
2526
2527
2528
2529/*
2530 * BufferedRandom
2531 */
2532
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002533PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002534 "A buffered interface to random access streams.\n"
2535 "\n"
2536 "The constructor creates a reader and writer for a seekable stream,\n"
2537 "raw, given in the first argument. If the buffer_size is omitted it\n"
Florent Xicluna109d5732012-07-07 17:03:22 +02002538 "defaults to DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002539 );
2540
2541static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002542bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002543{
Florent Xicluna109d5732012-07-07 17:03:22 +02002544 char *kwlist[] = {"raw", "buffer_size", NULL};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002545 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002546 PyObject *raw;
2547
2548 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002549 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002550
R David Murray9f10f562013-02-23 22:07:55 -05002551 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedRandom", kwlist,
Florent Xicluna109d5732012-07-07 17:03:22 +02002552 &raw, &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002553 return -1;
2554 }
2555
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002556 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002557 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002558 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002559 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002560 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002561 return -1;
2562
2563 Py_CLEAR(self->raw);
2564 Py_INCREF(raw);
2565 self->raw = raw;
2566 self->buffer_size = buffer_size;
2567 self->readable = 1;
2568 self->writable = 1;
2569
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002570 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002571 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002572 _bufferedreader_reset_buf(self);
2573 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002574 self->pos = 0;
2575
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002576 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2577 Py_TYPE(raw) == &PyFileIO_Type);
2578
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002579 self->ok = 1;
2580 return 0;
2581}
2582
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002583static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002584 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002585 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2586 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2587 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2588 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2589 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2590 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2591 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002592 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002593 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002594
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002595 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002596
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002597 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2598 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2599 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2600 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2601 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2602 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Petersona96fea02014-06-22 14:17:44 -07002603 {"readinto1", (PyCFunction)buffered_readinto1, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002604 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2605 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2606 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002607 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002608 {NULL, NULL}
2609};
2610
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002611static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002612 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02002613 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002614 {NULL}
2615};
2616
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002617static PyGetSetDef bufferedrandom_getset[] = {
2618 {"closed", (getter)buffered_closed_get, NULL, NULL},
2619 {"name", (getter)buffered_name_get, NULL, NULL},
2620 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002621 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002622};
2623
2624
2625PyTypeObject PyBufferedRandom_Type = {
2626 PyVarObject_HEAD_INIT(NULL, 0)
2627 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002628 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002629 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002630 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002631 0, /*tp_print*/
2632 0, /*tp_getattr*/
2633 0, /*tp_setattr*/
2634 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002635 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002636 0, /*tp_as_number*/
2637 0, /*tp_as_sequence*/
2638 0, /*tp_as_mapping*/
2639 0, /*tp_hash */
2640 0, /*tp_call*/
2641 0, /*tp_str*/
2642 0, /*tp_getattro*/
2643 0, /*tp_setattro*/
2644 0, /*tp_as_buffer*/
2645 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002646 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002647 bufferedrandom_doc, /* tp_doc */
2648 (traverseproc)buffered_traverse, /* tp_traverse */
2649 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002650 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002651 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002652 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002653 (iternextfunc)buffered_iternext, /* tp_iternext */
2654 bufferedrandom_methods, /* tp_methods */
2655 bufferedrandom_members, /* tp_members */
2656 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002657 0, /* tp_base */
2658 0, /*tp_dict*/
2659 0, /* tp_descr_get */
2660 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002661 offsetof(buffered, dict), /*tp_dictoffset*/
2662 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002663 0, /* tp_alloc */
2664 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002665 0, /* tp_free */
2666 0, /* tp_is_gc */
2667 0, /* tp_bases */
2668 0, /* tp_mro */
2669 0, /* tp_cache */
2670 0, /* tp_subclasses */
2671 0, /* tp_weaklist */
2672 0, /* tp_del */
2673 0, /* tp_version_tag */
2674 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002675};