blob: 365bb85c74fce0002542972cd93765cca6684b1e [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);
27_Py_IDENTIFIER(writable);
28_Py_IDENTIFIER(write);
Martin v. Löwisafe55bb2011-10-09 10:38:36 +020029
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000030/*
31 * BufferedIOBase class, inherits from IOBase.
32 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000033PyDoc_STRVAR(bufferediobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000034 "Base class for buffered IO objects.\n"
35 "\n"
36 "The main difference with RawIOBase is that the read() method\n"
37 "supports omitting the size argument, and does not have a default\n"
38 "implementation that defers to readinto().\n"
39 "\n"
40 "In addition, read(), readinto() and write() may raise\n"
41 "BlockingIOError if the underlying raw stream is in non-blocking\n"
42 "mode and not ready; unlike their raw counterparts, they will never\n"
43 "return None.\n"
44 "\n"
45 "A typical implementation should not inherit from a RawIOBase\n"
46 "implementation, but wrap one.\n"
47 );
48
49static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000050bufferediobase_readinto(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000051{
52 Py_buffer buf;
53 Py_ssize_t len;
54 PyObject *data;
55
56 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
57 return NULL;
58 }
59
Martin v. Löwisafe55bb2011-10-09 10:38:36 +020060 data = _PyObject_CallMethodId(self, &PyId_read, "n", buf.len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000061 if (data == NULL)
62 goto error;
63
64 if (!PyBytes_Check(data)) {
65 Py_DECREF(data);
66 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
67 goto error;
68 }
69
70 len = Py_SIZE(data);
Serhiy Storchaka37a79a12013-05-28 16:24:45 +030071 if (len > buf.len) {
72 PyErr_Format(PyExc_ValueError,
73 "read() returned too much data: "
74 "%zd bytes requested, %zd returned",
75 buf.len, len);
76 Py_DECREF(data);
77 goto error;
78 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000079 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
80
81 PyBuffer_Release(&buf);
82 Py_DECREF(data);
83
84 return PyLong_FromSsize_t(len);
85
86 error:
87 PyBuffer_Release(&buf);
88 return NULL;
89}
90
91static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000092bufferediobase_unsupported(const char *message)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000093{
Antoine Pitrou712cb732013-12-21 15:51:54 +010094 _PyIO_State *state = IO_STATE();
95 if (state != NULL)
96 PyErr_SetString(state->unsupported_operation, message);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000097 return NULL;
98}
99
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000100PyDoc_STRVAR(bufferediobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000101 "Disconnect this buffer from its underlying raw stream and return it.\n"
102 "\n"
103 "After the raw stream has been detached, the buffer is in an unusable\n"
104 "state.\n");
105
106static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000107bufferediobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000108{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000109 return bufferediobase_unsupported("detach");
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000110}
111
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000112PyDoc_STRVAR(bufferediobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000113 "Read and return up to n bytes.\n"
114 "\n"
115 "If the argument is omitted, None, or negative, reads and\n"
116 "returns all data until EOF.\n"
117 "\n"
118 "If the argument is positive, and the underlying raw stream is\n"
119 "not 'interactive', multiple raw reads may be issued to satisfy\n"
120 "the byte count (unless EOF is reached first). But for\n"
121 "interactive raw streams (as well as sockets and pipes), at most\n"
122 "one raw read will be issued, and a short result does not imply\n"
123 "that EOF is imminent.\n"
124 "\n"
125 "Returns an empty bytes object on EOF.\n"
126 "\n"
127 "Returns None if the underlying raw stream was open in non-blocking\n"
128 "mode and no data is available at the moment.\n");
129
130static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000131bufferediobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000132{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000133 return bufferediobase_unsupported("read");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000134}
135
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000136PyDoc_STRVAR(bufferediobase_read1_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000137 "Read and return up to n bytes, with at most one read() call\n"
138 "to the underlying raw stream. A short result does not imply\n"
139 "that EOF is imminent.\n"
140 "\n"
141 "Returns an empty bytes object on EOF.\n");
142
143static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000144bufferediobase_read1(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000145{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000146 return bufferediobase_unsupported("read1");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000147}
148
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000149PyDoc_STRVAR(bufferediobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000150 "Write the given buffer to the IO stream.\n"
151 "\n"
152 "Returns the number of bytes written, which is never less than\n"
153 "len(b).\n"
154 "\n"
155 "Raises BlockingIOError if the buffer is full and the\n"
156 "underlying raw stream cannot accept more data at the moment.\n");
157
158static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000159bufferediobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000160{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000161 return bufferediobase_unsupported("write");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000162}
163
164
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000165static PyMethodDef bufferediobase_methods[] = {
166 {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
167 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
168 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
169 {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
170 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000171 {NULL, NULL}
172};
173
174PyTypeObject PyBufferedIOBase_Type = {
175 PyVarObject_HEAD_INIT(NULL, 0)
176 "_io._BufferedIOBase", /*tp_name*/
177 0, /*tp_basicsize*/
178 0, /*tp_itemsize*/
179 0, /*tp_dealloc*/
180 0, /*tp_print*/
181 0, /*tp_getattr*/
182 0, /*tp_setattr*/
183 0, /*tp_compare */
184 0, /*tp_repr*/
185 0, /*tp_as_number*/
186 0, /*tp_as_sequence*/
187 0, /*tp_as_mapping*/
188 0, /*tp_hash */
189 0, /*tp_call*/
190 0, /*tp_str*/
191 0, /*tp_getattro*/
192 0, /*tp_setattro*/
193 0, /*tp_as_buffer*/
Antoine Pitrou796564c2013-07-30 19:59:21 +0200194 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
195 | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000196 bufferediobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000197 0, /* tp_traverse */
198 0, /* tp_clear */
199 0, /* tp_richcompare */
200 0, /* tp_weaklistoffset */
201 0, /* tp_iter */
202 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000203 bufferediobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000204 0, /* tp_members */
205 0, /* tp_getset */
206 &PyIOBase_Type, /* tp_base */
207 0, /* tp_dict */
208 0, /* tp_descr_get */
209 0, /* tp_descr_set */
210 0, /* tp_dictoffset */
211 0, /* tp_init */
212 0, /* tp_alloc */
213 0, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +0200214 0, /* tp_free */
215 0, /* tp_is_gc */
216 0, /* tp_bases */
217 0, /* tp_mro */
218 0, /* tp_cache */
219 0, /* tp_subclasses */
220 0, /* tp_weaklist */
221 0, /* tp_del */
222 0, /* tp_version_tag */
223 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000224};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000225
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000226
227typedef struct {
228 PyObject_HEAD
229
230 PyObject *raw;
231 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000232 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000233 int readable;
234 int writable;
Antoine Pitrou796564c2013-07-30 19:59:21 +0200235 char finalizing;
Antoine Pitrou3486a982011-05-12 01:57:53 +0200236
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000237 /* True if this is a vanilla Buffered object (rather than a user derived
238 class) *and* the raw stream is a vanilla FileIO object. */
239 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000240
241 /* Absolute position inside the raw stream (-1 if unknown). */
242 Py_off_t abs_pos;
243
244 /* A static buffer of size `buffer_size` */
245 char *buffer;
246 /* Current logical position in the buffer. */
247 Py_off_t pos;
248 /* Position of the raw stream in the buffer. */
249 Py_off_t raw_pos;
250
251 /* Just after the last buffered byte in the buffer, or -1 if the buffer
252 isn't ready for reading. */
253 Py_off_t read_end;
254
255 /* Just after the last byte actually written */
256 Py_off_t write_pos;
257 /* Just after the last byte waiting to be written, or -1 if the buffer
258 isn't ready for writing. */
259 Py_off_t write_end;
260
Georg Brandldfd73442009-04-05 11:47:34 +0000261#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000262 PyThread_type_lock lock;
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000263 volatile long owner;
Georg Brandldfd73442009-04-05 11:47:34 +0000264#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000265
266 Py_ssize_t buffer_size;
267 Py_ssize_t buffer_mask;
268
269 PyObject *dict;
270 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000271} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000272
273/*
274 Implementation notes:
Antoine Pitrou3486a982011-05-12 01:57:53 +0200275
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000276 * BufferedReader, BufferedWriter and BufferedRandom try to share most
277 methods (this is helped by the members `readable` and `writable`, which
278 are initialized in the respective constructors)
279 * They also share a single buffer for reading and writing. This enables
280 interleaved reads and writes without flushing. It also makes the logic
281 a bit trickier to get right.
282 * The absolute position of the raw stream is cached, if possible, in the
283 `abs_pos` member. It must be updated every time an operation is done
284 on the raw stream. If not sure, it can be reinitialized by calling
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000285 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000286 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000287 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
288 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000289
290 NOTE: we should try to maintain block alignment of reads and writes to the
291 raw stream (according to the buffer size), but for now it is only done
292 in read() and friends.
Antoine Pitrou3486a982011-05-12 01:57:53 +0200293
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000294*/
295
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000296/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000297
Georg Brandldfd73442009-04-05 11:47:34 +0000298#ifdef WITH_THREAD
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000299
300static int
301_enter_buffered_busy(buffered *self)
302{
Antoine Pitrou25f85d42015-04-13 19:41:47 +0200303 int relax_locking;
304 PyLockStatus st;
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000305 if (self->owner == PyThread_get_thread_ident()) {
306 PyErr_Format(PyExc_RuntimeError,
307 "reentrant call inside %R", self);
308 return 0;
Antoine Pitrou5800b272009-11-01 12:05:48 +0000309 }
Antoine Pitrou25f85d42015-04-13 19:41:47 +0200310 relax_locking = (_Py_Finalizing != NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000311 Py_BEGIN_ALLOW_THREADS
Antoine Pitrou25f85d42015-04-13 19:41:47 +0200312 if (!relax_locking)
313 st = PyThread_acquire_lock(self->lock, 1);
314 else {
315 /* When finalizing, we don't want a deadlock to happen with daemon
316 * threads abruptly shut down while they owned the lock.
317 * Therefore, only wait for a grace period (1 s.).
318 * Note that non-daemon threads have already exited here, so this
319 * shouldn't affect carefully written threaded I/O code.
320 */
321 st = PyThread_acquire_lock_timed(self->lock, 1e6, 0);
322 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000323 Py_END_ALLOW_THREADS
Antoine Pitrou25f85d42015-04-13 19:41:47 +0200324 if (relax_locking && st != PY_LOCK_ACQUIRED) {
325 PyObject *msgobj = PyUnicode_FromFormat(
326 "could not acquire lock for %A at interpreter "
327 "shutdown, possibly due to daemon threads",
328 (PyObject *) self);
329 char *msg = PyUnicode_AsUTF8(msgobj);
330 Py_FatalError(msg);
331 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000332 return 1;
333}
334
335#define ENTER_BUFFERED(self) \
336 ( (PyThread_acquire_lock(self->lock, 0) ? \
337 1 : _enter_buffered_busy(self)) \
338 && (self->owner = PyThread_get_thread_ident(), 1) )
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000339
340#define LEAVE_BUFFERED(self) \
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000341 do { \
342 self->owner = 0; \
343 PyThread_release_lock(self->lock); \
344 } while(0);
345
Georg Brandldfd73442009-04-05 11:47:34 +0000346#else
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000347#define ENTER_BUFFERED(self) 1
Georg Brandldfd73442009-04-05 11:47:34 +0000348#define LEAVE_BUFFERED(self)
349#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000350
351#define CHECK_INITIALIZED(self) \
352 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000353 if (self->detached) { \
354 PyErr_SetString(PyExc_ValueError, \
355 "raw stream has been detached"); \
356 } else { \
357 PyErr_SetString(PyExc_ValueError, \
358 "I/O operation on uninitialized object"); \
359 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000360 return NULL; \
361 }
362
363#define CHECK_INITIALIZED_INT(self) \
364 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000365 if (self->detached) { \
366 PyErr_SetString(PyExc_ValueError, \
367 "raw stream has been detached"); \
368 } else { \
369 PyErr_SetString(PyExc_ValueError, \
370 "I/O operation on uninitialized object"); \
371 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000372 return -1; \
373 }
374
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000375#define IS_CLOSED(self) \
376 (self->fast_closed_checks \
377 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000378 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000379
380#define CHECK_CLOSED(self, error_msg) \
381 if (IS_CLOSED(self)) { \
382 PyErr_SetString(PyExc_ValueError, error_msg); \
383 return NULL; \
384 }
385
386
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000387#define VALID_READ_BUFFER(self) \
388 (self->readable && self->read_end != -1)
389
390#define VALID_WRITE_BUFFER(self) \
391 (self->writable && self->write_end != -1)
392
393#define ADJUST_POSITION(self, _new_pos) \
394 do { \
395 self->pos = _new_pos; \
396 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
397 self->read_end = self->pos; \
398 } while(0)
399
400#define READAHEAD(self) \
401 ((self->readable && VALID_READ_BUFFER(self)) \
402 ? (self->read_end - self->pos) : 0)
403
404#define RAW_OFFSET(self) \
405 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
406 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
407
408#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000409 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000410
411#define MINUS_LAST_BLOCK(self, size) \
412 (self->buffer_mask ? \
413 (size & ~self->buffer_mask) : \
414 (self->buffer_size * (size / self->buffer_size)))
415
416
417static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000418buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000419{
Antoine Pitrou796564c2013-07-30 19:59:21 +0200420 self->finalizing = 1;
421 if (_PyIOBase_finalize((PyObject *) self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000422 return;
423 _PyObject_GC_UNTRACK(self);
424 self->ok = 0;
425 if (self->weakreflist != NULL)
426 PyObject_ClearWeakRefs((PyObject *)self);
427 Py_CLEAR(self->raw);
428 if (self->buffer) {
429 PyMem_Free(self->buffer);
430 self->buffer = NULL;
431 }
Georg Brandldfd73442009-04-05 11:47:34 +0000432#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000433 if (self->lock) {
434 PyThread_free_lock(self->lock);
435 self->lock = NULL;
436 }
Georg Brandldfd73442009-04-05 11:47:34 +0000437#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000438 Py_CLEAR(self->dict);
439 Py_TYPE(self)->tp_free((PyObject *)self);
440}
441
Antoine Pitrou10f0c502012-07-29 19:02:46 +0200442static PyObject *
443buffered_sizeof(buffered *self, void *unused)
444{
445 Py_ssize_t res;
446
447 res = sizeof(buffered);
448 if (self->buffer)
449 res += self->buffer_size;
450 return PyLong_FromSsize_t(res);
451}
452
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000453static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000454buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000455{
456 Py_VISIT(self->raw);
457 Py_VISIT(self->dict);
458 return 0;
459}
460
461static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000462buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000463{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000464 self->ok = 0;
465 Py_CLEAR(self->raw);
466 Py_CLEAR(self->dict);
467 return 0;
468}
469
Antoine Pitroue033e062010-10-29 10:38:18 +0000470/* Because this can call arbitrary code, it shouldn't be called when
471 the refcount is 0 (that is, not directly from tp_dealloc unless
472 the refcount has been temporarily re-incremented). */
Matthias Klosebee33162010-11-16 20:07:51 +0000473static PyObject *
Antoine Pitroue033e062010-10-29 10:38:18 +0000474buffered_dealloc_warn(buffered *self, PyObject *source)
475{
476 if (self->ok && self->raw) {
477 PyObject *r;
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200478 r = _PyObject_CallMethodId(self->raw, &PyId__dealloc_warn, "O", source);
Antoine Pitroue033e062010-10-29 10:38:18 +0000479 if (r)
480 Py_DECREF(r);
481 else
482 PyErr_Clear();
483 }
484 Py_RETURN_NONE;
485}
486
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000487/*
488 * _BufferedIOMixin methods
489 * This is not a class, just a collection of methods that will be reused
490 * by BufferedReader and BufferedWriter
491 */
492
493/* Flush and close */
494
495static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000496buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000497{
498 CHECK_INITIALIZED(self)
499 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
500}
501
502static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000503buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000504{
505 int closed;
506 PyObject *res;
507 CHECK_INITIALIZED_INT(self)
508 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
509 if (res == NULL)
510 return -1;
511 closed = PyObject_IsTrue(res);
512 Py_DECREF(res);
513 return closed;
514}
515
516static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000517buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000518{
519 CHECK_INITIALIZED(self)
520 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
521}
522
523static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000524buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000525{
Benjamin Peterson68623612012-12-20 11:53:11 -0600526 PyObject *res = NULL, *exc = NULL, *val, *tb;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000527 int r;
528
529 CHECK_INITIALIZED(self)
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000530 if (!ENTER_BUFFERED(self))
531 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000532
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000533 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000534 if (r < 0)
535 goto end;
536 if (r > 0) {
537 res = Py_None;
538 Py_INCREF(res);
539 goto end;
540 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000541
Antoine Pitrou796564c2013-07-30 19:59:21 +0200542 if (self->finalizing) {
Antoine Pitroue033e062010-10-29 10:38:18 +0000543 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
544 if (r)
545 Py_DECREF(r);
546 else
547 PyErr_Clear();
548 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000549 /* flush() will most probably re-take the lock, so drop it first */
550 LEAVE_BUFFERED(self)
551 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000552 if (!ENTER_BUFFERED(self))
553 return NULL;
Benjamin Peterson68623612012-12-20 11:53:11 -0600554 if (res == NULL)
555 PyErr_Fetch(&exc, &val, &tb);
556 else
557 Py_DECREF(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000558
559 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
560
Jesus Ceadc469452012-10-04 12:37:56 +0200561 if (self->buffer) {
562 PyMem_Free(self->buffer);
563 self->buffer = NULL;
564 }
565
Benjamin Peterson68623612012-12-20 11:53:11 -0600566 if (exc != NULL) {
Serhiy Storchakae2bd2a72014-10-08 22:31:52 +0300567 _PyErr_ChainExceptions(exc, val, tb);
568 Py_CLEAR(res);
Benjamin Peterson68623612012-12-20 11:53:11 -0600569 }
570
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000571end:
572 LEAVE_BUFFERED(self)
573 return res;
574}
575
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000576/* detach */
577
578static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000579buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000580{
581 PyObject *raw, *res;
582 CHECK_INITIALIZED(self)
583 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
584 if (res == NULL)
585 return NULL;
586 Py_DECREF(res);
587 raw = self->raw;
588 self->raw = NULL;
589 self->detached = 1;
590 self->ok = 0;
591 return raw;
592}
593
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000594/* Inquiries */
595
596static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000597buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000598{
599 CHECK_INITIALIZED(self)
600 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
601}
602
603static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000604buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000605{
606 CHECK_INITIALIZED(self)
607 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
608}
609
610static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000611buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000612{
613 CHECK_INITIALIZED(self)
614 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
615}
616
617static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000618buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000619{
620 CHECK_INITIALIZED(self)
Martin v. Löwis767046a2011-10-14 15:35:36 +0200621 return _PyObject_GetAttrId(self->raw, &PyId_name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000622}
623
624static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000625buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000626{
627 CHECK_INITIALIZED(self)
Martin v. Löwis767046a2011-10-14 15:35:36 +0200628 return _PyObject_GetAttrId(self->raw, &PyId_mode);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000629}
630
631/* Lower-level APIs */
632
633static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000634buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000635{
636 CHECK_INITIALIZED(self)
637 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
638}
639
640static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000641buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000642{
643 CHECK_INITIALIZED(self)
644 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
645}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000646
Antoine Pitrou243757e2010-11-05 21:15:39 +0000647/* Serialization */
648
649static PyObject *
650buffered_getstate(buffered *self, PyObject *args)
651{
652 PyErr_Format(PyExc_TypeError,
653 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
654 return NULL;
655}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000656
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000657/* Forward decls */
658static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100659_bufferedwriter_flush_unlocked(buffered *);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000660static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000661_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000662static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000663_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000664static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000665_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000666static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +0200667_bufferedreader_peek_unlocked(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000668static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000669_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000670static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000671_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000672static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000673_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Antoine Pitrou3486a982011-05-12 01:57:53 +0200674static Py_ssize_t
675_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000676
677/*
678 * Helpers
679 */
680
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100681/* Sets the current error to BlockingIOError */
682static void
683_set_BlockingIOError(char *msg, Py_ssize_t written)
684{
685 PyObject *err;
Victor Stinnerace47d72013-07-18 01:41:08 +0200686#ifdef Py_DEBUG
687 /* in debug mode, PyEval_EvalFrameEx() fails with an assertion error
688 if an exception is set when it is called */
689 PyErr_Clear();
690#endif
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100691 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
692 errno, msg, written);
693 if (err)
694 PyErr_SetObject(PyExc_BlockingIOError, err);
695 Py_XDECREF(err);
696}
697
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000698/* Returns the address of the `written` member if a BlockingIOError was
699 raised, NULL otherwise. The error is always re-raised. */
700static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000701_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000702{
703 PyObject *t, *v, *tb;
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200704 PyOSErrorObject *err;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000705
706 PyErr_Fetch(&t, &v, &tb);
707 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
708 PyErr_Restore(t, v, tb);
709 return NULL;
710 }
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200711 err = (PyOSErrorObject *) v;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000712 /* TODO: sanity check (err->written >= 0) */
713 PyErr_Restore(t, v, tb);
714 return &err->written;
715}
716
717static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000718_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000719{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000720 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000721 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000722 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
723 if (res == NULL)
724 return -1;
725 n = PyNumber_AsOff_t(res, PyExc_ValueError);
726 Py_DECREF(res);
727 if (n < 0) {
728 if (!PyErr_Occurred())
729 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000730 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200731 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000732 return -1;
733 }
734 self->abs_pos = n;
735 return n;
736}
737
738static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000739_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000740{
741 PyObject *res, *posobj, *whenceobj;
742 Py_off_t n;
743
744 posobj = PyLong_FromOff_t(target);
745 if (posobj == NULL)
746 return -1;
747 whenceobj = PyLong_FromLong(whence);
748 if (whenceobj == NULL) {
749 Py_DECREF(posobj);
750 return -1;
751 }
752 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
753 posobj, whenceobj, NULL);
754 Py_DECREF(posobj);
755 Py_DECREF(whenceobj);
756 if (res == NULL)
757 return -1;
758 n = PyNumber_AsOff_t(res, PyExc_ValueError);
759 Py_DECREF(res);
760 if (n < 0) {
761 if (!PyErr_Occurred())
762 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000763 "Raw stream returned invalid position %" PY_PRIdOFF,
Antoine Pitrou3486a982011-05-12 01:57:53 +0200764 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000765 return -1;
766 }
767 self->abs_pos = n;
768 return n;
769}
770
771static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000772_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000773{
774 Py_ssize_t n;
775 if (self->buffer_size <= 0) {
776 PyErr_SetString(PyExc_ValueError,
777 "buffer size must be strictly positive");
778 return -1;
779 }
780 if (self->buffer)
781 PyMem_Free(self->buffer);
782 self->buffer = PyMem_Malloc(self->buffer_size);
783 if (self->buffer == NULL) {
784 PyErr_NoMemory();
785 return -1;
786 }
Georg Brandldfd73442009-04-05 11:47:34 +0000787#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000788 if (self->lock)
789 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000790 self->lock = PyThread_allocate_lock();
791 if (self->lock == NULL) {
792 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
793 return -1;
794 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000795 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000796#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000797 /* Find out whether buffer_size is a power of 2 */
798 /* XXX is this optimization useful? */
799 for (n = self->buffer_size - 1; n & 1; n >>= 1)
800 ;
801 if (n == 0)
802 self->buffer_mask = self->buffer_size - 1;
803 else
804 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000805 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000806 PyErr_Clear();
807 return 0;
808}
809
Antoine Pitrou707ce822011-02-25 21:24:11 +0000810/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
811 clears the error indicator), 0 otherwise.
812 Should only be called when PyErr_Occurred() is true.
813*/
Gregory P. Smith51359922012-06-23 23:55:39 -0700814int
815_PyIO_trap_eintr(void)
Antoine Pitrou707ce822011-02-25 21:24:11 +0000816{
817 static PyObject *eintr_int = NULL;
818 PyObject *typ, *val, *tb;
819 PyEnvironmentErrorObject *env_err;
820
821 if (eintr_int == NULL) {
822 eintr_int = PyLong_FromLong(EINTR);
823 assert(eintr_int != NULL);
824 }
825 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
826 return 0;
827 PyErr_Fetch(&typ, &val, &tb);
828 PyErr_NormalizeException(&typ, &val, &tb);
829 env_err = (PyEnvironmentErrorObject *) val;
830 assert(env_err != NULL);
831 if (env_err->myerrno != NULL &&
832 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
833 Py_DECREF(typ);
834 Py_DECREF(val);
835 Py_XDECREF(tb);
836 return 1;
837 }
838 /* This silences any error set by PyObject_RichCompareBool() */
839 PyErr_Restore(typ, val, tb);
840 return 0;
841}
842
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000843/*
844 * Shared methods and wrappers
845 */
846
847static PyObject *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200848buffered_flush_and_rewind_unlocked(buffered *self)
849{
850 PyObject *res;
851
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +0100852 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200853 if (res == NULL)
854 return NULL;
855 Py_DECREF(res);
856
857 if (self->readable) {
858 /* Rewind the raw stream so that its position corresponds to
859 the current logical position. */
860 Py_off_t n;
861 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
862 _bufferedreader_reset_buf(self);
863 if (n == -1)
864 return NULL;
865 }
866 Py_RETURN_NONE;
867}
868
869static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000870buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000871{
872 PyObject *res;
873
874 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000875 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000876
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000877 if (!ENTER_BUFFERED(self))
878 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200879 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000880 LEAVE_BUFFERED(self)
881
882 return res;
883}
884
885static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000886buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000887{
888 Py_ssize_t n = 0;
889 PyObject *res = NULL;
890
891 CHECK_INITIALIZED(self)
Berker Peksagea6d5592015-05-12 17:13:56 +0300892 CHECK_CLOSED(self, "peek of closed file")
893
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000894 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
895 return NULL;
896 }
897
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000898 if (!ENTER_BUFFERED(self))
899 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000900
901 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200902 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000903 if (res == NULL)
904 goto end;
905 Py_CLEAR(res);
906 }
Victor Stinnerbc93a112011-06-01 00:01:24 +0200907 res = _bufferedreader_peek_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000908
909end:
910 LEAVE_BUFFERED(self)
911 return res;
912}
913
914static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000915buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000916{
917 Py_ssize_t n = -1;
918 PyObject *res;
919
920 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000921 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000922 return NULL;
923 }
924 if (n < -1) {
925 PyErr_SetString(PyExc_ValueError,
926 "read length must be positive or -1");
927 return NULL;
928 }
929
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000930 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000931
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000932 if (n == -1) {
933 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000934 if (!ENTER_BUFFERED(self))
935 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000936 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000937 }
938 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000939 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200940 if (res != Py_None)
941 return res;
942 Py_DECREF(res);
943 if (!ENTER_BUFFERED(self))
944 return NULL;
945 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000946 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000947
Antoine Pitroue05565e2011-08-20 14:39:23 +0200948 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000949 return res;
950}
951
952static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000953buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000954{
955 Py_ssize_t n, have, r;
956 PyObject *res = NULL;
957
958 CHECK_INITIALIZED(self)
959 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
960 return NULL;
961 }
962
963 if (n < 0) {
964 PyErr_SetString(PyExc_ValueError,
965 "read length must be positive");
966 return NULL;
967 }
Berker Peksagea6d5592015-05-12 17:13:56 +0300968
969 CHECK_CLOSED(self, "read of closed file")
970
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000971 if (n == 0)
972 return PyBytes_FromStringAndSize(NULL, 0);
973
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000974 /* Return up to n bytes. If at least one byte is buffered, we
975 only return buffered bytes. Otherwise, we do one raw read. */
976
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000977 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
978 if (have > 0) {
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100979 n = Py_MIN(have, n);
980 res = _bufferedreader_read_fast(self, n);
981 assert(res != Py_None);
982 return res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000983 }
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100984 res = PyBytes_FromStringAndSize(NULL, n);
985 if (res == NULL)
986 return NULL;
987 if (!ENTER_BUFFERED(self)) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200988 Py_DECREF(res);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100989 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200990 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000991 _bufferedreader_reset_buf(self);
Antoine Pitrou56a220a2011-11-16 00:56:10 +0100992 r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
993 LEAVE_BUFFERED(self)
994 if (r == -1) {
995 Py_DECREF(res);
996 return NULL;
997 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000998 if (r == -2)
999 r = 0;
1000 if (n > r)
Antoine Pitrou56a220a2011-11-16 00:56:10 +01001001 _PyBytes_Resize(&res, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001002 return res;
1003}
1004
1005static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001006buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001007{
Antoine Pitrou3486a982011-05-12 01:57:53 +02001008 Py_buffer buf;
1009 Py_ssize_t n, written = 0, remaining;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001010 PyObject *res = NULL;
1011
1012 CHECK_INITIALIZED(self)
Antoine Pitrou3486a982011-05-12 01:57:53 +02001013
1014 if (!PyArg_ParseTuple(args, "w*:readinto", &buf))
1015 return NULL;
1016
1017 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1018 if (n > 0) {
1019 if (n >= buf.len) {
1020 memcpy(buf.buf, self->buffer + self->pos, buf.len);
1021 self->pos += buf.len;
1022 res = PyLong_FromSsize_t(buf.len);
1023 goto end_unlocked;
1024 }
1025 memcpy(buf.buf, self->buffer + self->pos, n);
1026 self->pos += n;
1027 written = n;
1028 }
1029
1030 if (!ENTER_BUFFERED(self))
1031 goto end_unlocked;
1032
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001033 if (self->writable) {
Antoine Pitroue8bb1a02011-08-20 14:52:04 +02001034 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001035 if (res == NULL)
1036 goto end;
Antoine Pitrou3486a982011-05-12 01:57:53 +02001037 Py_CLEAR(res);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001038 }
Antoine Pitrou3486a982011-05-12 01:57:53 +02001039
1040 _bufferedreader_reset_buf(self);
1041 self->pos = 0;
1042
1043 for (remaining = buf.len - written;
1044 remaining > 0;
1045 written += n, remaining -= n) {
1046 /* If remaining bytes is larger than internal buffer size, copy
1047 * directly into caller's buffer. */
1048 if (remaining > self->buffer_size) {
Antoine Pitrou4e19e112011-05-12 02:07:00 +02001049 n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
1050 remaining);
Antoine Pitrou3486a982011-05-12 01:57:53 +02001051 }
1052 else {
1053 n = _bufferedreader_fill_buffer(self);
1054 if (n > 0) {
1055 if (n > remaining)
1056 n = remaining;
Antoine Pitrou4e19e112011-05-12 02:07:00 +02001057 memcpy((char *) buf.buf + written,
1058 self->buffer + self->pos, n);
Antoine Pitrou3486a982011-05-12 01:57:53 +02001059 self->pos += n;
1060 continue; /* short circuit */
1061 }
1062 }
1063 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 }
1072 }
1073 res = PyLong_FromSsize_t(written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001074
1075end:
Antoine Pitrou3486a982011-05-12 01:57:53 +02001076 LEAVE_BUFFERED(self);
1077end_unlocked:
1078 PyBuffer_Release(&buf);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001079 return res;
1080}
1081
1082static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001083_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001084{
1085 PyObject *res = NULL;
1086 PyObject *chunks = NULL;
1087 Py_ssize_t n, written = 0;
1088 const char *start, *s, *end;
1089
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001090 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001091
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001092 /* First, try to find a line in the buffer. This can run unlocked because
1093 the calls to the C API are simple enough that they can't trigger
1094 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001095 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1096 if (limit >= 0 && n > limit)
1097 n = limit;
1098 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001099 s = memchr(start, '\n', n);
1100 if (s != NULL) {
1101 res = PyBytes_FromStringAndSize(start, s - start + 1);
1102 if (res != NULL)
1103 self->pos += s - start + 1;
1104 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001105 }
1106 if (n == limit) {
1107 res = PyBytes_FromStringAndSize(start, n);
1108 if (res != NULL)
1109 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001110 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001111 }
1112
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001113 if (!ENTER_BUFFERED(self))
1114 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001115
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001116 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001117 chunks = PyList_New(0);
1118 if (chunks == NULL)
1119 goto end;
1120 if (n > 0) {
1121 res = PyBytes_FromStringAndSize(start, n);
1122 if (res == NULL)
1123 goto end;
1124 if (PyList_Append(chunks, res) < 0) {
1125 Py_CLEAR(res);
1126 goto end;
1127 }
1128 Py_CLEAR(res);
1129 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001130 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001131 if (limit >= 0)
1132 limit -= n;
1133 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001134 if (self->writable) {
1135 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1136 if (r == NULL)
1137 goto end;
1138 Py_DECREF(r);
1139 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001140
1141 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001142 _bufferedreader_reset_buf(self);
1143 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001144 if (n == -1)
1145 goto end;
1146 if (n <= 0)
1147 break;
1148 if (limit >= 0 && n > limit)
1149 n = limit;
1150 start = self->buffer;
1151 end = start + n;
1152 s = start;
1153 while (s < end) {
1154 if (*s++ == '\n') {
1155 res = PyBytes_FromStringAndSize(start, s - start);
1156 if (res == NULL)
1157 goto end;
1158 self->pos = s - start;
1159 goto found;
1160 }
1161 }
1162 res = PyBytes_FromStringAndSize(start, n);
1163 if (res == NULL)
1164 goto end;
1165 if (n == limit) {
1166 self->pos = n;
1167 break;
1168 }
1169 if (PyList_Append(chunks, res) < 0) {
1170 Py_CLEAR(res);
1171 goto end;
1172 }
1173 Py_CLEAR(res);
1174 written += n;
1175 if (limit >= 0)
1176 limit -= n;
1177 }
1178found:
1179 if (res != NULL && PyList_Append(chunks, res) < 0) {
1180 Py_CLEAR(res);
1181 goto end;
1182 }
1183 Py_CLEAR(res);
1184 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1185
1186end:
1187 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001188end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001189 Py_XDECREF(chunks);
1190 return res;
1191}
1192
1193static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001194buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001195{
1196 Py_ssize_t limit = -1;
1197
1198 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001199 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001200 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001201 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001202}
1203
1204
1205static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001206buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001207{
1208 Py_off_t pos;
1209
1210 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001211 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001212 if (pos == -1)
1213 return NULL;
1214 pos -= RAW_OFFSET(self);
1215 /* TODO: sanity check (pos >= 0) */
1216 return PyLong_FromOff_t(pos);
1217}
1218
1219static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001220buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001221{
1222 Py_off_t target, n;
1223 int whence = 0;
1224 PyObject *targetobj, *res = NULL;
1225
1226 CHECK_INITIALIZED(self)
1227 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1228 return NULL;
1229 }
Jesus Cea94363612012-06-22 18:32:07 +02001230
1231 /* Do some error checking instead of trusting OS 'seek()'
1232 ** error detection, just in case.
1233 */
1234 if ((whence < 0 || whence >2)
1235#ifdef SEEK_HOLE
1236 && (whence != SEEK_HOLE)
1237#endif
1238#ifdef SEEK_DATA
1239 && (whence != SEEK_DATA)
1240#endif
1241 ) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001242 PyErr_Format(PyExc_ValueError,
Jesus Cea94363612012-06-22 18:32:07 +02001243 "whence value %d unsupported", whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001244 return NULL;
1245 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001246
1247 CHECK_CLOSED(self, "seek of closed file")
1248
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001249 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1250 return NULL;
1251
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001252 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1253 if (target == -1 && PyErr_Occurred())
1254 return NULL;
1255
Jesus Cea94363612012-06-22 18:32:07 +02001256 /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1257 buffer. Other whence values must be managed without this optimization.
1258 Some Operating Systems can provide additional values, like
1259 SEEK_HOLE/SEEK_DATA. */
1260 if (((whence == 0) || (whence == 1)) && self->readable) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001261 Py_off_t current, avail;
1262 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001263 so as to return quickly if possible. Also, we needn't take the
1264 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001265 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001266 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1267 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001268 current = RAW_TELL(self);
1269 avail = READAHEAD(self);
1270 if (avail > 0) {
1271 Py_off_t offset;
1272 if (whence == 0)
1273 offset = target - (current - RAW_OFFSET(self));
1274 else
1275 offset = target;
1276 if (offset >= -self->pos && offset <= avail) {
1277 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001278 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001279 }
1280 }
1281 }
1282
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001283 if (!ENTER_BUFFERED(self))
1284 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001285
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001286 /* Fallback: invoke raw seek() method and clear buffer */
1287 if (self->writable) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001288 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001289 if (res == NULL)
1290 goto end;
1291 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001292 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001293 }
1294
1295 /* TODO: align on block boundary and read buffer if needed? */
1296 if (whence == 1)
1297 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001298 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001299 if (n == -1)
1300 goto end;
1301 self->raw_pos = -1;
1302 res = PyLong_FromOff_t(n);
1303 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001304 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001305
1306end:
1307 LEAVE_BUFFERED(self)
1308 return res;
1309}
1310
1311static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001312buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001313{
1314 PyObject *pos = Py_None;
1315 PyObject *res = NULL;
1316
1317 CHECK_INITIALIZED(self)
1318 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1319 return NULL;
1320 }
1321
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001322 if (!ENTER_BUFFERED(self))
1323 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001324
1325 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001326 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001327 if (res == NULL)
1328 goto end;
1329 Py_CLEAR(res);
1330 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001331 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1332 if (res == NULL)
1333 goto end;
1334 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001335 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001336 PyErr_Clear();
1337
1338end:
1339 LEAVE_BUFFERED(self)
1340 return res;
1341}
1342
1343static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001344buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001345{
1346 PyObject *line;
1347 PyTypeObject *tp;
1348
1349 CHECK_INITIALIZED(self);
1350
1351 tp = Py_TYPE(self);
1352 if (tp == &PyBufferedReader_Type ||
1353 tp == &PyBufferedRandom_Type) {
1354 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001355 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001356 }
1357 else {
1358 line = PyObject_CallMethodObjArgs((PyObject *)self,
1359 _PyIO_str_readline, NULL);
1360 if (line && !PyBytes_Check(line)) {
1361 PyErr_Format(PyExc_IOError,
1362 "readline() should have returned a bytes object, "
1363 "not '%.200s'", Py_TYPE(line)->tp_name);
1364 Py_DECREF(line);
1365 return NULL;
1366 }
1367 }
1368
1369 if (line == NULL)
1370 return NULL;
1371
1372 if (PyBytes_GET_SIZE(line) == 0) {
1373 /* Reached EOF or would have blocked */
1374 Py_DECREF(line);
1375 return NULL;
1376 }
1377
1378 return line;
1379}
1380
Antoine Pitrou716c4442009-05-23 19:04:03 +00001381static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001382buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001383{
1384 PyObject *nameobj, *res;
1385
Martin v. Löwis767046a2011-10-14 15:35:36 +02001386 nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
Antoine Pitrou716c4442009-05-23 19:04:03 +00001387 if (nameobj == NULL) {
Benjamin Peterson10e76b62014-12-21 20:51:50 -06001388 if (PyErr_ExceptionMatches(PyExc_Exception))
Antoine Pitrou716c4442009-05-23 19:04:03 +00001389 PyErr_Clear();
1390 else
1391 return NULL;
1392 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1393 }
1394 else {
1395 res = PyUnicode_FromFormat("<%s name=%R>",
1396 Py_TYPE(self)->tp_name, nameobj);
1397 Py_DECREF(nameobj);
1398 }
1399 return res;
1400}
1401
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001402/*
1403 * class BufferedReader
1404 */
1405
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001406PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001407 "Create a new buffered reader using the given readable raw IO object.");
1408
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001409static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001410{
1411 self->read_end = -1;
1412}
1413
1414static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001415bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001416{
1417 char *kwlist[] = {"raw", "buffer_size", NULL};
1418 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1419 PyObject *raw;
1420
1421 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001422 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001423
1424 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1425 &raw, &buffer_size)) {
1426 return -1;
1427 }
1428
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001429 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001430 return -1;
1431
1432 Py_CLEAR(self->raw);
1433 Py_INCREF(raw);
1434 self->raw = raw;
1435 self->buffer_size = buffer_size;
1436 self->readable = 1;
1437 self->writable = 0;
1438
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001439 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001440 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001441 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001442
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001443 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1444 Py_TYPE(raw) == &PyFileIO_Type);
1445
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001446 self->ok = 1;
1447 return 0;
1448}
1449
1450static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001451_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001452{
1453 Py_buffer buf;
1454 PyObject *memobj, *res;
1455 Py_ssize_t n;
1456 /* NOTE: the buffer needn't be released as its object is NULL. */
1457 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1458 return -1;
1459 memobj = PyMemoryView_FromBuffer(&buf);
1460 if (memobj == NULL)
1461 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001462 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1463 occurs so we needn't do it ourselves.
1464 We then retry reading, ignoring the signal if no handler has
1465 raised (see issue #10956).
1466 */
1467 do {
1468 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
Gregory P. Smith51359922012-06-23 23:55:39 -07001469 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001470 Py_DECREF(memobj);
1471 if (res == NULL)
1472 return -1;
1473 if (res == Py_None) {
1474 /* Non-blocking stream would have blocked. Special return code! */
1475 Py_DECREF(res);
1476 return -2;
1477 }
1478 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1479 Py_DECREF(res);
1480 if (n < 0 || n > len) {
1481 PyErr_Format(PyExc_IOError,
1482 "raw readinto() returned invalid length %zd "
1483 "(should have been between 0 and %zd)", n, len);
1484 return -1;
1485 }
1486 if (n > 0 && self->abs_pos != -1)
1487 self->abs_pos += n;
1488 return n;
1489}
1490
1491static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001492_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001493{
1494 Py_ssize_t start, len, n;
1495 if (VALID_READ_BUFFER(self))
1496 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1497 else
1498 start = 0;
1499 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001500 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001501 if (n <= 0)
1502 return n;
1503 self->read_end = start + n;
1504 self->raw_pos = start + n;
1505 return n;
1506}
1507
1508static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001509_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001510{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001511 Py_ssize_t current_size;
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001512 PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001513
1514 /* First copy what we have in the current buffer. */
1515 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1516 if (current_size) {
1517 data = PyBytes_FromStringAndSize(
1518 self->buffer + self->pos, current_size);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001519 if (data == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001520 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001521 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001522 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001523 /* We're going past the buffer's bounds, flush it */
1524 if (self->writable) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001525 tmp = buffered_flush_and_rewind_unlocked(self);
1526 if (tmp == NULL)
1527 goto cleanup;
1528 Py_CLEAR(tmp);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001529 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001530 _bufferedreader_reset_buf(self);
Victor Stinnerb57f1082011-05-26 00:19:38 +02001531
1532 if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001533 tmp = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
1534 if (tmp == NULL)
1535 goto cleanup;
1536 if (tmp != Py_None && !PyBytes_Check(tmp)) {
Victor Stinnerb57f1082011-05-26 00:19:38 +02001537 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001538 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001539 }
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001540 if (tmp == Py_None) {
1541 if (current_size == 0) {
1542 res = Py_None;
1543 goto cleanup;
1544 } else {
1545 res = data;
1546 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001547 }
1548 }
1549 else if (current_size) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001550 PyBytes_Concat(&data, tmp);
1551 res = data;
1552 goto cleanup;
1553 }
1554 else {
1555 res = tmp;
1556 goto cleanup;
1557 }
Victor Stinnerb57f1082011-05-26 00:19:38 +02001558 }
1559
1560 chunks = PyList_New(0);
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001561 if (chunks == NULL)
1562 goto cleanup;
Victor Stinnerb57f1082011-05-26 00:19:38 +02001563
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001564 while (1) {
1565 if (data) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001566 if (PyList_Append(chunks, data) < 0)
1567 goto cleanup;
1568 Py_CLEAR(data);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001569 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001570
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001571 /* Read until EOF or until read() would block. */
1572 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001573 if (data == NULL)
1574 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001575 if (data != Py_None && !PyBytes_Check(data)) {
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001576 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001577 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001578 }
1579 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1580 if (current_size == 0) {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001581 res = data;
1582 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001583 }
1584 else {
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001585 tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1586 res = tmp;
1587 goto cleanup;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001588 }
1589 }
1590 current_size += PyBytes_GET_SIZE(data);
1591 if (self->abs_pos != -1)
1592 self->abs_pos += PyBytes_GET_SIZE(data);
1593 }
Richard Oudkerk9ad51ec2013-07-15 16:05:22 +01001594cleanup:
1595 /* res is either NULL or a borrowed ref */
1596 Py_XINCREF(res);
1597 Py_XDECREF(data);
1598 Py_XDECREF(tmp);
1599 Py_XDECREF(chunks);
1600 return res;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001601}
1602
1603/* Read n bytes from the buffer if it can, otherwise return None.
1604 This function is simple enough that it can run unlocked. */
1605static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001606_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001607{
1608 Py_ssize_t current_size;
1609
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001610 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1611 if (n <= current_size) {
1612 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001613 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1614 if (res != NULL)
1615 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001616 return res;
1617 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001618 Py_RETURN_NONE;
1619}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001620
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001621/* Generic read function: read from the stream until enough bytes are read,
1622 * or until an EOF occurs or until read() would block.
1623 */
1624static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001625_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001626{
1627 PyObject *res = NULL;
1628 Py_ssize_t current_size, remaining, written;
1629 char *out;
1630
1631 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1632 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001633 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001634
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001635 res = PyBytes_FromStringAndSize(NULL, n);
1636 if (res == NULL)
1637 goto error;
1638 out = PyBytes_AS_STRING(res);
1639 remaining = n;
1640 written = 0;
1641 if (current_size > 0) {
1642 memcpy(out, self->buffer + self->pos, current_size);
1643 remaining -= current_size;
1644 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001645 self->pos += current_size;
1646 }
1647 /* Flush the write buffer if necessary */
1648 if (self->writable) {
1649 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1650 if (r == NULL)
1651 goto error;
1652 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001653 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001654 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001655 while (remaining > 0) {
1656 /* We want to read a whole block at the end into buffer.
1657 If we had readv() we could do this in one pass. */
1658 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1659 if (r == 0)
1660 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001661 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001662 if (r == -1)
1663 goto error;
1664 if (r == 0 || r == -2) {
1665 /* EOF occurred or read() would block. */
1666 if (r == 0 || written > 0) {
1667 if (_PyBytes_Resize(&res, written))
1668 goto error;
1669 return res;
1670 }
1671 Py_DECREF(res);
1672 Py_INCREF(Py_None);
1673 return Py_None;
1674 }
1675 remaining -= r;
1676 written += r;
1677 }
1678 assert(remaining <= self->buffer_size);
1679 self->pos = 0;
1680 self->raw_pos = 0;
1681 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001682 /* NOTE: when the read is satisfied, we avoid issuing any additional
1683 reads, which could block indefinitely (e.g. on a socket).
1684 See issue #9550. */
1685 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001686 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001687 if (r == -1)
1688 goto error;
1689 if (r == 0 || r == -2) {
1690 /* EOF occurred or read() would block. */
1691 if (r == 0 || written > 0) {
1692 if (_PyBytes_Resize(&res, written))
1693 goto error;
1694 return res;
1695 }
1696 Py_DECREF(res);
1697 Py_INCREF(Py_None);
1698 return Py_None;
1699 }
1700 if (remaining > r) {
1701 memcpy(out + written, self->buffer + self->pos, r);
1702 written += r;
1703 self->pos += r;
1704 remaining -= r;
1705 }
1706 else if (remaining > 0) {
1707 memcpy(out + written, self->buffer + self->pos, remaining);
1708 written += remaining;
1709 self->pos += remaining;
1710 remaining = 0;
1711 }
1712 if (remaining == 0)
1713 break;
1714 }
1715
1716 return res;
1717
1718error:
1719 Py_XDECREF(res);
1720 return NULL;
1721}
1722
1723static PyObject *
Victor Stinnerbc93a112011-06-01 00:01:24 +02001724_bufferedreader_peek_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001725{
1726 Py_ssize_t have, r;
1727
1728 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1729 /* Constraints:
1730 1. we don't want to advance the file position.
1731 2. we don't want to lose block alignment, so we can't shift the buffer
1732 to make some place.
1733 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1734 */
1735 if (have > 0) {
1736 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1737 }
1738
1739 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001740 _bufferedreader_reset_buf(self);
1741 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001742 if (r == -1)
1743 return NULL;
1744 if (r == -2)
1745 r = 0;
1746 self->pos = 0;
1747 return PyBytes_FromStringAndSize(self->buffer, r);
1748}
1749
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001750static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001751 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001752 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1753 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1754 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1755 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1756 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1757 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1758 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1759 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001760 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001761 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001762
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001763 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1764 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1765 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
Antoine Pitrou3486a982011-05-12 01:57:53 +02001766 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001767 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1768 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1769 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1770 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02001771 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001772 {NULL, NULL}
1773};
1774
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001775static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001776 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02001777 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001778 {NULL}
1779};
1780
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001781static PyGetSetDef bufferedreader_getset[] = {
1782 {"closed", (getter)buffered_closed_get, NULL, NULL},
1783 {"name", (getter)buffered_name_get, NULL, NULL},
1784 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001785 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001786};
1787
1788
1789PyTypeObject PyBufferedReader_Type = {
1790 PyVarObject_HEAD_INIT(NULL, 0)
1791 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001792 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001793 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001794 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001795 0, /*tp_print*/
1796 0, /*tp_getattr*/
1797 0, /*tp_setattr*/
1798 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001799 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001800 0, /*tp_as_number*/
1801 0, /*tp_as_sequence*/
1802 0, /*tp_as_mapping*/
1803 0, /*tp_hash */
1804 0, /*tp_call*/
1805 0, /*tp_str*/
1806 0, /*tp_getattro*/
1807 0, /*tp_setattro*/
1808 0, /*tp_as_buffer*/
1809 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02001810 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001811 bufferedreader_doc, /* tp_doc */
1812 (traverseproc)buffered_traverse, /* tp_traverse */
1813 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001814 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001815 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001816 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001817 (iternextfunc)buffered_iternext, /* tp_iternext */
1818 bufferedreader_methods, /* tp_methods */
1819 bufferedreader_members, /* tp_members */
1820 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001821 0, /* tp_base */
1822 0, /* tp_dict */
1823 0, /* tp_descr_get */
1824 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001825 offsetof(buffered, dict), /* tp_dictoffset */
1826 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001827 0, /* tp_alloc */
1828 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02001829 0, /* tp_free */
1830 0, /* tp_is_gc */
1831 0, /* tp_bases */
1832 0, /* tp_mro */
1833 0, /* tp_cache */
1834 0, /* tp_subclasses */
1835 0, /* tp_weaklist */
1836 0, /* tp_del */
1837 0, /* tp_version_tag */
1838 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001839};
1840
1841
Benjamin Peterson59406a92009-03-26 17:10:29 +00001842
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001843/*
1844 * class BufferedWriter
1845 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001846PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001847 "A buffer for a writeable sequential RawIO object.\n"
1848 "\n"
1849 "The constructor creates a BufferedWriter for the given writeable raw\n"
1850 "stream. If the buffer_size is not given, it defaults to\n"
Florent Xicluna109d5732012-07-07 17:03:22 +02001851 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001852 );
1853
1854static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001855_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001856{
1857 self->write_pos = 0;
1858 self->write_end = -1;
1859}
1860
1861static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001862bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001863{
Florent Xicluna109d5732012-07-07 17:03:22 +02001864 char *kwlist[] = {"raw", "buffer_size", NULL};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001865 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001866 PyObject *raw;
1867
1868 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001869 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001870
R David Murray9f10f562013-02-23 22:07:55 -05001871 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedWriter", kwlist,
Florent Xicluna109d5732012-07-07 17:03:22 +02001872 &raw, &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001873 return -1;
1874 }
1875
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001876 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001877 return -1;
1878
1879 Py_CLEAR(self->raw);
1880 Py_INCREF(raw);
1881 self->raw = raw;
1882 self->readable = 0;
1883 self->writable = 1;
1884
1885 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001886 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001887 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001888 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001889 self->pos = 0;
1890
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001891 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1892 Py_TYPE(raw) == &PyFileIO_Type);
1893
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001894 self->ok = 1;
1895 return 0;
1896}
1897
1898static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001899_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001900{
1901 Py_buffer buf;
1902 PyObject *memobj, *res;
1903 Py_ssize_t n;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001904 int errnum;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001905 /* NOTE: the buffer needn't be released as its object is NULL. */
1906 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1907 return -1;
1908 memobj = PyMemoryView_FromBuffer(&buf);
1909 if (memobj == NULL)
1910 return -1;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001911 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1912 occurs so we needn't do it ourselves.
1913 We then retry writing, ignoring the signal if no handler has
1914 raised (see issue #10956).
1915 */
1916 do {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001917 errno = 0;
Antoine Pitrou707ce822011-02-25 21:24:11 +00001918 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001919 errnum = errno;
Gregory P. Smith51359922012-06-23 23:55:39 -07001920 } while (res == NULL && _PyIO_trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001921 Py_DECREF(memobj);
1922 if (res == NULL)
1923 return -1;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001924 if (res == Py_None) {
1925 /* Non-blocking stream would have blocked. Special return code!
1926 Being paranoid we reset errno in case it is changed by code
1927 triggered by a decref. errno is used by _set_BlockingIOError(). */
1928 Py_DECREF(res);
1929 errno = errnum;
1930 return -2;
1931 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001932 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1933 Py_DECREF(res);
1934 if (n < 0 || n > len) {
1935 PyErr_Format(PyExc_IOError,
1936 "raw write() returned invalid length %zd "
1937 "(should have been between 0 and %zd)", n, len);
1938 return -1;
1939 }
1940 if (n > 0 && self->abs_pos != -1)
1941 self->abs_pos += n;
1942 return n;
1943}
1944
1945/* `restore_pos` is 1 if we need to restore the raw stream position at
1946 the end, 0 otherwise. */
1947static PyObject *
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001948_bufferedwriter_flush_unlocked(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001949{
1950 Py_ssize_t written = 0;
1951 Py_off_t n, rewind;
1952
1953 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1954 goto end;
1955 /* First, rewind */
1956 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1957 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001958 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001959 if (n < 0) {
1960 goto error;
1961 }
1962 self->raw_pos -= rewind;
1963 }
1964 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001965 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001966 self->buffer + self->write_pos,
1967 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1968 Py_off_t, Py_ssize_t));
1969 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01001970 goto error;
1971 }
1972 else if (n == -2) {
1973 _set_BlockingIOError("write could not complete without blocking",
1974 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001975 goto error;
1976 }
1977 self->write_pos += n;
1978 self->raw_pos = self->write_pos;
1979 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001980 /* Partial writes can return successfully when interrupted by a
1981 signal (see write(2)). We must run signal handlers before
1982 blocking another time, possibly indefinitely. */
1983 if (PyErr_CheckSignals() < 0)
1984 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001985 }
1986
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001987 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001988
1989end:
1990 Py_RETURN_NONE;
1991
1992error:
1993 return NULL;
1994}
1995
1996static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001997bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001998{
1999 PyObject *res = NULL;
2000 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002001 Py_ssize_t written, avail, remaining;
2002 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002003
2004 CHECK_INITIALIZED(self)
2005 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
2006 return NULL;
2007 }
2008
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002009 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002010 PyErr_SetString(PyExc_ValueError, "write to closed file");
2011 PyBuffer_Release(&buf);
2012 return NULL;
2013 }
2014
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00002015 if (!ENTER_BUFFERED(self)) {
2016 PyBuffer_Release(&buf);
2017 return NULL;
2018 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002019
2020 /* Fast path: the data to write can be fully buffered. */
2021 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
2022 self->pos = 0;
2023 self->raw_pos = 0;
2024 }
2025 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
2026 if (buf.len <= avail) {
2027 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02002028 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002029 self->write_pos = self->pos;
2030 }
2031 ADJUST_POSITION(self, self->pos + buf.len);
2032 if (self->pos > self->write_end)
2033 self->write_end = self->pos;
2034 written = buf.len;
2035 goto end;
2036 }
2037
2038 /* First write the current buffer */
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002039 res = _bufferedwriter_flush_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002040 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002041 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002042 if (w == NULL)
2043 goto error;
2044 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002045 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002046 /* Make some place by shifting the buffer. */
2047 assert(VALID_WRITE_BUFFER(self));
2048 memmove(self->buffer, self->buffer + self->write_pos,
2049 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2050 Py_off_t, Py_ssize_t));
2051 self->write_end -= self->write_pos;
2052 self->raw_pos -= self->write_pos;
2053 self->pos -= self->write_pos;
2054 self->write_pos = 0;
2055 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
2056 Py_off_t, Py_ssize_t);
2057 if (buf.len <= avail) {
2058 /* Everything can be buffered */
2059 PyErr_Clear();
2060 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
2061 self->write_end += buf.len;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002062 self->pos += buf.len;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002063 written = buf.len;
2064 goto end;
2065 }
2066 /* Buffer as much as possible. */
2067 memcpy(self->buffer + self->write_end, buf.buf, avail);
2068 self->write_end += avail;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002069 self->pos += avail;
2070 /* XXX Modifying the existing exception e using the pointer w
2071 will change e.characters_written but not e.args[2].
2072 Therefore we just replace with a new error. */
2073 _set_BlockingIOError("write could not complete without blocking",
2074 avail);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002075 goto error;
2076 }
2077 Py_CLEAR(res);
2078
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002079 /* Adjust the raw stream position if it is away from the logical stream
2080 position. This happens if the read buffer has been filled but not
2081 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2082 the raw stream by itself).
2083 Fixes issue #6629.
2084 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002085 offset = RAW_OFFSET(self);
2086 if (offset != 0) {
2087 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002088 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002089 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00002090 }
2091
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002092 /* Then write buf itself. At this point the buffer has been emptied. */
2093 remaining = buf.len;
2094 written = 0;
2095 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00002096 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002097 self, (char *) buf.buf + written, buf.len - written);
2098 if (n == -1) {
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002099 goto error;
2100 } else if (n == -2) {
2101 /* Write failed because raw file is non-blocking */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002102 if (remaining > self->buffer_size) {
2103 /* Can't buffer everything, still buffer as much as possible */
2104 memcpy(self->buffer,
2105 (char *) buf.buf + written, self->buffer_size);
2106 self->raw_pos = 0;
2107 ADJUST_POSITION(self, self->buffer_size);
2108 self->write_end = self->buffer_size;
Antoine Pitrou58fcf9f2011-11-21 20:16:44 +01002109 written += self->buffer_size;
2110 _set_BlockingIOError("write could not complete without "
2111 "blocking", written);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002112 goto error;
2113 }
2114 PyErr_Clear();
2115 break;
2116 }
2117 written += n;
2118 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00002119 /* Partial writes can return successfully when interrupted by a
2120 signal (see write(2)). We must run signal handlers before
2121 blocking another time, possibly indefinitely. */
2122 if (PyErr_CheckSignals() < 0)
2123 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002124 }
2125 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002126 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002127 if (remaining > 0) {
2128 memcpy(self->buffer, (char *) buf.buf + written, remaining);
2129 written += remaining;
2130 }
2131 self->write_pos = 0;
2132 /* TODO: sanity check (remaining >= 0) */
2133 self->write_end = remaining;
2134 ADJUST_POSITION(self, remaining);
2135 self->raw_pos = 0;
2136
2137end:
2138 res = PyLong_FromSsize_t(written);
2139
2140error:
2141 LEAVE_BUFFERED(self)
2142 PyBuffer_Release(&buf);
2143 return res;
2144}
2145
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002146static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002147 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002148 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2149 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2150 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2151 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2152 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2153 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2154 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002155 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002156 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002157
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002158 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2159 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2160 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2161 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2162 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002163 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002164 {NULL, NULL}
2165};
2166
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002167static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002168 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02002169 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002170 {NULL}
2171};
2172
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002173static PyGetSetDef bufferedwriter_getset[] = {
2174 {"closed", (getter)buffered_closed_get, NULL, NULL},
2175 {"name", (getter)buffered_name_get, NULL, NULL},
2176 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002177 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002178};
2179
2180
2181PyTypeObject PyBufferedWriter_Type = {
2182 PyVarObject_HEAD_INIT(NULL, 0)
2183 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002184 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002185 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002186 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002187 0, /*tp_print*/
2188 0, /*tp_getattr*/
2189 0, /*tp_setattr*/
2190 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002191 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002192 0, /*tp_as_number*/
2193 0, /*tp_as_sequence*/
2194 0, /*tp_as_mapping*/
2195 0, /*tp_hash */
2196 0, /*tp_call*/
2197 0, /*tp_str*/
2198 0, /*tp_getattro*/
2199 0, /*tp_setattro*/
2200 0, /*tp_as_buffer*/
2201 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002202 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002203 bufferedwriter_doc, /* tp_doc */
2204 (traverseproc)buffered_traverse, /* tp_traverse */
2205 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002206 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002207 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002208 0, /* tp_iter */
2209 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002210 bufferedwriter_methods, /* tp_methods */
2211 bufferedwriter_members, /* tp_members */
2212 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002213 0, /* tp_base */
2214 0, /* tp_dict */
2215 0, /* tp_descr_get */
2216 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002217 offsetof(buffered, dict), /* tp_dictoffset */
2218 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002219 0, /* tp_alloc */
2220 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002221 0, /* tp_free */
2222 0, /* tp_is_gc */
2223 0, /* tp_bases */
2224 0, /* tp_mro */
2225 0, /* tp_cache */
2226 0, /* tp_subclasses */
2227 0, /* tp_weaklist */
2228 0, /* tp_del */
2229 0, /* tp_version_tag */
2230 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002231};
2232
2233
2234
2235/*
2236 * BufferedRWPair
2237 */
2238
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002239PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002240 "A buffered reader and writer object together.\n"
2241 "\n"
2242 "A buffered reader object and buffered writer object put together to\n"
2243 "form a sequential IO object that can read and write. This is typically\n"
2244 "used with a socket or two-way pipe.\n"
2245 "\n"
2246 "reader and writer are RawIOBase objects that are readable and\n"
2247 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002248 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002249 );
2250
2251/* XXX The usefulness of this (compared to having two separate IO objects) is
2252 * questionable.
2253 */
2254
2255typedef struct {
2256 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002257 buffered *reader;
2258 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002259 PyObject *dict;
2260 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002261} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002262
2263static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002264bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002265{
2266 PyObject *reader, *writer;
2267 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002268
Florent Xicluna109d5732012-07-07 17:03:22 +02002269 if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer,
2270 &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002271 return -1;
2272 }
2273
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002274 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002275 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002276 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002277 return -1;
2278
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002279 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002280 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002281 if (self->reader == NULL)
2282 return -1;
2283
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002284 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002285 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002286 if (self->writer == NULL) {
2287 Py_CLEAR(self->reader);
2288 return -1;
2289 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002290
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002291 return 0;
2292}
2293
2294static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002295bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002296{
2297 Py_VISIT(self->dict);
2298 return 0;
2299}
2300
2301static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002302bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002303{
2304 Py_CLEAR(self->reader);
2305 Py_CLEAR(self->writer);
2306 Py_CLEAR(self->dict);
2307 return 0;
2308}
2309
2310static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002311bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002312{
2313 _PyObject_GC_UNTRACK(self);
Benjamin Petersonbbd0a322014-09-29 22:46:57 -04002314 if (self->weakreflist != NULL)
2315 PyObject_ClearWeakRefs((PyObject *)self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002316 Py_CLEAR(self->reader);
2317 Py_CLEAR(self->writer);
2318 Py_CLEAR(self->dict);
2319 Py_TYPE(self)->tp_free((PyObject *) self);
2320}
2321
2322static PyObject *
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002323_forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002324{
Serhiy Storchaka61e24932014-02-12 10:52:35 +02002325 PyObject *func, *ret;
2326 if (self == NULL) {
2327 PyErr_SetString(PyExc_ValueError,
2328 "I/O operation on uninitialized object");
2329 return NULL;
2330 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002331
Serhiy Storchaka61e24932014-02-12 10:52:35 +02002332 func = _PyObject_GetAttrId((PyObject *)self, name);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002333 if (func == NULL) {
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002334 PyErr_SetString(PyExc_AttributeError, name->string);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002335 return NULL;
2336 }
2337
2338 ret = PyObject_CallObject(func, args);
2339 Py_DECREF(func);
2340 return ret;
2341}
2342
2343static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002344bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002345{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002346 return _forward_call(self->reader, &PyId_read, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002347}
2348
2349static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002350bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002351{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002352 return _forward_call(self->reader, &PyId_peek, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002353}
2354
2355static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002356bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002357{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002358 return _forward_call(self->reader, &PyId_read1, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002359}
2360
2361static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002362bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002363{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002364 return _forward_call(self->reader, &PyId_readinto, args);
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002365}
2366
2367static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002368bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002369{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002370 return _forward_call(self->writer, &PyId_write, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002371}
2372
2373static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002374bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002375{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002376 return _forward_call(self->writer, &PyId_flush, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002377}
2378
2379static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002380bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002381{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002382 return _forward_call(self->reader, &PyId_readable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002383}
2384
2385static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002386bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002387{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002388 return _forward_call(self->writer, &PyId_writable, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002389}
2390
2391static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002392bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002393{
Serhiy Storchaka7665be62015-03-24 23:21:57 +02002394 PyObject *exc = NULL, *val, *tb;
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002395 PyObject *ret = _forward_call(self->writer, &PyId_close, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002396 if (ret == NULL)
Serhiy Storchaka7665be62015-03-24 23:21:57 +02002397 PyErr_Fetch(&exc, &val, &tb);
2398 else
2399 Py_DECREF(ret);
2400 ret = _forward_call(self->reader, &PyId_close, args);
2401 if (exc != NULL) {
2402 _PyErr_ChainExceptions(exc, val, tb);
2403 Py_CLEAR(ret);
2404 }
2405 return ret;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002406}
2407
2408static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002409bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002410{
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002411 PyObject *ret = _forward_call(self->writer, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002412
2413 if (ret != Py_False) {
2414 /* either True or exception */
2415 return ret;
2416 }
2417 Py_DECREF(ret);
2418
Martin v. Löwisafe55bb2011-10-09 10:38:36 +02002419 return _forward_call(self->reader, &PyId_isatty, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002420}
2421
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002422static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002423bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002424{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002425 if (self->writer == NULL) {
2426 PyErr_SetString(PyExc_RuntimeError,
2427 "the BufferedRWPair object is being garbage-collected");
2428 return NULL;
2429 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002430 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2431}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002432
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002433static PyMethodDef bufferedrwpair_methods[] = {
2434 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2435 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2436 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2437 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002438
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002439 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2440 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002441
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002442 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2443 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002444
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002445 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2446 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002447
Antoine Pitrou243757e2010-11-05 21:15:39 +00002448 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2449
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002450 {NULL, NULL}
2451};
2452
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002453static PyGetSetDef bufferedrwpair_getset[] = {
2454 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002455 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002456};
2457
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002458PyTypeObject PyBufferedRWPair_Type = {
2459 PyVarObject_HEAD_INIT(NULL, 0)
2460 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002461 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002462 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002463 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002464 0, /*tp_print*/
2465 0, /*tp_getattr*/
2466 0, /*tp_setattr*/
2467 0, /*tp_compare */
2468 0, /*tp_repr*/
2469 0, /*tp_as_number*/
2470 0, /*tp_as_sequence*/
2471 0, /*tp_as_mapping*/
2472 0, /*tp_hash */
2473 0, /*tp_call*/
2474 0, /*tp_str*/
2475 0, /*tp_getattro*/
2476 0, /*tp_setattro*/
2477 0, /*tp_as_buffer*/
2478 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002479 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002480 bufferedrwpair_doc, /* tp_doc */
2481 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2482 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002483 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002484 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002485 0, /* tp_iter */
2486 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002487 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002488 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002489 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002490 0, /* tp_base */
2491 0, /* tp_dict */
2492 0, /* tp_descr_get */
2493 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002494 offsetof(rwpair, dict), /* tp_dictoffset */
2495 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002496 0, /* tp_alloc */
2497 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002498 0, /* tp_free */
2499 0, /* tp_is_gc */
2500 0, /* tp_bases */
2501 0, /* tp_mro */
2502 0, /* tp_cache */
2503 0, /* tp_subclasses */
2504 0, /* tp_weaklist */
2505 0, /* tp_del */
2506 0, /* tp_version_tag */
2507 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002508};
2509
2510
2511
2512/*
2513 * BufferedRandom
2514 */
2515
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002516PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002517 "A buffered interface to random access streams.\n"
2518 "\n"
2519 "The constructor creates a reader and writer for a seekable stream,\n"
2520 "raw, given in the first argument. If the buffer_size is omitted it\n"
Florent Xicluna109d5732012-07-07 17:03:22 +02002521 "defaults to DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002522 );
2523
2524static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002525bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002526{
Florent Xicluna109d5732012-07-07 17:03:22 +02002527 char *kwlist[] = {"raw", "buffer_size", NULL};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002528 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002529 PyObject *raw;
2530
2531 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002532 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002533
R David Murray9f10f562013-02-23 22:07:55 -05002534 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedRandom", kwlist,
Florent Xicluna109d5732012-07-07 17:03:22 +02002535 &raw, &buffer_size)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002536 return -1;
2537 }
2538
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002539 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002540 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002541 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002542 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002543 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002544 return -1;
2545
2546 Py_CLEAR(self->raw);
2547 Py_INCREF(raw);
2548 self->raw = raw;
2549 self->buffer_size = buffer_size;
2550 self->readable = 1;
2551 self->writable = 1;
2552
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002553 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002554 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002555 _bufferedreader_reset_buf(self);
2556 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002557 self->pos = 0;
2558
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002559 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2560 Py_TYPE(raw) == &PyFileIO_Type);
2561
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002562 self->ok = 1;
2563 return 0;
2564}
2565
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002566static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002567 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002568 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2569 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2570 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2571 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2572 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2573 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2574 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002575 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002576 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002577
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002578 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002579
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002580 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2581 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2582 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2583 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2584 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2585 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2586 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2587 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2588 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Antoine Pitrou10f0c502012-07-29 19:02:46 +02002589 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002590 {NULL, NULL}
2591};
2592
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002593static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002594 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou796564c2013-07-30 19:59:21 +02002595 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002596 {NULL}
2597};
2598
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002599static PyGetSetDef bufferedrandom_getset[] = {
2600 {"closed", (getter)buffered_closed_get, NULL, NULL},
2601 {"name", (getter)buffered_name_get, NULL, NULL},
2602 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002603 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002604};
2605
2606
2607PyTypeObject PyBufferedRandom_Type = {
2608 PyVarObject_HEAD_INIT(NULL, 0)
2609 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002610 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002611 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002612 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002613 0, /*tp_print*/
2614 0, /*tp_getattr*/
2615 0, /*tp_setattr*/
2616 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002617 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002618 0, /*tp_as_number*/
2619 0, /*tp_as_sequence*/
2620 0, /*tp_as_mapping*/
2621 0, /*tp_hash */
2622 0, /*tp_call*/
2623 0, /*tp_str*/
2624 0, /*tp_getattro*/
2625 0, /*tp_setattro*/
2626 0, /*tp_as_buffer*/
2627 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
Antoine Pitrou796564c2013-07-30 19:59:21 +02002628 | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002629 bufferedrandom_doc, /* tp_doc */
2630 (traverseproc)buffered_traverse, /* tp_traverse */
2631 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002632 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002633 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002634 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002635 (iternextfunc)buffered_iternext, /* tp_iternext */
2636 bufferedrandom_methods, /* tp_methods */
2637 bufferedrandom_members, /* tp_members */
2638 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002639 0, /* tp_base */
2640 0, /*tp_dict*/
2641 0, /* tp_descr_get */
2642 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002643 offsetof(buffered, dict), /*tp_dictoffset*/
2644 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002645 0, /* tp_alloc */
2646 PyType_GenericNew, /* tp_new */
Antoine Pitrou796564c2013-07-30 19:59:21 +02002647 0, /* tp_free */
2648 0, /* tp_is_gc */
2649 0, /* tp_bases */
2650 0, /* tp_mro */
2651 0, /* tp_cache */
2652 0, /* tp_subclasses */
2653 0, /* tp_weaklist */
2654 0, /* tp_del */
2655 0, /* tp_version_tag */
2656 0, /* tp_finalize */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002657};