blob: 692ce41cf99a9a5727c86fcb3c821c296767e58d [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#ifdef Py_DEBUG
684 /* in debug mode, PyEval_EvalFrameEx() fails with an assertion error
685 if an exception is set when it is called */
686 PyErr_Clear();
687#endif
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100688 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
689 errno, msg, written);
690 if (err)
691 PyErr_SetObject(PyExc_BlockingIOError, err);
692 Py_XDECREF(err);
693}
694
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000695/* Returns the address of the `written` member if a BlockingIOError was
696 raised, NULL otherwise. The error is always re-raised. */
697static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000698_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000699{
700 PyObject *t, *v, *tb;
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200701 PyOSErrorObject *err;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000702
703 PyErr_Fetch(&t, &v, &tb);
704 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
705 PyErr_Restore(t, v, tb);
706 return NULL;
707 }
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200708 err = (PyOSErrorObject *) v;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000709 /* TODO: sanity check (err->written >= 0) */
710 PyErr_Restore(t, v, tb);
711 return &err->written;
712}
713
714static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000715_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000716{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000717 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000718 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000719 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
720 if (res == NULL)
721 return -1;
722 n = PyNumber_AsOff_t(res, PyExc_ValueError);
723 Py_DECREF(res);
724 if (n < 0) {
725 if (!PyErr_Occurred())
726 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000727 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200728 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000729 return -1;
730 }
731 self->abs_pos = n;
732 return n;
733}
734
735static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000736_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000737{
738 PyObject *res, *posobj, *whenceobj;
739 Py_off_t n;
740
741 posobj = PyLong_FromOff_t(target);
742 if (posobj == NULL)
743 return -1;
744 whenceobj = PyLong_FromLong(whence);
745 if (whenceobj == NULL) {
746 Py_DECREF(posobj);
747 return -1;
748 }
749 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
750 posobj, whenceobj, NULL);
751 Py_DECREF(posobj);
752 Py_DECREF(whenceobj);
753 if (res == NULL)
754 return -1;
755 n = PyNumber_AsOff_t(res, PyExc_ValueError);
756 Py_DECREF(res);
757 if (n < 0) {
758 if (!PyErr_Occurred())
759 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000760 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200761 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000762 return -1;
763 }
764 self->abs_pos = n;
765 return n;
766}
767
768static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000769_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000770{
771 Py_ssize_t n;
772 if (self->buffer_size <= 0) {
773 PyErr_SetString(PyExc_ValueError,
774 "buffer size must be strictly positive");
775 return -1;
776 }
777 if (self->buffer)
778 PyMem_Free(self->buffer);
779 self->buffer = PyMem_Malloc(self->buffer_size);
780 if (self->buffer == NULL) {
781 PyErr_NoMemory();
782 return -1;
783 }
Georg Brandldfd73442009-04-05 11:47:34 +0000784#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000785 if (self->lock)
786 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000787 self->lock = PyThread_allocate_lock();
788 if (self->lock == NULL) {
789 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
790 return -1;
791 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000792 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000793#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000794 /* Find out whether buffer_size is a power of 2 */
795 /* XXX is this optimization useful? */
796 for (n = self->buffer_size - 1; n & 1; n >>= 1)
797 ;
798 if (n == 0)
799 self->buffer_mask = self->buffer_size - 1;
800 else
801 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000802 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000803 PyErr_Clear();
804 return 0;
805}
806
Antoine Pitrou707ce822011-02-25 21:24:11 +0000807/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
808 clears the error indicator), 0 otherwise.
809 Should only be called when PyErr_Occurred() is true.
810*/
Gregory P. Smith51359922012-06-23 23:55:39 -0700811int
812_PyIO_trap_eintr(void)
Antoine Pitrou707ce822011-02-25 21:24:11 +0000813{
814 static PyObject *eintr_int = NULL;
815 PyObject *typ, *val, *tb;
816 PyEnvironmentErrorObject *env_err;
817
818 if (eintr_int == NULL) {
819 eintr_int = PyLong_FromLong(EINTR);
820 assert(eintr_int != NULL);
821 }
822 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
823 return 0;
824 PyErr_Fetch(&typ, &val, &tb);
825 PyErr_NormalizeException(&typ, &val, &tb);
826 env_err = (PyEnvironmentErrorObject *) val;
827 assert(env_err != NULL);
828 if (env_err->myerrno != NULL &&
829 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
830 Py_DECREF(typ);
831 Py_DECREF(val);
832 Py_XDECREF(tb);
833 return 1;
834 }
835 /* This silences any error set by PyObject_RichCompareBool() */
836 PyErr_Restore(typ, val, tb);
837 return 0;
838}
839
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000840/*
841 * Shared methods and wrappers
842 */
843
844static PyObject *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200845buffered_flush_and_rewind_unlocked(buffered *self)
846{
847 PyObject *res;
848
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100849 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200850 if (res == NULL)
851 return NULL;
852 Py_DECREF(res);
853
854 if (self->readable) {
855 /* Rewind the raw stream so that its position corresponds to
856 the current logical position. */
857 Py_off_t n;
858 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
859 _bufferedreader_reset_buf(self);
860 if (n == -1)
861 return NULL;
862 }
863 Py_RETURN_NONE;
864}
865
866static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000867buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000868{
869 PyObject *res;
870
871 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000872 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000873
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000874 if (!ENTER_BUFFERED(self))
875 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200876 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000877 LEAVE_BUFFERED(self)
878
879 return res;
880}
881
882static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000883buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000884{
885 Py_ssize_t n = 0;
886 PyObject *res = NULL;
887
888 CHECK_INITIALIZED(self)
889 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
890 return NULL;
891 }
892
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000893 if (!ENTER_BUFFERED(self))
894 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000895
896 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200897 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000898 if (res == NULL)
899 goto end;
900 Py_CLEAR(res);
901 }
Victor Stinnerbc93a112011-06-01 00:01:24 +0200902 res = _bufferedreader_peek_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000903
904end:
905 LEAVE_BUFFERED(self)
906 return res;
907}
908
909static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000910buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000911{
912 Py_ssize_t n = -1;
913 PyObject *res;
914
915 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000916 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000917 return NULL;
918 }
919 if (n < -1) {
920 PyErr_SetString(PyExc_ValueError,
921 "read length must be positive or -1");
922 return NULL;
923 }
924
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000925 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000926
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000927 if (n == -1) {
928 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000929 if (!ENTER_BUFFERED(self))
930 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000931 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000932 }
933 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000934 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200935 if (res != Py_None)
936 return res;
937 Py_DECREF(res);
938 if (!ENTER_BUFFERED(self))
939 return NULL;
940 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000941 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000942
Antoine Pitroue05565e2011-08-20 14:39:23 +0200943 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000944 return res;
945}
946
947static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000948buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000949{
950 Py_ssize_t n, have, r;
951 PyObject *res = NULL;
952
953 CHECK_INITIALIZED(self)
954 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
955 return NULL;
956 }
957
958 if (n < 0) {
959 PyErr_SetString(PyExc_ValueError,
960 "read length must be positive");
961 return NULL;
962 }
963 if (n == 0)
964 return PyBytes_FromStringAndSize(NULL, 0);
965
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000966 /* Return up to n bytes. If at least one byte is buffered, we
967 only return buffered bytes. Otherwise, we do one raw read. */
968
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000969 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
970 if (have > 0) {
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100971 n = Py_MIN(have, n);
972 res = _bufferedreader_read_fast(self, n);
973 assert(res != Py_None);
974 return res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000975 }
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100976 res = PyBytes_FromStringAndSize(NULL, n);
977 if (res == NULL)
978 return NULL;
979 if (!ENTER_BUFFERED(self)) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200980 Py_DECREF(res);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100981 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200982 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000983 _bufferedreader_reset_buf(self);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100984 r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
985 LEAVE_BUFFERED(self)
986 if (r == -1) {
987 Py_DECREF(res);
988 return NULL;
989 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000990 if (r == -2)
991 r = 0;
992 if (n > r)
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100993 _PyBytes_Resize(&res, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000994 return res;
995}
996
997static PyObject *
Benjamin Petersona96fea02014-06-22 14:17:44 -0700998_buffered_readinto_generic(buffered *self, PyObject *args, char readinto1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000999{
Antoine Pitrou3486a982011-05-12 01:57:53 +02001000 Py_buffer buf;
1001 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001002 PyObject *res = NULL;
1003
1004 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +02001005
Benjamin Petersona96fea02014-06-22 14:17:44 -07001006 if (!PyArg_ParseTuple(args,
1007 readinto1 ? "w*:readinto1" : "w*:readinto",
1008 &buf))
Antoine Pitrou3486a982011-05-12 01:57:53 +02001009 return NULL;
1010
1011 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1012 if (n > 0) {
1013 if (n >= buf.len) {
1014 memcpy(buf.buf, self->buffer + self->pos, buf.len);
1015 self->pos += buf.len;
1016 res = PyLong_FromSsize_t(buf.len);
1017 goto end_unlocked;
1018 }
1019 memcpy(buf.buf, self->buffer + self->pos, n);
1020 self->pos += n;
1021 written = n;
1022 }
1023
1024 if (!ENTER_BUFFERED(self))
1025 goto end_unlocked;
1026
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001027 if (self->writable) {
Antoine Pitroue8bb1a02011-08-20 14:52:04 +02001028 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001029 if (res == NULL)
1030 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +02001031 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001032 }
Antoine Pitrou3486a982011-05-12 01:57:53 +02001033
1034 _bufferedreader_reset_buf(self);
1035 self->pos = 0;
1036
1037 for (remaining = buf.len - written;
1038 remaining > 0;
1039 written += n, remaining -= n) {
1040 /* If remaining bytes is larger than internal buffer size, copy
1041 * directly into caller's buffer. */
1042 if (remaining > self->buffer_size) {
Antoine Pitrou4e19e112011-05-12 02:07:00 +02001043 n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
1044 remaining);
Antoine Pitrou3486a982011-05-12 01:57:53 +02001045 }
Benjamin Petersona96fea02014-06-22 14:17:44 -07001046
1047 /* In readinto1 mode, we do not want to fill the internal
1048 buffer if we already have some data to return */
1049 else if (!(readinto1 && written)) {
Antoine Pitrou3486a982011-05-12 01:57:53 +02001050 n = _bufferedreader_fill_buffer(self);
1051 if (n > 0) {
1052 if (n > remaining)
1053 n = remaining;
Antoine Pitrou4e19e112011-05-12 02:07:00 +02001054 memcpy((char *) buf.buf + written,
1055 self->buffer + self->pos, n);
Antoine Pitrou3486a982011-05-12 01:57:53 +02001056 self->pos += n;
1057 continue; /* short circuit */
1058 }
1059 }
Benjamin Petersona96fea02014-06-22 14:17:44 -07001060 else
1061 n = 0;
1062
Antoine Pitrou3486a982011-05-12 01:57:53 +02001063 if (n == 0 || (n == -2 && written > 0))
1064 break;
1065 if (n < 0) {
1066 if (n == -2) {
1067 Py_INCREF(Py_None);
1068 res = Py_None;
1069 }
1070 goto end;
1071 }
Benjamin Petersona96fea02014-06-22 14:17:44 -07001072
1073 /* At most one read in readinto1 mode */
1074 if (readinto1) {
1075 written += n;
1076 break;
1077 }
Antoine Pitrou3486a982011-05-12 01:57:53 +02001078 }
1079 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001080
1081end:
Antoine Pitrou3486a982011-05-12 01:57:53 +02001082 LEAVE_BUFFERED(self);
1083end_unlocked:
1084 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001085 return res;
1086}
1087
1088static PyObject *
Benjamin Petersona96fea02014-06-22 14:17:44 -07001089buffered_readinto(buffered *self, PyObject *args)
1090{
1091 return _buffered_readinto_generic(self, args, 0);
1092}
1093
1094static PyObject *
1095buffered_readinto1(buffered *self, PyObject *args)
1096{
1097 return _buffered_readinto_generic(self, args, 1);
1098}
1099
1100
1101static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001102_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001103{
1104 PyObject *res = NULL;
1105 PyObject *chunks = NULL;
1106 Py_ssize_t n, written = 0;
1107 const char *start, *s, *end;
1108
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001109 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001110
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001111 /* First, try to find a line in the buffer. This can run unlocked because
1112 the calls to the C API are simple enough that they can't trigger
1113 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001114 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1115 if (limit >= 0 && n > limit)
1116 n = limit;
1117 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001118 s = memchr(start, '\n', n);
1119 if (s != NULL) {
1120 res = PyBytes_FromStringAndSize(start, s - start + 1);
1121 if (res != NULL)
1122 self->pos += s - start + 1;
1123 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001124 }
1125 if (n == limit) {
1126 res = PyBytes_FromStringAndSize(start, n);
1127 if (res != NULL)
1128 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001129 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001130 }
1131
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001132 if (!ENTER_BUFFERED(self))
1133 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001134
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001135 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001136 chunks = PyList_New(0);
1137 if (chunks == NULL)
1138 goto end;
1139 if (n > 0) {
1140 res = PyBytes_FromStringAndSize(start, n);
1141 if (res == NULL)
1142 goto end;
1143 if (PyList_Append(chunks, res) < 0) {
1144 Py_CLEAR(res);
1145 goto end;
1146 }
1147 Py_CLEAR(res);
1148 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001149 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001150 if (limit >= 0)
1151 limit -= n;
1152 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001153 if (self->writable) {
1154 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1155 if (r == NULL)
1156 goto end;
1157 Py_DECREF(r);
1158 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001159
1160 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001161 _bufferedreader_reset_buf(self);
1162 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001163 if (n == -1)
1164 goto end;
1165 if (n <= 0)
1166 break;
1167 if (limit >= 0 && n > limit)
1168 n = limit;
1169 start = self->buffer;
1170 end = start + n;
1171 s = start;
1172 while (s < end) {
1173 if (*s++ == '\n') {
1174 res = PyBytes_FromStringAndSize(start, s - start);
1175 if (res == NULL)
1176 goto end;
1177 self->pos = s - start;
1178 goto found;
1179 }
1180 }
1181 res = PyBytes_FromStringAndSize(start, n);
1182 if (res == NULL)
1183 goto end;
1184 if (n == limit) {
1185 self->pos = n;
1186 break;
1187 }
1188 if (PyList_Append(chunks, res) < 0) {
1189 Py_CLEAR(res);
1190 goto end;
1191 }
1192 Py_CLEAR(res);
1193 written += n;
1194 if (limit >= 0)
1195 limit -= n;
1196 }
1197found:
1198 if (res != NULL && PyList_Append(chunks, res) < 0) {
1199 Py_CLEAR(res);
1200 goto end;
1201 }
1202 Py_CLEAR(res);
1203 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1204
1205end:
1206 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001207end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001208 Py_XDECREF(chunks);
1209 return res;
1210}
1211
1212static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001213buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001214{
1215 Py_ssize_t limit = -1;
1216
1217 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001218 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001219 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001220 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001221}
1222
1223
1224static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001225buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001226{
1227 Py_off_t pos;
1228
1229 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001230 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001231 if (pos == -1)
1232 return NULL;
1233 pos -= RAW_OFFSET(self);
1234 /* TODO: sanity check (pos >= 0) */
1235 return PyLong_FromOff_t(pos);
1236}
1237
1238static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001239buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001240{
1241 Py_off_t target, n;
1242 int whence = 0;
1243 PyObject *targetobj, *res = NULL;
1244
1245 CHECK_INITIALIZED(self)
1246 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1247 return NULL;
1248 }
Jesus Cea94363612012-06-22 18:32:07 +02001249
1250 /* Do some error checking instead of trusting OS 'seek()'
1251 ** error detection, just in case.
1252 */
1253 if ((whence < 0 || whence >2)
1254#ifdef SEEK_HOLE
1255 && (whence != SEEK_HOLE)
1256#endif
1257#ifdef SEEK_DATA
1258 && (whence != SEEK_DATA)
1259#endif
1260 ) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001261 PyErr_Format(PyExc_ValueError,
Jesus Cea94363612012-06-22 18:32:07 +02001262 "whence value %d unsupported", whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001263 return NULL;
1264 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001265
1266 CHECK_CLOSED(self, "seek of closed file")
1267
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001268 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1269 return NULL;
1270
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001271 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1272 if (target == -1 && PyErr_Occurred())
1273 return NULL;
1274
Jesus Cea94363612012-06-22 18:32:07 +02001275 /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1276 buffer. Other whence values must be managed without this optimization.
1277 Some Operating Systems can provide additional values, like
1278 SEEK_HOLE/SEEK_DATA. */
1279 if (((whence == 0) || (whence == 1)) && self->readable) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001280 Py_off_t current, avail;
1281 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001282 so as to return quickly if possible. Also, we needn't take the
1283 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001284 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001285 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1286 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001287 current = RAW_TELL(self);
1288 avail = READAHEAD(self);
1289 if (avail > 0) {
1290 Py_off_t offset;
1291 if (whence == 0)
1292 offset = target - (current - RAW_OFFSET(self));
1293 else
1294 offset = target;
1295 if (offset >= -self->pos && offset <= avail) {
1296 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001297 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001298 }
1299 }
1300 }
1301
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001302 if (!ENTER_BUFFERED(self))
1303 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001304
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001305 /* Fallback: invoke raw seek() method and clear buffer */
1306 if (self->writable) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001307 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001308 if (res == NULL)
1309 goto end;
1310 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001311 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001312 }
1313
1314 /* TODO: align on block boundary and read buffer if needed? */
1315 if (whence == 1)
1316 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001317 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001318 if (n == -1)
1319 goto end;
1320 self->raw_pos = -1;
1321 res = PyLong_FromOff_t(n);
1322 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001323 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001324
1325end:
1326 LEAVE_BUFFERED(self)
1327 return res;
1328}
1329
1330static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001331buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001332{
1333 PyObject *pos = Py_None;
1334 PyObject *res = NULL;
1335
1336 CHECK_INITIALIZED(self)
1337 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1338 return NULL;
1339 }
1340
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001341 if (!ENTER_BUFFERED(self))
1342 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001343
1344 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001345 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001346 if (res == NULL)
1347 goto end;
1348 Py_CLEAR(res);
1349 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001350 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1351 if (res == NULL)
1352 goto end;
1353 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001354 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001355 PyErr_Clear();
1356
1357end:
1358 LEAVE_BUFFERED(self)
1359 return res;
1360}
1361
1362static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001363buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001364{
1365 PyObject *line;
1366 PyTypeObject *tp;
1367
1368 CHECK_INITIALIZED(self);
1369
1370 tp = Py_TYPE(self);
1371 if (tp == &PyBufferedReader_Type ||
1372 tp == &PyBufferedRandom_Type) {
1373 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001374 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001375 }
1376 else {
1377 line = PyObject_CallMethodObjArgs((PyObject *)self,
1378 _PyIO_str_readline, NULL);
1379 if (line && !PyBytes_Check(line)) {
1380 PyErr_Format(PyExc_IOError,
1381 "readline() should have returned a bytes object, "
1382 "not '%.200s'", Py_TYPE(line)->tp_name);
1383 Py_DECREF(line);
1384 return NULL;
1385 }
1386 }
1387
1388 if (line == NULL)
1389 return NULL;
1390
1391 if (PyBytes_GET_SIZE(line) == 0) {
1392 /* Reached EOF or would have blocked */
1393 Py_DECREF(line);
1394 return NULL;
1395 }
1396
1397 return line;
1398}
1399
Antoine Pitrou716c4442009-05-23 19:04:03 +00001400static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001401buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001402{
1403 PyObject *nameobj, *res;
1404
Martin v. Löwis767046a2011-10-14 15:35:36 +02001405 nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
Antoine Pitrou716c4442009-05-23 19:04:03 +00001406 if (nameobj == NULL) {
Benjamin Peterson10e76b62014-12-21 20:51:50 -06001407 if (PyErr_ExceptionMatches(PyExc_Exception))
Antoine Pitrou716c4442009-05-23 19:04:03 +00001408 PyErr_Clear();
1409 else
1410 return NULL;
1411 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1412 }
1413 else {
1414 res = PyUnicode_FromFormat("<%s name=%R>",
1415 Py_TYPE(self)->tp_name, nameobj);
1416 Py_DECREF(nameobj);
1417 }
1418 return res;
1419}
1420
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001421/*
1422 * class BufferedReader
1423 */
1424
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001425PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001426 "Create a new buffered reader using the given readable raw IO object.");
1427
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001428static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001429{
1430 self->read_end = -1;
1431}
1432
1433static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001434bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001435{
1436 char *kwlist[] = {"raw", "buffer_size", NULL};
1437 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1438 PyObject *raw;
1439
1440 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001441 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001442
1443 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1444 &raw, &buffer_size)) {
1445 return -1;
1446 }
1447
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001448 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001449 return -1;
1450
1451 Py_CLEAR(self->raw);
1452 Py_INCREF(raw);
1453 self->raw = raw;
1454 self->buffer_size = buffer_size;
1455 self->readable = 1;
1456 self->writable = 0;
1457
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001458 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001459 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001460 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001461
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001462 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1463 Py_TYPE(raw) == &PyFileIO_Type);
1464
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001465 self->ok = 1;
1466 return 0;
1467}
1468
1469static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001470_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001471{
1472 Py_buffer buf;
1473 PyObject *memobj, *res;
1474 Py_ssize_t n;
1475 /* NOTE: the buffer needn't be released as its object is NULL. */
1476 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1477 return -1;
1478 memobj = PyMemoryView_FromBuffer(&buf);
1479 if (memobj == NULL)
1480 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001481 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1482 occurs so we needn't do it ourselves.
1483 We then retry reading, ignoring the signal if no handler has
1484 raised (see issue #10956).
1485 */
1486 do {
1487 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
Gregory P. Smith51359922012-06-23 23:55:39 -07001488 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001489 Py_DECREF(memobj);
1490 if (res == NULL)
1491 return -1;
1492 if (res == Py_None) {
1493 /* Non-blocking stream would have blocked. Special return code! */
1494 Py_DECREF(res);
1495 return -2;
1496 }
1497 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1498 Py_DECREF(res);
1499 if (n < 0 || n > len) {
1500 PyErr_Format(PyExc_IOError,
1501 "raw readinto() returned invalid length %zd "
1502 "(should have been between 0 and %zd)", n, len);
1503 return -1;
1504 }
1505 if (n > 0 && self->abs_pos != -1)
1506 self->abs_pos += n;
1507 return n;
1508}
1509
1510static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001511_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001512{
1513 Py_ssize_t start, len, n;
1514 if (VALID_READ_BUFFER(self))
1515 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1516 else
1517 start = 0;
1518 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001519 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001520 if (n <= 0)
1521 return n;
1522 self->read_end = start + n;
1523 self->raw_pos = start + n;
1524 return n;
1525}
1526
1527static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001528_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001529{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001530 Py_ssize_t current_size;
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001531 PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001532
1533 /* First copy what we have in the current buffer. */
1534 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1535 if (current_size) {
1536 data = PyBytes_FromStringAndSize(
1537 self->buffer + self->pos, current_size);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001538 if (data == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001539 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001540 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001541 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001542 /* We're going past the buffer's bounds, flush it */
1543 if (self->writable) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001544 tmp = buffered_flush_and_rewind_unlocked(self);
1545 if (tmp == NULL)
1546 goto cleanup;
1547 Py_CLEAR(tmp);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001548 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001549 _bufferedreader_reset_buf(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001550
1551 if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001552 tmp = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
1553 if (tmp == NULL)
1554 goto cleanup;
1555 if (tmp != Py_None && !PyBytes_Check(tmp)) {
Victor Stinnerb57f1082011-05-26 00:19:38 +02001556 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001557 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001558 }
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001559 if (tmp == Py_None) {
1560 if (current_size == 0) {
1561 res = Py_None;
1562 goto cleanup;
1563 } else {
1564 res = data;
1565 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001566 }
1567 }
1568 else if (current_size) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001569 PyBytes_Concat(&data, tmp);
1570 res = data;
1571 goto cleanup;
1572 }
1573 else {
1574 res = tmp;
1575 goto cleanup;
1576 }
Victor Stinnerb57f1082011-05-26 00:19:38 +02001577 }
1578
1579 chunks = PyList_New(0);
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001580 if (chunks == NULL)
1581 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001582
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001583 while (1) {
1584 if (data) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001585 if (PyList_Append(chunks, data) < 0)
1586 goto cleanup;
1587 Py_CLEAR(data);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001588 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001589
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001590 /* Read until EOF or until read() would block. */
1591 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001592 if (data == NULL)
1593 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001594 if (data != Py_None && !PyBytes_Check(data)) {
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001595 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001596 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001597 }
1598 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1599 if (current_size == 0) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001600 res = data;
1601 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001602 }
1603 else {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001604 tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1605 res = tmp;
1606 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001607 }
1608 }
1609 current_size += PyBytes_GET_SIZE(data);
1610 if (self->abs_pos != -1)
1611 self->abs_pos += PyBytes_GET_SIZE(data);
1612 }
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001613cleanup:
1614 /* res is either NULL or a borrowed ref */
1615 Py_XINCREF(res);
1616 Py_XDECREF(data);
1617 Py_XDECREF(tmp);
1618 Py_XDECREF(chunks);
1619 return res;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001620}
1621
1622/* Read n bytes from the buffer if it can, otherwise return None.
1623 This function is simple enough that it can run unlocked. */
1624static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001625_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001626{
1627 Py_ssize_t current_size;
1628
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001629 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1630 if (n <= current_size) {
1631 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001632 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1633 if (res != NULL)
1634 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001635 return res;
1636 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001637 Py_RETURN_NONE;
1638}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001639
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001640/* Generic read function: read from the stream until enough bytes are read,
1641 * or until an EOF occurs or until read() would block.
1642 */
1643static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001644_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001645{
1646 PyObject *res = NULL;
1647 Py_ssize_t current_size, remaining, written;
1648 char *out;
1649
1650 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1651 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001652 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001653
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001654 res = PyBytes_FromStringAndSize(NULL, n);
1655 if (res == NULL)
1656 goto error;
1657 out = PyBytes_AS_STRING(res);
1658 remaining = n;
1659 written = 0;
1660 if (current_size > 0) {
1661 memcpy(out, self->buffer + self->pos, current_size);
1662 remaining -= current_size;
1663 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001664 self->pos += current_size;
1665 }
1666 /* Flush the write buffer if necessary */
1667 if (self->writable) {
1668 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1669 if (r == NULL)
1670 goto error;
1671 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001672 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001673 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001674 while (remaining > 0) {
1675 /* We want to read a whole block at the end into buffer.
1676 If we had readv() we could do this in one pass. */
1677 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1678 if (r == 0)
1679 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001680 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001681 if (r == -1)
1682 goto error;
1683 if (r == 0 || r == -2) {
1684 /* EOF occurred or read() would block. */
1685 if (r == 0 || written > 0) {
1686 if (_PyBytes_Resize(&res, written))
1687 goto error;
1688 return res;
1689 }
1690 Py_DECREF(res);
1691 Py_INCREF(Py_None);
1692 return Py_None;
1693 }
1694 remaining -= r;
1695 written += r;
1696 }
1697 assert(remaining <= self->buffer_size);
1698 self->pos = 0;
1699 self->raw_pos = 0;
1700 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001701 /* NOTE: when the read is satisfied, we avoid issuing any additional
1702 reads, which could block indefinitely (e.g. on a socket).
1703 See issue #9550. */
1704 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001705 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001706 if (r == -1)
1707 goto error;
1708 if (r == 0 || r == -2) {
1709 /* EOF occurred or read() would block. */
1710 if (r == 0 || written > 0) {
1711 if (_PyBytes_Resize(&res, written))
1712 goto error;
1713 return res;
1714 }
1715 Py_DECREF(res);
1716 Py_INCREF(Py_None);
1717 return Py_None;
1718 }
1719 if (remaining > r) {
1720 memcpy(out + written, self->buffer + self->pos, r);
1721 written += r;
1722 self->pos += r;
1723 remaining -= r;
1724 }
1725 else if (remaining > 0) {
1726 memcpy(out + written, self->buffer + self->pos, remaining);
1727 written += remaining;
1728 self->pos += remaining;
1729 remaining = 0;
1730 }
1731 if (remaining == 0)
1732 break;
1733 }
1734
1735 return res;
1736
1737error:
1738 Py_XDECREF(res);
1739 return NULL;
1740}
1741
1742static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +02001743_bufferedreader_peek_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001744{
1745 Py_ssize_t have, r;
1746
1747 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1748 /* Constraints:
1749 1. we don't want to advance the file position.
1750 2. we don't want to lose block alignment, so we can't shift the buffer
1751 to make some place.
1752 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1753 */
1754 if (have > 0) {
1755 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1756 }
1757
1758 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001759 _bufferedreader_reset_buf(self);
1760 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001761 if (r == -1)
1762 return NULL;
1763 if (r == -2)
1764 r = 0;
1765 self->pos = 0;
1766 return PyBytes_FromStringAndSize(self->buffer, r);
1767}
1768
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001769static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001770 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001771 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1772 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1773 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1774 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1775 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1776 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1777 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1778 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001779 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001780 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001781
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001782 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1783 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1784 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001785 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Petersona96fea02014-06-22 14:17:44 -07001786 {"readinto1", (PyCFunction)buffered_readinto1, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001787 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1788 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1789 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1790 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02001791 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001792 {NULL, NULL}
1793};
1794
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001795static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001796 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02001797 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001798 {NULL}
1799};
1800
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001801static PyGetSetDef bufferedreader_getset[] = {
1802 {"closed", (getter)buffered_closed_get, NULL, NULL},
1803 {"name", (getter)buffered_name_get, NULL, NULL},
1804 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001805 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001806};
1807
1808
1809PyTypeObject PyBufferedReader_Type = {
1810 PyVarObject_HEAD_INIT(NULL, 0)
1811 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001812 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001813 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001814 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001815 0, /*tp_print*/
1816 0, /*tp_getattr*/
1817 0, /*tp_setattr*/
1818 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001819 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001820 0, /*tp_as_number*/
1821 0, /*tp_as_sequence*/
1822 0, /*tp_as_mapping*/
1823 0, /*tp_hash */
1824 0, /*tp_call*/
1825 0, /*tp_str*/
1826 0, /*tp_getattro*/
1827 0, /*tp_setattro*/
1828 0, /*tp_as_buffer*/
1829 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02001830 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001831 bufferedreader_doc, /* tp_doc */
1832 (traverseproc)buffered_traverse, /* tp_traverse */
1833 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001834 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001835 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001836 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001837 (iternextfunc)buffered_iternext, /* tp_iternext */
1838 bufferedreader_methods, /* tp_methods */
1839 bufferedreader_members, /* tp_members */
1840 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001841 0, /* tp_base */
1842 0, /* tp_dict */
1843 0, /* tp_descr_get */
1844 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001845 offsetof(buffered, dict), /* tp_dictoffset */
1846 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001847 0, /* tp_alloc */
1848 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02001849 0, /* tp_free */
1850 0, /* tp_is_gc */
1851 0, /* tp_bases */
1852 0, /* tp_mro */
1853 0, /* tp_cache */
1854 0, /* tp_subclasses */
1855 0, /* tp_weaklist */
1856 0, /* tp_del */
1857 0, /* tp_version_tag */
1858 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001859};
1860
1861
Benjamin Peterson59406a92009-03-26 17:10:29 +00001862
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001863/*
1864 * class BufferedWriter
1865 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001866PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001867 "A buffer for a writeable sequential RawIO object.\n"
1868 "\n"
1869 "The constructor creates a BufferedWriter for the given writeable raw\n"
1870 "stream. If the buffer_size is not given, it defaults to\n"
Florent Xicluna109d5732012-07-07 17:03:22 +02001871 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001872 );
1873
1874static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001875_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001876{
1877 self->write_pos = 0;
1878 self->write_end = -1;
1879}
1880
1881static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001882bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001883{
Florent Xicluna109d5732012-07-07 17:03:22 +02001884 char *kwlist[] = {"raw", "buffer_size", NULL};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001885 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001886 PyObject *raw;
1887
1888 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001889 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001890
R David Murray9f10f562013-02-23 22:07:55 -05001891 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedWriter", kwlist,
Florent Xicluna109d5732012-07-07 17:03:22 +02001892 &raw, &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001893 return -1;
1894 }
1895
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001896 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001897 return -1;
1898
1899 Py_CLEAR(self->raw);
1900 Py_INCREF(raw);
1901 self->raw = raw;
1902 self->readable = 0;
1903 self->writable = 1;
1904
1905 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001906 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001907 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001908 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001909 self->pos = 0;
1910
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001911 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1912 Py_TYPE(raw) == &PyFileIO_Type);
1913
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001914 self->ok = 1;
1915 return 0;
1916}
1917
1918static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001919_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001920{
1921 Py_buffer buf;
1922 PyObject *memobj, *res;
1923 Py_ssize_t n;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001924 int errnum;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001925 /* NOTE: the buffer needn't be released as its object is NULL. */
1926 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1927 return -1;
1928 memobj = PyMemoryView_FromBuffer(&buf);
1929 if (memobj == NULL)
1930 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001931 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1932 occurs so we needn't do it ourselves.
1933 We then retry writing, ignoring the signal if no handler has
1934 raised (see issue #10956).
1935 */
1936 do {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001937 errno = 0;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001938 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001939 errnum = errno;
Gregory P. Smith51359922012-06-23 23:55:39 -07001940 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001941 Py_DECREF(memobj);
1942 if (res == NULL)
1943 return -1;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001944 if (res == Py_None) {
1945 /* Non-blocking stream would have blocked. Special return code!
1946 Being paranoid we reset errno in case it is changed by code
1947 triggered by a decref. errno is used by _set_BlockingIOError(). */
1948 Py_DECREF(res);
1949 errno = errnum;
1950 return -2;
1951 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001952 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1953 Py_DECREF(res);
1954 if (n < 0 || n > len) {
1955 PyErr_Format(PyExc_IOError,
1956 "raw write() returned invalid length %zd "
1957 "(should have been between 0 and %zd)", n, len);
1958 return -1;
1959 }
1960 if (n > 0 && self->abs_pos != -1)
1961 self->abs_pos += n;
1962 return n;
1963}
1964
1965/* `restore_pos` is 1 if we need to restore the raw stream position at
1966 the end, 0 otherwise. */
1967static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001968_bufferedwriter_flush_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001969{
1970 Py_ssize_t written = 0;
1971 Py_off_t n, rewind;
1972
1973 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1974 goto end;
1975 /* First, rewind */
1976 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1977 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001978 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001979 if (n < 0) {
1980 goto error;
1981 }
1982 self->raw_pos -= rewind;
1983 }
1984 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001985 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001986 self->buffer + self->write_pos,
1987 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1988 Py_off_t, Py_ssize_t));
1989 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001990 goto error;
1991 }
1992 else if (n == -2) {
1993 _set_BlockingIOError("write could not complete without blocking",
1994 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001995 goto error;
1996 }
1997 self->write_pos += n;
1998 self->raw_pos = self->write_pos;
1999 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002000 /* Partial writes can return successfully when interrupted by a
2001 signal (see write(2)). We must run signal handlers before
2002 blocking another time, possibly indefinitely. */
2003 if (PyErr_CheckSignals() < 0)
2004 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002005 }
2006
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002007 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002008
2009end:
2010 Py_RETURN_NONE;
2011
2012error:
2013 return NULL;
2014}
2015
2016static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002017bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002018{
2019 PyObject *res = NULL;
2020 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002021 Py_ssize_t written, avail, remaining;
2022 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002023
2024 CHECK_INITIALIZED(self)
2025 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
2026 return NULL;
2027 }
2028
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002029 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002030 PyErr_SetString(PyExc_ValueError, "write to closed file");
2031 PyBuffer_Release(&buf);
2032 return NULL;
2033 }
2034
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00002035 if (!ENTER_BUFFERED(self)) {
2036 PyBuffer_Release(&buf);
2037 return NULL;
2038 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002039
2040 /* Fast path: the data to write can be fully buffered. */
2041 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
2042 self->pos = 0;
2043 self->raw_pos = 0;
2044 }
2045 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
2046 if (buf.len <= avail) {
2047 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02002048 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002049 self->write_pos = self->pos;
2050 }
2051 ADJUST_POSITION(self, self->pos + buf.len);
2052 if (self->pos > self->write_end)
2053 self->write_end = self->pos;
2054 written = buf.len;
2055 goto end;
2056 }
2057
2058 /* First write the current buffer */
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002059 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002060 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002061 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002062 if (w == NULL)
2063 goto error;
2064 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002065 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002066 /* Make some place by shifting the buffer. */
2067 assert(VALID_WRITE_BUFFER(self));
2068 memmove(self->buffer, self->buffer + self->write_pos,
2069 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2070 Py_off_t, Py_ssize_t));
2071 self->write_end -= self->write_pos;
2072 self->raw_pos -= self->write_pos;
2073 self->pos -= self->write_pos;
2074 self->write_pos = 0;
2075 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
2076 Py_off_t, Py_ssize_t);
2077 if (buf.len <= avail) {
2078 /* Everything can be buffered */
2079 PyErr_Clear();
2080 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
2081 self->write_end += buf.len;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002082 self->pos += buf.len;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002083 written = buf.len;
2084 goto end;
2085 }
2086 /* Buffer as much as possible. */
2087 memcpy(self->buffer + self->write_end, buf.buf, avail);
2088 self->write_end += avail;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002089 self->pos += avail;
2090 /* XXX Modifying the existing exception e using the pointer w
2091 will change e.characters_written but not e.args[2].
2092 Therefore we just replace with a new error. */
2093 _set_BlockingIOError("write could not complete without blocking",
2094 avail);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002095 goto error;
2096 }
2097 Py_CLEAR(res);
2098
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002099 /* Adjust the raw stream position if it is away from the logical stream
2100 position. This happens if the read buffer has been filled but not
2101 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2102 the raw stream by itself).
2103 Fixes issue #6629.
2104 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002105 offset = RAW_OFFSET(self);
2106 if (offset != 0) {
2107 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002108 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002109 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002110 }
2111
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002112 /* Then write buf itself. At this point the buffer has been emptied. */
2113 remaining = buf.len;
2114 written = 0;
2115 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002116 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002117 self, (char *) buf.buf + written, buf.len - written);
2118 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002119 goto error;
2120 } else if (n == -2) {
2121 /* Write failed because raw file is non-blocking */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002122 if (remaining > self->buffer_size) {
2123 /* Can't buffer everything, still buffer as much as possible */
2124 memcpy(self->buffer,
2125 (char *) buf.buf + written, self->buffer_size);
2126 self->raw_pos = 0;
2127 ADJUST_POSITION(self, self->buffer_size);
2128 self->write_end = self->buffer_size;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002129 written += self->buffer_size;
2130 _set_BlockingIOError("write could not complete without "
2131 "blocking", written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002132 goto error;
2133 }
2134 PyErr_Clear();
2135 break;
2136 }
2137 written += n;
2138 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002139 /* Partial writes can return successfully when interrupted by a
2140 signal (see write(2)). We must run signal handlers before
2141 blocking another time, possibly indefinitely. */
2142 if (PyErr_CheckSignals() < 0)
2143 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002144 }
2145 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002146 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002147 if (remaining > 0) {
2148 memcpy(self->buffer, (char *) buf.buf + written, remaining);
2149 written += remaining;
2150 }
2151 self->write_pos = 0;
2152 /* TODO: sanity check (remaining >= 0) */
2153 self->write_end = remaining;
2154 ADJUST_POSITION(self, remaining);
2155 self->raw_pos = 0;
2156
2157end:
2158 res = PyLong_FromSsize_t(written);
2159
2160error:
2161 LEAVE_BUFFERED(self)
2162 PyBuffer_Release(&buf);
2163 return res;
2164}
2165
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002166static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002167 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002168 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2169 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2170 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2171 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2172 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2173 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2174 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002175 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002176 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002177
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002178 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2179 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2180 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2181 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2182 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002183 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002184 {NULL, NULL}
2185};
2186
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002187static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002188 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02002189 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002190 {NULL}
2191};
2192
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002193static PyGetSetDef bufferedwriter_getset[] = {
2194 {"closed", (getter)buffered_closed_get, NULL, NULL},
2195 {"name", (getter)buffered_name_get, NULL, NULL},
2196 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002197 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002198};
2199
2200
2201PyTypeObject PyBufferedWriter_Type = {
2202 PyVarObject_HEAD_INIT(NULL, 0)
2203 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002204 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002205 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002206 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002207 0, /*tp_print*/
2208 0, /*tp_getattr*/
2209 0, /*tp_setattr*/
2210 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002211 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002212 0, /*tp_as_number*/
2213 0, /*tp_as_sequence*/
2214 0, /*tp_as_mapping*/
2215 0, /*tp_hash */
2216 0, /*tp_call*/
2217 0, /*tp_str*/
2218 0, /*tp_getattro*/
2219 0, /*tp_setattro*/
2220 0, /*tp_as_buffer*/
2221 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002222 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002223 bufferedwriter_doc, /* tp_doc */
2224 (traverseproc)buffered_traverse, /* tp_traverse */
2225 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002226 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002227 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002228 0, /* tp_iter */
2229 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002230 bufferedwriter_methods, /* tp_methods */
2231 bufferedwriter_members, /* tp_members */
2232 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002233 0, /* tp_base */
2234 0, /* tp_dict */
2235 0, /* tp_descr_get */
2236 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002237 offsetof(buffered, dict), /* tp_dictoffset */
2238 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002239 0, /* tp_alloc */
2240 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002241 0, /* tp_free */
2242 0, /* tp_is_gc */
2243 0, /* tp_bases */
2244 0, /* tp_mro */
2245 0, /* tp_cache */
2246 0, /* tp_subclasses */
2247 0, /* tp_weaklist */
2248 0, /* tp_del */
2249 0, /* tp_version_tag */
2250 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002251};
2252
2253
2254
2255/*
2256 * BufferedRWPair
2257 */
2258
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002259PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002260 "A buffered reader and writer object together.\n"
2261 "\n"
2262 "A buffered reader object and buffered writer object put together to\n"
2263 "form a sequential IO object that can read and write. This is typically\n"
2264 "used with a socket or two-way pipe.\n"
2265 "\n"
2266 "reader and writer are RawIOBase objects that are readable and\n"
2267 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002268 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002269 );
2270
2271/* XXX The usefulness of this (compared to having two separate IO objects) is
2272 * questionable.
2273 */
2274
2275typedef struct {
2276 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002277 buffered *reader;
2278 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002279 PyObject *dict;
2280 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002281} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002282
2283static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002284bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002285{
2286 PyObject *reader, *writer;
2287 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002288
Florent Xicluna109d5732012-07-07 17:03:22 +02002289 if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer,
2290 &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002291 return -1;
2292 }
2293
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002294 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002295 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002296 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002297 return -1;
2298
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002299 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002300 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002301 if (self->reader == NULL)
2302 return -1;
2303
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002304 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002305 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002306 if (self->writer == NULL) {
2307 Py_CLEAR(self->reader);
2308 return -1;
2309 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002310
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002311 return 0;
2312}
2313
2314static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002315bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002316{
2317 Py_VISIT(self->dict);
2318 return 0;
2319}
2320
2321static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002322bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002323{
2324 Py_CLEAR(self->reader);
2325 Py_CLEAR(self->writer);
2326 Py_CLEAR(self->dict);
2327 return 0;
2328}
2329
2330static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002331bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002332{
2333 _PyObject_GC_UNTRACK(self);
Benjamin Petersonbbd0a322014-09-29 22:46:57 -04002334 if (self->weakreflist != NULL)
2335 PyObject_ClearWeakRefs((PyObject *)self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002336 Py_CLEAR(self->reader);
2337 Py_CLEAR(self->writer);
2338 Py_CLEAR(self->dict);
2339 Py_TYPE(self)->tp_free((PyObject *) self);
2340}
2341
2342static PyObject *
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002343_forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002344{
Serhiy Storchaka61e24932014-02-12 10:52:35 +02002345 PyObject *func, *ret;
2346 if (self == NULL) {
2347 PyErr_SetString(PyExc_ValueError,
2348 "I/O operation on uninitialized object");
2349 return NULL;
2350 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002351
Serhiy Storchaka61e24932014-02-12 10:52:35 +02002352 func = _PyObject_GetAttrId((PyObject *)self, name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002353 if (func == NULL) {
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002354 PyErr_SetString(PyExc_AttributeError, name->string);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002355 return NULL;
2356 }
2357
2358 ret = PyObject_CallObject(func, args);
2359 Py_DECREF(func);
2360 return ret;
2361}
2362
2363static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002364bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002365{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002366 return _forward_call(self->reader, &PyId_read, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002367}
2368
2369static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002370bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002371{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002372 return _forward_call(self->reader, &PyId_peek, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002373}
2374
2375static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002376bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002377{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002378 return _forward_call(self->reader, &PyId_read1, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002379}
2380
2381static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002382bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002383{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002384 return _forward_call(self->reader, &PyId_readinto, args);
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002385}
2386
2387static PyObject *
Benjamin Petersona96fea02014-06-22 14:17:44 -07002388bufferedrwpair_readinto1(rwpair *self, PyObject *args)
2389{
2390 return _forward_call(self->reader, &PyId_readinto1, args);
2391}
2392
2393static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002394bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002395{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002396 return _forward_call(self->writer, &PyId_write, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002397}
2398
2399static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002400bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002401{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002402 return _forward_call(self->writer, &PyId_flush, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002403}
2404
2405static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002406bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002407{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002408 return _forward_call(self->reader, &PyId_readable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002409}
2410
2411static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002412bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002413{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002414 return _forward_call(self->writer, &PyId_writable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002415}
2416
2417static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002418bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002419{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002420 PyObject *ret = _forward_call(self->writer, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002421 if (ret == NULL)
2422 return NULL;
2423 Py_DECREF(ret);
2424
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002425 return _forward_call(self->reader, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002426}
2427
2428static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002429bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002430{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002431 PyObject *ret = _forward_call(self->writer, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002432
2433 if (ret != Py_False) {
2434 /* either True or exception */
2435 return ret;
2436 }
2437 Py_DECREF(ret);
2438
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002439 return _forward_call(self->reader, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002440}
2441
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002442static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002443bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002444{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002445 if (self->writer == NULL) {
2446 PyErr_SetString(PyExc_RuntimeError,
2447 "the BufferedRWPair object is being garbage-collected");
2448 return NULL;
2449 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002450 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2451}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002452
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002453static PyMethodDef bufferedrwpair_methods[] = {
2454 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2455 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2456 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2457 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Petersona96fea02014-06-22 14:17:44 -07002458 {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002459
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002460 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2461 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002462
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002463 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2464 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002465
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002466 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2467 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002468
Antoine Pitrou243757e2010-11-05 21:15:39 +00002469 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2470
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002471 {NULL, NULL}
2472};
2473
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002474static PyGetSetDef bufferedrwpair_getset[] = {
2475 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002476 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002477};
2478
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002479PyTypeObject PyBufferedRWPair_Type = {
2480 PyVarObject_HEAD_INIT(NULL, 0)
2481 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002482 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002483 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002484 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002485 0, /*tp_print*/
2486 0, /*tp_getattr*/
2487 0, /*tp_setattr*/
2488 0, /*tp_compare */
2489 0, /*tp_repr*/
2490 0, /*tp_as_number*/
2491 0, /*tp_as_sequence*/
2492 0, /*tp_as_mapping*/
2493 0, /*tp_hash */
2494 0, /*tp_call*/
2495 0, /*tp_str*/
2496 0, /*tp_getattro*/
2497 0, /*tp_setattro*/
2498 0, /*tp_as_buffer*/
2499 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002500 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002501 bufferedrwpair_doc, /* tp_doc */
2502 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2503 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002504 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002505 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002506 0, /* tp_iter */
2507 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002508 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002509 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002510 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002511 0, /* tp_base */
2512 0, /* tp_dict */
2513 0, /* tp_descr_get */
2514 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002515 offsetof(rwpair, dict), /* tp_dictoffset */
2516 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002517 0, /* tp_alloc */
2518 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002519 0, /* tp_free */
2520 0, /* tp_is_gc */
2521 0, /* tp_bases */
2522 0, /* tp_mro */
2523 0, /* tp_cache */
2524 0, /* tp_subclasses */
2525 0, /* tp_weaklist */
2526 0, /* tp_del */
2527 0, /* tp_version_tag */
2528 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002529};
2530
2531
2532
2533/*
2534 * BufferedRandom
2535 */
2536
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002537PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002538 "A buffered interface to random access streams.\n"
2539 "\n"
2540 "The constructor creates a reader and writer for a seekable stream,\n"
2541 "raw, given in the first argument. If the buffer_size is omitted it\n"
Florent Xicluna109d5732012-07-07 17:03:22 +02002542 "defaults to DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002543 );
2544
2545static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002546bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002547{
Florent Xicluna109d5732012-07-07 17:03:22 +02002548 char *kwlist[] = {"raw", "buffer_size", NULL};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002549 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002550 PyObject *raw;
2551
2552 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002553 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002554
R David Murray9f10f562013-02-23 22:07:55 -05002555 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedRandom", kwlist,
Florent Xicluna109d5732012-07-07 17:03:22 +02002556 &raw, &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002557 return -1;
2558 }
2559
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002560 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002561 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002562 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002563 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002564 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002565 return -1;
2566
2567 Py_CLEAR(self->raw);
2568 Py_INCREF(raw);
2569 self->raw = raw;
2570 self->buffer_size = buffer_size;
2571 self->readable = 1;
2572 self->writable = 1;
2573
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002574 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002575 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002576 _bufferedreader_reset_buf(self);
2577 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002578 self->pos = 0;
2579
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002580 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2581 Py_TYPE(raw) == &PyFileIO_Type);
2582
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002583 self->ok = 1;
2584 return 0;
2585}
2586
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002587static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002588 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002589 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2590 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2591 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2592 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2593 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2594 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2595 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002596 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002597 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002598
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002599 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002600
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002601 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2602 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2603 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2604 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2605 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2606 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Petersona96fea02014-06-22 14:17:44 -07002607 {"readinto1", (PyCFunction)buffered_readinto1, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002608 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2609 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2610 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002611 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002612 {NULL, NULL}
2613};
2614
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002615static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002616 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02002617 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002618 {NULL}
2619};
2620
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002621static PyGetSetDef bufferedrandom_getset[] = {
2622 {"closed", (getter)buffered_closed_get, NULL, NULL},
2623 {"name", (getter)buffered_name_get, NULL, NULL},
2624 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002625 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002626};
2627
2628
2629PyTypeObject PyBufferedRandom_Type = {
2630 PyVarObject_HEAD_INIT(NULL, 0)
2631 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002632 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002633 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002634 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002635 0, /*tp_print*/
2636 0, /*tp_getattr*/
2637 0, /*tp_setattr*/
2638 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002639 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002640 0, /*tp_as_number*/
2641 0, /*tp_as_sequence*/
2642 0, /*tp_as_mapping*/
2643 0, /*tp_hash */
2644 0, /*tp_call*/
2645 0, /*tp_str*/
2646 0, /*tp_getattro*/
2647 0, /*tp_setattro*/
2648 0, /*tp_as_buffer*/
2649 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002650 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002651 bufferedrandom_doc, /* tp_doc */
2652 (traverseproc)buffered_traverse, /* tp_traverse */
2653 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002654 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002655 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002656 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002657 (iternextfunc)buffered_iternext, /* tp_iternext */
2658 bufferedrandom_methods, /* tp_methods */
2659 bufferedrandom_members, /* tp_members */
2660 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002661 0, /* tp_base */
2662 0, /*tp_dict*/
2663 0, /* tp_descr_get */
2664 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002665 offsetof(buffered, dict), /*tp_dictoffset*/
2666 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002667 0, /* tp_alloc */
2668 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002669 0, /* tp_free */
2670 0, /* tp_is_gc */
2671 0, /* tp_bases */
2672 0, /* tp_mro */
2673 0, /* tp_cache */
2674 0, /* tp_subclasses */
2675 0, /* tp_weaklist */
2676 0, /* tp_del */
2677 0, /* tp_version_tag */
2678 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002679};