blob: c979ac2336d19f3742eb9afecc13a95637ff07ce [file] [log] [blame]
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001/*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
3
4 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
6
7 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8*/
9
10#define PY_SSIZE_T_CLEAN
11#include "Python.h"
12#include "structmember.h"
13#include "pythread.h"
14#include "_iomodule.h"
15
16/*
17 * BufferedIOBase class, inherits from IOBase.
18 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000019PyDoc_STRVAR(bufferediobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000020 "Base class for buffered IO objects.\n"
21 "\n"
22 "The main difference with RawIOBase is that the read() method\n"
23 "supports omitting the size argument, and does not have a default\n"
24 "implementation that defers to readinto().\n"
25 "\n"
26 "In addition, read(), readinto() and write() may raise\n"
27 "BlockingIOError if the underlying raw stream is in non-blocking\n"
28 "mode and not ready; unlike their raw counterparts, they will never\n"
29 "return None.\n"
30 "\n"
31 "A typical implementation should not inherit from a RawIOBase\n"
32 "implementation, but wrap one.\n"
33 );
34
35static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000036bufferediobase_readinto(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000037{
38 Py_buffer buf;
39 Py_ssize_t len;
40 PyObject *data;
41
42 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
43 return NULL;
44 }
45
46 data = PyObject_CallMethod(self, "read", "n", buf.len);
47 if (data == NULL)
48 goto error;
49
50 if (!PyBytes_Check(data)) {
51 Py_DECREF(data);
52 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
53 goto error;
54 }
55
56 len = Py_SIZE(data);
57 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
58
59 PyBuffer_Release(&buf);
60 Py_DECREF(data);
61
62 return PyLong_FromSsize_t(len);
63
64 error:
65 PyBuffer_Release(&buf);
66 return NULL;
67}
68
69static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000070bufferediobase_unsupported(const char *message)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000071{
72 PyErr_SetString(IO_STATE->unsupported_operation, message);
73 return NULL;
74}
75
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000076PyDoc_STRVAR(bufferediobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +000077 "Disconnect this buffer from its underlying raw stream and return it.\n"
78 "\n"
79 "After the raw stream has been detached, the buffer is in an unusable\n"
80 "state.\n");
81
82static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000083bufferediobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +000084{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000085 return bufferediobase_unsupported("detach");
Benjamin Petersond2e0c792009-05-01 20:40:59 +000086}
87
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000088PyDoc_STRVAR(bufferediobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000089 "Read and return up to n bytes.\n"
90 "\n"
91 "If the argument is omitted, None, or negative, reads and\n"
92 "returns all data until EOF.\n"
93 "\n"
94 "If the argument is positive, and the underlying raw stream is\n"
95 "not 'interactive', multiple raw reads may be issued to satisfy\n"
96 "the byte count (unless EOF is reached first). But for\n"
97 "interactive raw streams (as well as sockets and pipes), at most\n"
98 "one raw read will be issued, and a short result does not imply\n"
99 "that EOF is imminent.\n"
100 "\n"
101 "Returns an empty bytes object on EOF.\n"
102 "\n"
103 "Returns None if the underlying raw stream was open in non-blocking\n"
104 "mode and no data is available at the moment.\n");
105
106static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000107bufferediobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000108{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000109 return bufferediobase_unsupported("read");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000110}
111
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000112PyDoc_STRVAR(bufferediobase_read1_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000113 "Read and return up to n bytes, with at most one read() call\n"
114 "to the underlying raw stream. A short result does not imply\n"
115 "that EOF is imminent.\n"
116 "\n"
117 "Returns an empty bytes object on EOF.\n");
118
119static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000120bufferediobase_read1(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000121{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000122 return bufferediobase_unsupported("read1");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000123}
124
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000125PyDoc_STRVAR(bufferediobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000126 "Write the given buffer to the IO stream.\n"
127 "\n"
128 "Returns the number of bytes written, which is never less than\n"
129 "len(b).\n"
130 "\n"
131 "Raises BlockingIOError if the buffer is full and the\n"
132 "underlying raw stream cannot accept more data at the moment.\n");
133
134static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000135bufferediobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000136{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000137 return bufferediobase_unsupported("write");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000138}
139
140
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000141static PyMethodDef bufferediobase_methods[] = {
142 {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
143 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
144 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
145 {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
146 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000147 {NULL, NULL}
148};
149
150PyTypeObject PyBufferedIOBase_Type = {
151 PyVarObject_HEAD_INIT(NULL, 0)
152 "_io._BufferedIOBase", /*tp_name*/
153 0, /*tp_basicsize*/
154 0, /*tp_itemsize*/
155 0, /*tp_dealloc*/
156 0, /*tp_print*/
157 0, /*tp_getattr*/
158 0, /*tp_setattr*/
159 0, /*tp_compare */
160 0, /*tp_repr*/
161 0, /*tp_as_number*/
162 0, /*tp_as_sequence*/
163 0, /*tp_as_mapping*/
164 0, /*tp_hash */
165 0, /*tp_call*/
166 0, /*tp_str*/
167 0, /*tp_getattro*/
168 0, /*tp_setattro*/
169 0, /*tp_as_buffer*/
170 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000171 bufferediobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000172 0, /* tp_traverse */
173 0, /* tp_clear */
174 0, /* tp_richcompare */
175 0, /* tp_weaklistoffset */
176 0, /* tp_iter */
177 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000178 bufferediobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000179 0, /* tp_members */
180 0, /* tp_getset */
181 &PyIOBase_Type, /* tp_base */
182 0, /* tp_dict */
183 0, /* tp_descr_get */
184 0, /* tp_descr_set */
185 0, /* tp_dictoffset */
186 0, /* tp_init */
187 0, /* tp_alloc */
188 0, /* tp_new */
189};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000190
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000191
192typedef struct {
193 PyObject_HEAD
194
195 PyObject *raw;
196 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000197 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000198 int readable;
199 int writable;
Antoine Pitroue033e062010-10-29 10:38:18 +0000200 int deallocating;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000201
202 /* True if this is a vanilla Buffered object (rather than a user derived
203 class) *and* the raw stream is a vanilla FileIO object. */
204 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000205
206 /* Absolute position inside the raw stream (-1 if unknown). */
207 Py_off_t abs_pos;
208
209 /* A static buffer of size `buffer_size` */
210 char *buffer;
211 /* Current logical position in the buffer. */
212 Py_off_t pos;
213 /* Position of the raw stream in the buffer. */
214 Py_off_t raw_pos;
215
216 /* Just after the last buffered byte in the buffer, or -1 if the buffer
217 isn't ready for reading. */
218 Py_off_t read_end;
219
220 /* Just after the last byte actually written */
221 Py_off_t write_pos;
222 /* Just after the last byte waiting to be written, or -1 if the buffer
223 isn't ready for writing. */
224 Py_off_t write_end;
225
Georg Brandldfd73442009-04-05 11:47:34 +0000226#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000227 PyThread_type_lock lock;
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000228 volatile long owner;
Georg Brandldfd73442009-04-05 11:47:34 +0000229#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000230
231 Py_ssize_t buffer_size;
232 Py_ssize_t buffer_mask;
233
234 PyObject *dict;
235 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000236} buffered;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000237
238/*
239 Implementation notes:
240
241 * BufferedReader, BufferedWriter and BufferedRandom try to share most
242 methods (this is helped by the members `readable` and `writable`, which
243 are initialized in the respective constructors)
244 * They also share a single buffer for reading and writing. This enables
245 interleaved reads and writes without flushing. It also makes the logic
246 a bit trickier to get right.
247 * The absolute position of the raw stream is cached, if possible, in the
248 `abs_pos` member. It must be updated every time an operation is done
249 on the raw stream. If not sure, it can be reinitialized by calling
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000250 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000251 also does it). To read it, use RAW_TELL().
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000252 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
253 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000254
255 NOTE: we should try to maintain block alignment of reads and writes to the
256 raw stream (according to the buffer size), but for now it is only done
257 in read() and friends.
258
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000259*/
260
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000261/* These macros protect the buffered object against concurrent operations. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000262
Georg Brandldfd73442009-04-05 11:47:34 +0000263#ifdef WITH_THREAD
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000264
265static int
266_enter_buffered_busy(buffered *self)
267{
268 if (self->owner == PyThread_get_thread_ident()) {
269 PyErr_Format(PyExc_RuntimeError,
270 "reentrant call inside %R", self);
271 return 0;
Antoine Pitrou5800b272009-11-01 12:05:48 +0000272 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000273 Py_BEGIN_ALLOW_THREADS
274 PyThread_acquire_lock(self->lock, 1);
275 Py_END_ALLOW_THREADS
276 return 1;
277}
278
279#define ENTER_BUFFERED(self) \
280 ( (PyThread_acquire_lock(self->lock, 0) ? \
281 1 : _enter_buffered_busy(self)) \
282 && (self->owner = PyThread_get_thread_ident(), 1) )
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000283
284#define LEAVE_BUFFERED(self) \
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000285 do { \
286 self->owner = 0; \
287 PyThread_release_lock(self->lock); \
288 } while(0);
289
Georg Brandldfd73442009-04-05 11:47:34 +0000290#else
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000291#define ENTER_BUFFERED(self) 1
Georg Brandldfd73442009-04-05 11:47:34 +0000292#define LEAVE_BUFFERED(self)
293#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000294
295#define CHECK_INITIALIZED(self) \
296 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000297 if (self->detached) { \
298 PyErr_SetString(PyExc_ValueError, \
299 "raw stream has been detached"); \
300 } else { \
301 PyErr_SetString(PyExc_ValueError, \
302 "I/O operation on uninitialized object"); \
303 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000304 return NULL; \
305 }
306
307#define CHECK_INITIALIZED_INT(self) \
308 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000309 if (self->detached) { \
310 PyErr_SetString(PyExc_ValueError, \
311 "raw stream has been detached"); \
312 } else { \
313 PyErr_SetString(PyExc_ValueError, \
314 "I/O operation on uninitialized object"); \
315 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000316 return -1; \
317 }
318
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000319#define IS_CLOSED(self) \
320 (self->fast_closed_checks \
321 ? _PyFileIO_closed(self->raw) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000322 : buffered_closed(self))
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000323
324#define CHECK_CLOSED(self, error_msg) \
325 if (IS_CLOSED(self)) { \
326 PyErr_SetString(PyExc_ValueError, error_msg); \
327 return NULL; \
328 }
329
330
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000331#define VALID_READ_BUFFER(self) \
332 (self->readable && self->read_end != -1)
333
334#define VALID_WRITE_BUFFER(self) \
335 (self->writable && self->write_end != -1)
336
337#define ADJUST_POSITION(self, _new_pos) \
338 do { \
339 self->pos = _new_pos; \
340 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
341 self->read_end = self->pos; \
342 } while(0)
343
344#define READAHEAD(self) \
345 ((self->readable && VALID_READ_BUFFER(self)) \
346 ? (self->read_end - self->pos) : 0)
347
348#define RAW_OFFSET(self) \
349 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
350 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
351
352#define RAW_TELL(self) \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000353 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000354
355#define MINUS_LAST_BLOCK(self, size) \
356 (self->buffer_mask ? \
357 (size & ~self->buffer_mask) : \
358 (self->buffer_size * (size / self->buffer_size)))
359
360
361static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000362buffered_dealloc(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000363{
Antoine Pitroue033e062010-10-29 10:38:18 +0000364 self->deallocating = 1;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000365 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
366 return;
367 _PyObject_GC_UNTRACK(self);
368 self->ok = 0;
369 if (self->weakreflist != NULL)
370 PyObject_ClearWeakRefs((PyObject *)self);
371 Py_CLEAR(self->raw);
372 if (self->buffer) {
373 PyMem_Free(self->buffer);
374 self->buffer = NULL;
375 }
Georg Brandldfd73442009-04-05 11:47:34 +0000376#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000377 if (self->lock) {
378 PyThread_free_lock(self->lock);
379 self->lock = NULL;
380 }
Georg Brandldfd73442009-04-05 11:47:34 +0000381#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000382 Py_CLEAR(self->dict);
383 Py_TYPE(self)->tp_free((PyObject *)self);
384}
385
386static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000387buffered_traverse(buffered *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000388{
389 Py_VISIT(self->raw);
390 Py_VISIT(self->dict);
391 return 0;
392}
393
394static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000395buffered_clear(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000396{
397 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
398 return -1;
399 self->ok = 0;
400 Py_CLEAR(self->raw);
401 Py_CLEAR(self->dict);
402 return 0;
403}
404
Antoine Pitroue033e062010-10-29 10:38:18 +0000405/* Because this can call arbitrary code, it shouldn't be called when
406 the refcount is 0 (that is, not directly from tp_dealloc unless
407 the refcount has been temporarily re-incremented). */
Matthias Klosebee33162010-11-16 20:07:51 +0000408static PyObject *
Antoine Pitroue033e062010-10-29 10:38:18 +0000409buffered_dealloc_warn(buffered *self, PyObject *source)
410{
411 if (self->ok && self->raw) {
412 PyObject *r;
413 r = PyObject_CallMethod(self->raw, "_dealloc_warn", "O", source);
414 if (r)
415 Py_DECREF(r);
416 else
417 PyErr_Clear();
418 }
419 Py_RETURN_NONE;
420}
421
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000422/*
423 * _BufferedIOMixin methods
424 * This is not a class, just a collection of methods that will be reused
425 * by BufferedReader and BufferedWriter
426 */
427
428/* Flush and close */
429
430static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000431buffered_simple_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000432{
433 CHECK_INITIALIZED(self)
434 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
435}
436
437static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000438buffered_closed(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000439{
440 int closed;
441 PyObject *res;
442 CHECK_INITIALIZED_INT(self)
443 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
444 if (res == NULL)
445 return -1;
446 closed = PyObject_IsTrue(res);
447 Py_DECREF(res);
448 return closed;
449}
450
451static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000452buffered_closed_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000453{
454 CHECK_INITIALIZED(self)
455 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
456}
457
458static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000459buffered_close(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000460{
461 PyObject *res = NULL;
462 int r;
463
464 CHECK_INITIALIZED(self)
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000465 if (!ENTER_BUFFERED(self))
466 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000467
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000468 r = buffered_closed(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000469 if (r < 0)
470 goto end;
471 if (r > 0) {
472 res = Py_None;
473 Py_INCREF(res);
474 goto end;
475 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000476
477 if (self->deallocating) {
478 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
479 if (r)
480 Py_DECREF(r);
481 else
482 PyErr_Clear();
483 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000484 /* flush() will most probably re-take the lock, so drop it first */
485 LEAVE_BUFFERED(self)
486 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000487 if (!ENTER_BUFFERED(self))
488 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000489 if (res == NULL) {
Antoine Pitrou6be88762010-05-03 16:48:20 +0000490 goto end;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000491 }
492 Py_XDECREF(res);
493
494 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
495
496end:
497 LEAVE_BUFFERED(self)
498 return res;
499}
500
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000501/* detach */
502
503static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000504buffered_detach(buffered *self, PyObject *args)
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000505{
506 PyObject *raw, *res;
507 CHECK_INITIALIZED(self)
508 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
509 if (res == NULL)
510 return NULL;
511 Py_DECREF(res);
512 raw = self->raw;
513 self->raw = NULL;
514 self->detached = 1;
515 self->ok = 0;
516 return raw;
517}
518
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000519/* Inquiries */
520
521static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000522buffered_seekable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000523{
524 CHECK_INITIALIZED(self)
525 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
526}
527
528static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000529buffered_readable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000530{
531 CHECK_INITIALIZED(self)
532 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
533}
534
535static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000536buffered_writable(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000537{
538 CHECK_INITIALIZED(self)
539 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
540}
541
542static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000543buffered_name_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000544{
545 CHECK_INITIALIZED(self)
546 return PyObject_GetAttrString(self->raw, "name");
547}
548
549static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000550buffered_mode_get(buffered *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000551{
552 CHECK_INITIALIZED(self)
553 return PyObject_GetAttrString(self->raw, "mode");
554}
555
556/* Lower-level APIs */
557
558static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000559buffered_fileno(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000560{
561 CHECK_INITIALIZED(self)
562 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
563}
564
565static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000566buffered_isatty(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000567{
568 CHECK_INITIALIZED(self)
569 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
570}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000571
Antoine Pitrou243757e2010-11-05 21:15:39 +0000572/* Serialization */
573
574static PyObject *
575buffered_getstate(buffered *self, PyObject *args)
576{
577 PyErr_Format(PyExc_TypeError,
578 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
579 return NULL;
580}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000581
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000582/* Forward decls */
583static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000584_bufferedwriter_flush_unlocked(buffered *, int);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000585static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000586_bufferedreader_fill_buffer(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000587static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000588_bufferedreader_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000589static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000590_bufferedwriter_reset_buf(buffered *self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000591static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000592_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000593static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000594_bufferedreader_read_all(buffered *self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000595static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000596_bufferedreader_read_fast(buffered *self, Py_ssize_t);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000597static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000598_bufferedreader_read_generic(buffered *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000599
600
601/*
602 * Helpers
603 */
604
605/* Returns the address of the `written` member if a BlockingIOError was
606 raised, NULL otherwise. The error is always re-raised. */
607static Py_ssize_t *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000608_buffered_check_blocking_error(void)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000609{
610 PyObject *t, *v, *tb;
611 PyBlockingIOErrorObject *err;
612
613 PyErr_Fetch(&t, &v, &tb);
614 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
615 PyErr_Restore(t, v, tb);
616 return NULL;
617 }
618 err = (PyBlockingIOErrorObject *) v;
619 /* TODO: sanity check (err->written >= 0) */
620 PyErr_Restore(t, v, tb);
621 return &err->written;
622}
623
624static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000625_buffered_raw_tell(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000626{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000627 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000628 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000629 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
630 if (res == NULL)
631 return -1;
632 n = PyNumber_AsOff_t(res, PyExc_ValueError);
633 Py_DECREF(res);
634 if (n < 0) {
635 if (!PyErr_Occurred())
636 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000637 "Raw stream returned invalid position %" PY_PRIdOFF,
638 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000639 return -1;
640 }
641 self->abs_pos = n;
642 return n;
643}
644
645static Py_off_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000646_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000647{
648 PyObject *res, *posobj, *whenceobj;
649 Py_off_t n;
650
651 posobj = PyLong_FromOff_t(target);
652 if (posobj == NULL)
653 return -1;
654 whenceobj = PyLong_FromLong(whence);
655 if (whenceobj == NULL) {
656 Py_DECREF(posobj);
657 return -1;
658 }
659 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
660 posobj, whenceobj, NULL);
661 Py_DECREF(posobj);
662 Py_DECREF(whenceobj);
663 if (res == NULL)
664 return -1;
665 n = PyNumber_AsOff_t(res, PyExc_ValueError);
666 Py_DECREF(res);
667 if (n < 0) {
668 if (!PyErr_Occurred())
669 PyErr_Format(PyExc_IOError,
Mark Dickinson1a0aaaa2009-11-24 20:54:11 +0000670 "Raw stream returned invalid position %" PY_PRIdOFF,
671 (PY_OFF_T_COMPAT)n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000672 return -1;
673 }
674 self->abs_pos = n;
675 return n;
676}
677
678static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000679_buffered_init(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000680{
681 Py_ssize_t n;
682 if (self->buffer_size <= 0) {
683 PyErr_SetString(PyExc_ValueError,
684 "buffer size must be strictly positive");
685 return -1;
686 }
687 if (self->buffer)
688 PyMem_Free(self->buffer);
689 self->buffer = PyMem_Malloc(self->buffer_size);
690 if (self->buffer == NULL) {
691 PyErr_NoMemory();
692 return -1;
693 }
Georg Brandldfd73442009-04-05 11:47:34 +0000694#ifdef WITH_THREAD
Antoine Pitrouc881f152010-08-01 16:53:42 +0000695 if (self->lock)
696 PyThread_free_lock(self->lock);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000697 self->lock = PyThread_allocate_lock();
698 if (self->lock == NULL) {
699 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
700 return -1;
701 }
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000702 self->owner = 0;
Georg Brandldfd73442009-04-05 11:47:34 +0000703#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000704 /* Find out whether buffer_size is a power of 2 */
705 /* XXX is this optimization useful? */
706 for (n = self->buffer_size - 1; n & 1; n >>= 1)
707 ;
708 if (n == 0)
709 self->buffer_mask = self->buffer_size - 1;
710 else
711 self->buffer_mask = 0;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000712 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000713 PyErr_Clear();
714 return 0;
715}
716
Antoine Pitroud843c2d2011-02-25 21:34:39 +0000717/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
718 clears the error indicator), 0 otherwise.
719 Should only be called when PyErr_Occurred() is true.
720*/
721static int
722_trap_eintr(void)
723{
724 static PyObject *eintr_int = NULL;
725 PyObject *typ, *val, *tb;
726 PyEnvironmentErrorObject *env_err;
727
728 if (eintr_int == NULL) {
729 eintr_int = PyLong_FromLong(EINTR);
730 assert(eintr_int != NULL);
731 }
732 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
733 return 0;
734 PyErr_Fetch(&typ, &val, &tb);
735 PyErr_NormalizeException(&typ, &val, &tb);
736 env_err = (PyEnvironmentErrorObject *) val;
737 assert(env_err != NULL);
738 if (env_err->myerrno != NULL &&
739 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
740 Py_DECREF(typ);
741 Py_DECREF(val);
742 Py_XDECREF(tb);
743 return 1;
744 }
745 /* This silences any error set by PyObject_RichCompareBool() */
746 PyErr_Restore(typ, val, tb);
747 return 0;
748}
749
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000750/*
751 * Shared methods and wrappers
752 */
753
754static PyObject *
Antoine Pitroue05565e2011-08-20 14:39:23 +0200755buffered_flush_and_rewind_unlocked(buffered *self)
756{
757 PyObject *res;
758
759 res = _bufferedwriter_flush_unlocked(self, 0);
760 if (res == NULL)
761 return NULL;
762 Py_DECREF(res);
763
764 if (self->readable) {
765 /* Rewind the raw stream so that its position corresponds to
766 the current logical position. */
767 Py_off_t n;
768 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
769 _bufferedreader_reset_buf(self);
770 if (n == -1)
771 return NULL;
772 }
773 Py_RETURN_NONE;
774}
775
776static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000777buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000778{
779 PyObject *res;
780
781 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000782 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000783
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000784 if (!ENTER_BUFFERED(self))
785 return NULL;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200786 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000787 LEAVE_BUFFERED(self)
788
789 return res;
790}
791
792static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000793buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000794{
795 Py_ssize_t n = 0;
796 PyObject *res = NULL;
797
798 CHECK_INITIALIZED(self)
799 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
800 return NULL;
801 }
802
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000803 if (!ENTER_BUFFERED(self))
804 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000805
806 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +0200807 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000808 if (res == NULL)
809 goto end;
810 Py_CLEAR(res);
811 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000812 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000813
814end:
815 LEAVE_BUFFERED(self)
816 return res;
817}
818
819static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000820buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000821{
822 Py_ssize_t n = -1;
823 PyObject *res;
824
825 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000826 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000827 return NULL;
828 }
829 if (n < -1) {
830 PyErr_SetString(PyExc_ValueError,
831 "read length must be positive or -1");
832 return NULL;
833 }
834
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000835 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000836
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000837 if (n == -1) {
838 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000839 if (!ENTER_BUFFERED(self))
840 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000841 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000842 }
843 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000844 res = _bufferedreader_read_fast(self, n);
Antoine Pitroue05565e2011-08-20 14:39:23 +0200845 if (res != Py_None)
846 return res;
847 Py_DECREF(res);
848 if (!ENTER_BUFFERED(self))
849 return NULL;
850 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000851 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000852
Antoine Pitroue05565e2011-08-20 14:39:23 +0200853 LEAVE_BUFFERED(self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000854 return res;
855}
856
857static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000858buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000859{
860 Py_ssize_t n, have, r;
861 PyObject *res = NULL;
862
863 CHECK_INITIALIZED(self)
864 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
865 return NULL;
866 }
867
868 if (n < 0) {
869 PyErr_SetString(PyExc_ValueError,
870 "read length must be positive");
871 return NULL;
872 }
873 if (n == 0)
874 return PyBytes_FromStringAndSize(NULL, 0);
875
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000876 if (!ENTER_BUFFERED(self))
877 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000878
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000879 /* Return up to n bytes. If at least one byte is buffered, we
880 only return buffered bytes. Otherwise, we do one raw read. */
881
882 /* XXX: this mimicks the io.py implementation but is probably wrong.
883 If we need to read from the raw stream, then we could actually read
884 all `n` bytes asked by the caller (and possibly more, so as to fill
885 our buffer for the next reads). */
886
887 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
888 if (have > 0) {
889 if (n > have)
890 n = have;
891 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
892 if (res == NULL)
893 goto end;
894 self->pos += n;
895 goto end;
896 }
897
Antoine Pitroue05565e2011-08-20 14:39:23 +0200898 if (self->writable) {
899 res = buffered_flush_and_rewind_unlocked(self);
900 if (res == NULL)
901 goto end;
902 Py_DECREF(res);
903 }
904
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000905 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000906 _bufferedreader_reset_buf(self);
907 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000908 if (r == -1)
909 goto end;
910 if (r == -2)
911 r = 0;
912 if (n > r)
913 n = r;
914 res = PyBytes_FromStringAndSize(self->buffer, n);
915 if (res == NULL)
916 goto end;
917 self->pos = n;
918
919end:
920 LEAVE_BUFFERED(self)
921 return res;
922}
923
924static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000925buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000926{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000927 CHECK_INITIALIZED(self)
928
Antoine Pitroue05565e2011-08-20 14:39:23 +0200929 /* TODO: use raw.readinto() (or a direct copy from our buffer) instead! */
930 return bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000931}
932
933static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000934_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000935{
936 PyObject *res = NULL;
937 PyObject *chunks = NULL;
938 Py_ssize_t n, written = 0;
939 const char *start, *s, *end;
940
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000941 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000942
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000943 /* First, try to find a line in the buffer. This can run unlocked because
944 the calls to the C API are simple enough that they can't trigger
945 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000946 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
947 if (limit >= 0 && n > limit)
948 n = limit;
949 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000950 s = memchr(start, '\n', n);
951 if (s != NULL) {
952 res = PyBytes_FromStringAndSize(start, s - start + 1);
953 if (res != NULL)
954 self->pos += s - start + 1;
955 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000956 }
957 if (n == limit) {
958 res = PyBytes_FromStringAndSize(start, n);
959 if (res != NULL)
960 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000961 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000962 }
963
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000964 if (!ENTER_BUFFERED(self))
965 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000966
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000967 /* Now we try to get some more from the raw stream */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000968 chunks = PyList_New(0);
969 if (chunks == NULL)
970 goto end;
971 if (n > 0) {
972 res = PyBytes_FromStringAndSize(start, n);
973 if (res == NULL)
974 goto end;
975 if (PyList_Append(chunks, res) < 0) {
976 Py_CLEAR(res);
977 goto end;
978 }
979 Py_CLEAR(res);
980 written += n;
Antoine Pitroue05565e2011-08-20 14:39:23 +0200981 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000982 if (limit >= 0)
983 limit -= n;
984 }
Antoine Pitroue05565e2011-08-20 14:39:23 +0200985 if (self->writable) {
986 PyObject *r = buffered_flush_and_rewind_unlocked(self);
987 if (r == NULL)
988 goto end;
989 Py_DECREF(r);
990 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000991
992 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000993 _bufferedreader_reset_buf(self);
994 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000995 if (n == -1)
996 goto end;
997 if (n <= 0)
998 break;
999 if (limit >= 0 && n > limit)
1000 n = limit;
1001 start = self->buffer;
1002 end = start + n;
1003 s = start;
1004 while (s < end) {
1005 if (*s++ == '\n') {
1006 res = PyBytes_FromStringAndSize(start, s - start);
1007 if (res == NULL)
1008 goto end;
1009 self->pos = s - start;
1010 goto found;
1011 }
1012 }
1013 res = PyBytes_FromStringAndSize(start, n);
1014 if (res == NULL)
1015 goto end;
1016 if (n == limit) {
1017 self->pos = n;
1018 break;
1019 }
1020 if (PyList_Append(chunks, res) < 0) {
1021 Py_CLEAR(res);
1022 goto end;
1023 }
1024 Py_CLEAR(res);
1025 written += n;
1026 if (limit >= 0)
1027 limit -= n;
1028 }
1029found:
1030 if (res != NULL && PyList_Append(chunks, res) < 0) {
1031 Py_CLEAR(res);
1032 goto end;
1033 }
1034 Py_CLEAR(res);
1035 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1036
1037end:
1038 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001039end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001040 Py_XDECREF(chunks);
1041 return res;
1042}
1043
1044static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001045buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001046{
1047 Py_ssize_t limit = -1;
1048
1049 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001050 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001051 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001052 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001053}
1054
1055
1056static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001057buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001058{
1059 Py_off_t pos;
1060
1061 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001062 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001063 if (pos == -1)
1064 return NULL;
1065 pos -= RAW_OFFSET(self);
1066 /* TODO: sanity check (pos >= 0) */
1067 return PyLong_FromOff_t(pos);
1068}
1069
1070static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001071buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001072{
1073 Py_off_t target, n;
1074 int whence = 0;
1075 PyObject *targetobj, *res = NULL;
1076
1077 CHECK_INITIALIZED(self)
1078 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1079 return NULL;
1080 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001081 if (whence < 0 || whence > 2) {
1082 PyErr_Format(PyExc_ValueError,
1083 "whence must be between 0 and 2, not %d", whence);
1084 return NULL;
1085 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001086
1087 CHECK_CLOSED(self, "seek of closed file")
1088
Antoine Pitrou1e44fec2011-10-04 12:26:20 +02001089 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1090 return NULL;
1091
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001092 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1093 if (target == -1 && PyErr_Occurred())
1094 return NULL;
1095
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001096 if (whence != 2 && self->readable) {
1097 Py_off_t current, avail;
1098 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001099 so as to return quickly if possible. Also, we needn't take the
1100 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001101 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001102 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1103 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001104 current = RAW_TELL(self);
1105 avail = READAHEAD(self);
1106 if (avail > 0) {
1107 Py_off_t offset;
1108 if (whence == 0)
1109 offset = target - (current - RAW_OFFSET(self));
1110 else
1111 offset = target;
1112 if (offset >= -self->pos && offset <= avail) {
1113 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001114 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001115 }
1116 }
1117 }
1118
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001119 if (!ENTER_BUFFERED(self))
1120 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001121
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001122 /* Fallback: invoke raw seek() method and clear buffer */
1123 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001124 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001125 if (res == NULL)
1126 goto end;
1127 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001128 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001129 }
1130
1131 /* TODO: align on block boundary and read buffer if needed? */
1132 if (whence == 1)
1133 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001134 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001135 if (n == -1)
1136 goto end;
1137 self->raw_pos = -1;
1138 res = PyLong_FromOff_t(n);
1139 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001140 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001141
1142end:
1143 LEAVE_BUFFERED(self)
1144 return res;
1145}
1146
1147static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001148buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001149{
1150 PyObject *pos = Py_None;
1151 PyObject *res = NULL;
1152
1153 CHECK_INITIALIZED(self)
1154 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1155 return NULL;
1156 }
1157
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001158 if (!ENTER_BUFFERED(self))
1159 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001160
1161 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001162 res = buffered_flush_and_rewind_unlocked(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001163 if (res == NULL)
1164 goto end;
1165 Py_CLEAR(res);
1166 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001167 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1168 if (res == NULL)
1169 goto end;
1170 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001171 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001172 PyErr_Clear();
1173
1174end:
1175 LEAVE_BUFFERED(self)
1176 return res;
1177}
1178
1179static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001180buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001181{
1182 PyObject *line;
1183 PyTypeObject *tp;
1184
1185 CHECK_INITIALIZED(self);
1186
1187 tp = Py_TYPE(self);
1188 if (tp == &PyBufferedReader_Type ||
1189 tp == &PyBufferedRandom_Type) {
1190 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001191 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001192 }
1193 else {
1194 line = PyObject_CallMethodObjArgs((PyObject *)self,
1195 _PyIO_str_readline, NULL);
1196 if (line && !PyBytes_Check(line)) {
1197 PyErr_Format(PyExc_IOError,
1198 "readline() should have returned a bytes object, "
1199 "not '%.200s'", Py_TYPE(line)->tp_name);
1200 Py_DECREF(line);
1201 return NULL;
1202 }
1203 }
1204
1205 if (line == NULL)
1206 return NULL;
1207
1208 if (PyBytes_GET_SIZE(line) == 0) {
1209 /* Reached EOF or would have blocked */
1210 Py_DECREF(line);
1211 return NULL;
1212 }
1213
1214 return line;
1215}
1216
Antoine Pitrou716c4442009-05-23 19:04:03 +00001217static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001218buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001219{
1220 PyObject *nameobj, *res;
1221
1222 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1223 if (nameobj == NULL) {
1224 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1225 PyErr_Clear();
1226 else
1227 return NULL;
1228 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1229 }
1230 else {
1231 res = PyUnicode_FromFormat("<%s name=%R>",
1232 Py_TYPE(self)->tp_name, nameobj);
1233 Py_DECREF(nameobj);
1234 }
1235 return res;
1236}
1237
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001238/*
1239 * class BufferedReader
1240 */
1241
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001242PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001243 "Create a new buffered reader using the given readable raw IO object.");
1244
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001245static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001246{
1247 self->read_end = -1;
1248}
1249
1250static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001251bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001252{
1253 char *kwlist[] = {"raw", "buffer_size", NULL};
1254 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1255 PyObject *raw;
1256
1257 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001258 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001259
1260 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1261 &raw, &buffer_size)) {
1262 return -1;
1263 }
1264
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001265 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001266 return -1;
1267
1268 Py_CLEAR(self->raw);
1269 Py_INCREF(raw);
1270 self->raw = raw;
1271 self->buffer_size = buffer_size;
1272 self->readable = 1;
1273 self->writable = 0;
1274
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001275 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001276 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001277 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001278
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001279 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1280 Py_TYPE(raw) == &PyFileIO_Type);
1281
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001282 self->ok = 1;
1283 return 0;
1284}
1285
1286static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001287_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001288{
1289 Py_buffer buf;
1290 PyObject *memobj, *res;
1291 Py_ssize_t n;
1292 /* NOTE: the buffer needn't be released as its object is NULL. */
1293 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1294 return -1;
1295 memobj = PyMemoryView_FromBuffer(&buf);
1296 if (memobj == NULL)
1297 return -1;
Antoine Pitroud843c2d2011-02-25 21:34:39 +00001298 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1299 occurs so we needn't do it ourselves.
1300 We then retry reading, ignoring the signal if no handler has
1301 raised (see issue #10956).
1302 */
1303 do {
1304 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1305 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001306 Py_DECREF(memobj);
1307 if (res == NULL)
1308 return -1;
1309 if (res == Py_None) {
1310 /* Non-blocking stream would have blocked. Special return code! */
1311 Py_DECREF(res);
1312 return -2;
1313 }
1314 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1315 Py_DECREF(res);
1316 if (n < 0 || n > len) {
1317 PyErr_Format(PyExc_IOError,
1318 "raw readinto() returned invalid length %zd "
1319 "(should have been between 0 and %zd)", n, len);
1320 return -1;
1321 }
1322 if (n > 0 && self->abs_pos != -1)
1323 self->abs_pos += n;
1324 return n;
1325}
1326
1327static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001328_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001329{
1330 Py_ssize_t start, len, n;
1331 if (VALID_READ_BUFFER(self))
1332 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1333 else
1334 start = 0;
1335 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001336 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001337 if (n <= 0)
1338 return n;
1339 self->read_end = start + n;
1340 self->raw_pos = start + n;
1341 return n;
1342}
1343
1344static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001345_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001346{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001347 Py_ssize_t current_size;
1348 PyObject *res, *data = NULL;
1349 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001350
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001351 if (chunks == NULL)
1352 return NULL;
1353
1354 /* First copy what we have in the current buffer. */
1355 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1356 if (current_size) {
1357 data = PyBytes_FromStringAndSize(
1358 self->buffer + self->pos, current_size);
1359 if (data == NULL) {
1360 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001361 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001362 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001363 self->pos += current_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001364 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001365 /* We're going past the buffer's bounds, flush it */
1366 if (self->writable) {
Antoine Pitroue05565e2011-08-20 14:39:23 +02001367 res = buffered_flush_and_rewind_unlocked(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001368 if (res == NULL) {
1369 Py_DECREF(chunks);
1370 return NULL;
1371 }
1372 Py_CLEAR(res);
1373 }
Antoine Pitroue05565e2011-08-20 14:39:23 +02001374 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001375 while (1) {
1376 if (data) {
1377 if (PyList_Append(chunks, data) < 0) {
1378 Py_DECREF(data);
1379 Py_DECREF(chunks);
1380 return NULL;
1381 }
1382 Py_DECREF(data);
1383 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001384
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001385 /* Read until EOF or until read() would block. */
1386 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1387 if (data == NULL) {
1388 Py_DECREF(chunks);
1389 return NULL;
1390 }
1391 if (data != Py_None && !PyBytes_Check(data)) {
1392 Py_DECREF(data);
1393 Py_DECREF(chunks);
1394 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1395 return NULL;
1396 }
1397 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1398 if (current_size == 0) {
1399 Py_DECREF(chunks);
1400 return data;
1401 }
1402 else {
1403 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1404 Py_DECREF(data);
1405 Py_DECREF(chunks);
1406 return res;
1407 }
1408 }
1409 current_size += PyBytes_GET_SIZE(data);
1410 if (self->abs_pos != -1)
1411 self->abs_pos += PyBytes_GET_SIZE(data);
1412 }
1413}
1414
1415/* Read n bytes from the buffer if it can, otherwise return None.
1416 This function is simple enough that it can run unlocked. */
1417static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001418_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001419{
1420 Py_ssize_t current_size;
1421
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001422 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1423 if (n <= current_size) {
1424 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001425 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1426 if (res != NULL)
1427 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001428 return res;
1429 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001430 Py_RETURN_NONE;
1431}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001432
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001433/* Generic read function: read from the stream until enough bytes are read,
1434 * or until an EOF occurs or until read() would block.
1435 */
1436static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001437_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001438{
1439 PyObject *res = NULL;
1440 Py_ssize_t current_size, remaining, written;
1441 char *out;
1442
1443 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1444 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001445 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001446
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001447 res = PyBytes_FromStringAndSize(NULL, n);
1448 if (res == NULL)
1449 goto error;
1450 out = PyBytes_AS_STRING(res);
1451 remaining = n;
1452 written = 0;
1453 if (current_size > 0) {
1454 memcpy(out, self->buffer + self->pos, current_size);
1455 remaining -= current_size;
1456 written += current_size;
Antoine Pitroue05565e2011-08-20 14:39:23 +02001457 self->pos += current_size;
1458 }
1459 /* Flush the write buffer if necessary */
1460 if (self->writable) {
1461 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1462 if (r == NULL)
1463 goto error;
1464 Py_DECREF(r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001465 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001466 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001467 while (remaining > 0) {
1468 /* We want to read a whole block at the end into buffer.
1469 If we had readv() we could do this in one pass. */
1470 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1471 if (r == 0)
1472 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001473 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001474 if (r == -1)
1475 goto error;
1476 if (r == 0 || r == -2) {
1477 /* EOF occurred or read() would block. */
1478 if (r == 0 || written > 0) {
1479 if (_PyBytes_Resize(&res, written))
1480 goto error;
1481 return res;
1482 }
1483 Py_DECREF(res);
1484 Py_INCREF(Py_None);
1485 return Py_None;
1486 }
1487 remaining -= r;
1488 written += r;
1489 }
1490 assert(remaining <= self->buffer_size);
1491 self->pos = 0;
1492 self->raw_pos = 0;
1493 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001494 /* NOTE: when the read is satisfied, we avoid issuing any additional
1495 reads, which could block indefinitely (e.g. on a socket).
1496 See issue #9550. */
1497 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001498 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001499 if (r == -1)
1500 goto error;
1501 if (r == 0 || r == -2) {
1502 /* EOF occurred or read() would block. */
1503 if (r == 0 || written > 0) {
1504 if (_PyBytes_Resize(&res, written))
1505 goto error;
1506 return res;
1507 }
1508 Py_DECREF(res);
1509 Py_INCREF(Py_None);
1510 return Py_None;
1511 }
1512 if (remaining > r) {
1513 memcpy(out + written, self->buffer + self->pos, r);
1514 written += r;
1515 self->pos += r;
1516 remaining -= r;
1517 }
1518 else if (remaining > 0) {
1519 memcpy(out + written, self->buffer + self->pos, remaining);
1520 written += remaining;
1521 self->pos += remaining;
1522 remaining = 0;
1523 }
1524 if (remaining == 0)
1525 break;
1526 }
1527
1528 return res;
1529
1530error:
1531 Py_XDECREF(res);
1532 return NULL;
1533}
1534
1535static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001536_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001537{
1538 Py_ssize_t have, r;
1539
1540 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1541 /* Constraints:
1542 1. we don't want to advance the file position.
1543 2. we don't want to lose block alignment, so we can't shift the buffer
1544 to make some place.
1545 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1546 */
1547 if (have > 0) {
1548 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1549 }
1550
1551 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001552 _bufferedreader_reset_buf(self);
1553 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001554 if (r == -1)
1555 return NULL;
1556 if (r == -2)
1557 r = 0;
1558 self->pos = 0;
1559 return PyBytes_FromStringAndSize(self->buffer, r);
1560}
1561
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001562static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001563 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001564 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1565 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1566 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1567 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1568 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1569 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1570 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1571 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001572 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001573 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001574
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001575 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1576 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1577 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1578 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1579 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1580 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1581 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001582 {NULL, NULL}
1583};
1584
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001585static PyMemberDef bufferedreader_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001586 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001587 {NULL}
1588};
1589
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001590static PyGetSetDef bufferedreader_getset[] = {
1591 {"closed", (getter)buffered_closed_get, NULL, NULL},
1592 {"name", (getter)buffered_name_get, NULL, NULL},
1593 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001594 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001595};
1596
1597
1598PyTypeObject PyBufferedReader_Type = {
1599 PyVarObject_HEAD_INIT(NULL, 0)
1600 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001601 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001602 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001603 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001604 0, /*tp_print*/
1605 0, /*tp_getattr*/
1606 0, /*tp_setattr*/
1607 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001608 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001609 0, /*tp_as_number*/
1610 0, /*tp_as_sequence*/
1611 0, /*tp_as_mapping*/
1612 0, /*tp_hash */
1613 0, /*tp_call*/
1614 0, /*tp_str*/
1615 0, /*tp_getattro*/
1616 0, /*tp_setattro*/
1617 0, /*tp_as_buffer*/
1618 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1619 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001620 bufferedreader_doc, /* tp_doc */
1621 (traverseproc)buffered_traverse, /* tp_traverse */
1622 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001623 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001624 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001625 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001626 (iternextfunc)buffered_iternext, /* tp_iternext */
1627 bufferedreader_methods, /* tp_methods */
1628 bufferedreader_members, /* tp_members */
1629 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001630 0, /* tp_base */
1631 0, /* tp_dict */
1632 0, /* tp_descr_get */
1633 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001634 offsetof(buffered, dict), /* tp_dictoffset */
1635 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001636 0, /* tp_alloc */
1637 PyType_GenericNew, /* tp_new */
1638};
1639
1640
Benjamin Peterson59406a92009-03-26 17:10:29 +00001641
1642static int
1643complain_about_max_buffer_size(void)
1644{
1645 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1646 "max_buffer_size is deprecated", 1) < 0)
1647 return 0;
1648 return 1;
1649}
1650
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001651/*
1652 * class BufferedWriter
1653 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001654PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001655 "A buffer for a writeable sequential RawIO object.\n"
1656 "\n"
1657 "The constructor creates a BufferedWriter for the given writeable raw\n"
1658 "stream. If the buffer_size is not given, it defaults to\n"
1659 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1660 );
1661
1662static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001663_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001664{
1665 self->write_pos = 0;
1666 self->write_end = -1;
1667}
1668
1669static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001670bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001671{
1672 /* TODO: properly deprecate max_buffer_size */
1673 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1674 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001675 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001676 PyObject *raw;
1677
1678 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001679 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001680
1681 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1682 &raw, &buffer_size, &max_buffer_size)) {
1683 return -1;
1684 }
1685
Benjamin Peterson59406a92009-03-26 17:10:29 +00001686 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1687 return -1;
1688
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001689 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001690 return -1;
1691
1692 Py_CLEAR(self->raw);
1693 Py_INCREF(raw);
1694 self->raw = raw;
1695 self->readable = 0;
1696 self->writable = 1;
1697
1698 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001699 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001700 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001701 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001702 self->pos = 0;
1703
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001704 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1705 Py_TYPE(raw) == &PyFileIO_Type);
1706
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001707 self->ok = 1;
1708 return 0;
1709}
1710
1711static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001712_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001713{
1714 Py_buffer buf;
1715 PyObject *memobj, *res;
1716 Py_ssize_t n;
1717 /* NOTE: the buffer needn't be released as its object is NULL. */
1718 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1719 return -1;
1720 memobj = PyMemoryView_FromBuffer(&buf);
1721 if (memobj == NULL)
1722 return -1;
Antoine Pitroud843c2d2011-02-25 21:34:39 +00001723 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1724 occurs so we needn't do it ourselves.
1725 We then retry writing, ignoring the signal if no handler has
1726 raised (see issue #10956).
1727 */
1728 do {
1729 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1730 } while (res == NULL && _trap_eintr());
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001731 Py_DECREF(memobj);
1732 if (res == NULL)
1733 return -1;
1734 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1735 Py_DECREF(res);
1736 if (n < 0 || n > len) {
1737 PyErr_Format(PyExc_IOError,
1738 "raw write() returned invalid length %zd "
1739 "(should have been between 0 and %zd)", n, len);
1740 return -1;
1741 }
1742 if (n > 0 && self->abs_pos != -1)
1743 self->abs_pos += n;
1744 return n;
1745}
1746
1747/* `restore_pos` is 1 if we need to restore the raw stream position at
1748 the end, 0 otherwise. */
1749static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001750_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001751{
1752 Py_ssize_t written = 0;
1753 Py_off_t n, rewind;
1754
1755 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1756 goto end;
1757 /* First, rewind */
1758 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1759 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001760 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001761 if (n < 0) {
1762 goto error;
1763 }
1764 self->raw_pos -= rewind;
1765 }
1766 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001767 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001768 self->buffer + self->write_pos,
1769 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1770 Py_off_t, Py_ssize_t));
1771 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001772 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001773 if (w == NULL)
1774 goto error;
1775 self->write_pos += *w;
1776 self->raw_pos = self->write_pos;
1777 written += *w;
1778 *w = written;
1779 /* Already re-raised */
1780 goto error;
1781 }
1782 self->write_pos += n;
1783 self->raw_pos = self->write_pos;
1784 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001785 /* Partial writes can return successfully when interrupted by a
1786 signal (see write(2)). We must run signal handlers before
1787 blocking another time, possibly indefinitely. */
1788 if (PyErr_CheckSignals() < 0)
1789 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001790 }
1791
1792 if (restore_pos) {
1793 Py_off_t forward = rewind - written;
1794 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001795 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001796 if (n < 0) {
1797 goto error;
1798 }
1799 self->raw_pos += forward;
1800 }
1801 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001802 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001803
1804end:
1805 Py_RETURN_NONE;
1806
1807error:
1808 return NULL;
1809}
1810
1811static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001812bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001813{
1814 PyObject *res = NULL;
1815 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001816 Py_ssize_t written, avail, remaining;
1817 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001818
1819 CHECK_INITIALIZED(self)
1820 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1821 return NULL;
1822 }
1823
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001824 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001825 PyErr_SetString(PyExc_ValueError, "write to closed file");
1826 PyBuffer_Release(&buf);
1827 return NULL;
1828 }
1829
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001830 if (!ENTER_BUFFERED(self)) {
1831 PyBuffer_Release(&buf);
1832 return NULL;
1833 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001834
1835 /* Fast path: the data to write can be fully buffered. */
1836 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1837 self->pos = 0;
1838 self->raw_pos = 0;
1839 }
1840 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1841 if (buf.len <= avail) {
1842 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrou7c404892011-05-13 00:13:33 +02001843 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001844 self->write_pos = self->pos;
1845 }
1846 ADJUST_POSITION(self, self->pos + buf.len);
1847 if (self->pos > self->write_end)
1848 self->write_end = self->pos;
1849 written = buf.len;
1850 goto end;
1851 }
1852
1853 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001854 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001855 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001856 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001857 if (w == NULL)
1858 goto error;
1859 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001860 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001861 /* Make some place by shifting the buffer. */
1862 assert(VALID_WRITE_BUFFER(self));
1863 memmove(self->buffer, self->buffer + self->write_pos,
1864 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1865 Py_off_t, Py_ssize_t));
1866 self->write_end -= self->write_pos;
1867 self->raw_pos -= self->write_pos;
1868 self->pos -= self->write_pos;
1869 self->write_pos = 0;
1870 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1871 Py_off_t, Py_ssize_t);
1872 if (buf.len <= avail) {
1873 /* Everything can be buffered */
1874 PyErr_Clear();
1875 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1876 self->write_end += buf.len;
1877 written = buf.len;
1878 goto end;
1879 }
1880 /* Buffer as much as possible. */
1881 memcpy(self->buffer + self->write_end, buf.buf, avail);
1882 self->write_end += avail;
1883 /* Already re-raised */
1884 *w = avail;
1885 goto error;
1886 }
1887 Py_CLEAR(res);
1888
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001889 /* Adjust the raw stream position if it is away from the logical stream
1890 position. This happens if the read buffer has been filled but not
1891 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1892 the raw stream by itself).
1893 Fixes issue #6629.
1894 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001895 offset = RAW_OFFSET(self);
1896 if (offset != 0) {
1897 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001898 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001899 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001900 }
1901
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001902 /* Then write buf itself. At this point the buffer has been emptied. */
1903 remaining = buf.len;
1904 written = 0;
1905 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001906 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001907 self, (char *) buf.buf + written, buf.len - written);
1908 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001909 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001910 if (w == NULL)
1911 goto error;
1912 written += *w;
1913 remaining -= *w;
1914 if (remaining > self->buffer_size) {
1915 /* Can't buffer everything, still buffer as much as possible */
1916 memcpy(self->buffer,
1917 (char *) buf.buf + written, self->buffer_size);
1918 self->raw_pos = 0;
1919 ADJUST_POSITION(self, self->buffer_size);
1920 self->write_end = self->buffer_size;
1921 *w = written + self->buffer_size;
1922 /* Already re-raised */
1923 goto error;
1924 }
1925 PyErr_Clear();
1926 break;
1927 }
1928 written += n;
1929 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001930 /* Partial writes can return successfully when interrupted by a
1931 signal (see write(2)). We must run signal handlers before
1932 blocking another time, possibly indefinitely. */
1933 if (PyErr_CheckSignals() < 0)
1934 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001935 }
1936 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001937 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001938 if (remaining > 0) {
1939 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1940 written += remaining;
1941 }
1942 self->write_pos = 0;
1943 /* TODO: sanity check (remaining >= 0) */
1944 self->write_end = remaining;
1945 ADJUST_POSITION(self, remaining);
1946 self->raw_pos = 0;
1947
1948end:
1949 res = PyLong_FromSsize_t(written);
1950
1951error:
1952 LEAVE_BUFFERED(self)
1953 PyBuffer_Release(&buf);
1954 return res;
1955}
1956
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001957static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001958 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001959 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1960 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1961 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1962 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1963 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1964 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1965 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001966 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001967 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001968
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001969 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1970 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1971 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1972 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1973 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001974 {NULL, NULL}
1975};
1976
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001977static PyMemberDef bufferedwriter_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00001978 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001979 {NULL}
1980};
1981
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001982static PyGetSetDef bufferedwriter_getset[] = {
1983 {"closed", (getter)buffered_closed_get, NULL, NULL},
1984 {"name", (getter)buffered_name_get, NULL, NULL},
1985 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001986 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001987};
1988
1989
1990PyTypeObject PyBufferedWriter_Type = {
1991 PyVarObject_HEAD_INIT(NULL, 0)
1992 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001993 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001994 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001995 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001996 0, /*tp_print*/
1997 0, /*tp_getattr*/
1998 0, /*tp_setattr*/
1999 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002000 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002001 0, /*tp_as_number*/
2002 0, /*tp_as_sequence*/
2003 0, /*tp_as_mapping*/
2004 0, /*tp_hash */
2005 0, /*tp_call*/
2006 0, /*tp_str*/
2007 0, /*tp_getattro*/
2008 0, /*tp_setattro*/
2009 0, /*tp_as_buffer*/
2010 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2011 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002012 bufferedwriter_doc, /* tp_doc */
2013 (traverseproc)buffered_traverse, /* tp_traverse */
2014 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002015 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002016 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002017 0, /* tp_iter */
2018 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002019 bufferedwriter_methods, /* tp_methods */
2020 bufferedwriter_members, /* tp_members */
2021 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002022 0, /* tp_base */
2023 0, /* tp_dict */
2024 0, /* tp_descr_get */
2025 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002026 offsetof(buffered, dict), /* tp_dictoffset */
2027 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002028 0, /* tp_alloc */
2029 PyType_GenericNew, /* tp_new */
2030};
2031
2032
2033
2034/*
2035 * BufferedRWPair
2036 */
2037
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002038PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002039 "A buffered reader and writer object together.\n"
2040 "\n"
2041 "A buffered reader object and buffered writer object put together to\n"
2042 "form a sequential IO object that can read and write. This is typically\n"
2043 "used with a socket or two-way pipe.\n"
2044 "\n"
2045 "reader and writer are RawIOBase objects that are readable and\n"
2046 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00002047 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002048 );
2049
2050/* XXX The usefulness of this (compared to having two separate IO objects) is
2051 * questionable.
2052 */
2053
2054typedef struct {
2055 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002056 buffered *reader;
2057 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002058 PyObject *dict;
2059 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002060} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002061
2062static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002063bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002064{
2065 PyObject *reader, *writer;
2066 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002067 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002068
2069 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2070 &buffer_size, &max_buffer_size)) {
2071 return -1;
2072 }
2073
Benjamin Peterson59406a92009-03-26 17:10:29 +00002074 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2075 return -1;
2076
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002077 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002078 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002079 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002080 return -1;
2081
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002082 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002083 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002084 if (self->reader == NULL)
2085 return -1;
2086
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002087 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002088 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002089 if (self->writer == NULL) {
2090 Py_CLEAR(self->reader);
2091 return -1;
2092 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002093
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002094 return 0;
2095}
2096
2097static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002098bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002099{
2100 Py_VISIT(self->dict);
2101 return 0;
2102}
2103
2104static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002105bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002106{
2107 Py_CLEAR(self->reader);
2108 Py_CLEAR(self->writer);
2109 Py_CLEAR(self->dict);
2110 return 0;
2111}
2112
2113static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002114bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002115{
2116 _PyObject_GC_UNTRACK(self);
2117 Py_CLEAR(self->reader);
2118 Py_CLEAR(self->writer);
2119 Py_CLEAR(self->dict);
2120 Py_TYPE(self)->tp_free((PyObject *) self);
2121}
2122
2123static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002124_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002125{
2126 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2127 PyObject *ret;
2128
2129 if (func == NULL) {
2130 PyErr_SetString(PyExc_AttributeError, name);
2131 return NULL;
2132 }
2133
2134 ret = PyObject_CallObject(func, args);
2135 Py_DECREF(func);
2136 return ret;
2137}
2138
2139static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002140bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002141{
2142 return _forward_call(self->reader, "read", args);
2143}
2144
2145static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002146bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002147{
2148 return _forward_call(self->reader, "peek", args);
2149}
2150
2151static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002152bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002153{
2154 return _forward_call(self->reader, "read1", args);
2155}
2156
2157static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002158bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002159{
2160 return _forward_call(self->reader, "readinto", args);
2161}
2162
2163static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002164bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002165{
2166 return _forward_call(self->writer, "write", args);
2167}
2168
2169static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002170bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002171{
2172 return _forward_call(self->writer, "flush", args);
2173}
2174
2175static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002176bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002177{
2178 return _forward_call(self->reader, "readable", args);
2179}
2180
2181static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002182bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002183{
2184 return _forward_call(self->writer, "writable", args);
2185}
2186
2187static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002188bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002189{
2190 PyObject *ret = _forward_call(self->writer, "close", args);
2191 if (ret == NULL)
2192 return NULL;
2193 Py_DECREF(ret);
2194
2195 return _forward_call(self->reader, "close", args);
2196}
2197
2198static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002199bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002200{
2201 PyObject *ret = _forward_call(self->writer, "isatty", args);
2202
2203 if (ret != Py_False) {
2204 /* either True or exception */
2205 return ret;
2206 }
2207 Py_DECREF(ret);
2208
2209 return _forward_call(self->reader, "isatty", args);
2210}
2211
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002212static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002213bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002214{
Charles-François Natali42c28cd2011-10-05 19:53:43 +02002215 if (self->writer == NULL) {
2216 PyErr_SetString(PyExc_RuntimeError,
2217 "the BufferedRWPair object is being garbage-collected");
2218 return NULL;
2219 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002220 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2221}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002222
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002223static PyMethodDef bufferedrwpair_methods[] = {
2224 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2225 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2226 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2227 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002228
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002229 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2230 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002231
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002232 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2233 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002234
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002235 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2236 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002237
Antoine Pitrou243757e2010-11-05 21:15:39 +00002238 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2239
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002240 {NULL, NULL}
2241};
2242
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002243static PyGetSetDef bufferedrwpair_getset[] = {
2244 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002245 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002246};
2247
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002248PyTypeObject PyBufferedRWPair_Type = {
2249 PyVarObject_HEAD_INIT(NULL, 0)
2250 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002251 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002252 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002253 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002254 0, /*tp_print*/
2255 0, /*tp_getattr*/
2256 0, /*tp_setattr*/
2257 0, /*tp_compare */
2258 0, /*tp_repr*/
2259 0, /*tp_as_number*/
2260 0, /*tp_as_sequence*/
2261 0, /*tp_as_mapping*/
2262 0, /*tp_hash */
2263 0, /*tp_call*/
2264 0, /*tp_str*/
2265 0, /*tp_getattro*/
2266 0, /*tp_setattro*/
2267 0, /*tp_as_buffer*/
2268 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2269 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002270 bufferedrwpair_doc, /* tp_doc */
2271 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2272 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002273 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002274 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002275 0, /* tp_iter */
2276 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002277 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002278 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002279 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002280 0, /* tp_base */
2281 0, /* tp_dict */
2282 0, /* tp_descr_get */
2283 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002284 offsetof(rwpair, dict), /* tp_dictoffset */
2285 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002286 0, /* tp_alloc */
2287 PyType_GenericNew, /* tp_new */
2288};
2289
2290
2291
2292/*
2293 * BufferedRandom
2294 */
2295
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002296PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002297 "A buffered interface to random access streams.\n"
2298 "\n"
2299 "The constructor creates a reader and writer for a seekable stream,\n"
2300 "raw, given in the first argument. If the buffer_size is omitted it\n"
2301 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2302 );
2303
2304static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002305bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002306{
2307 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2308 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002309 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002310 PyObject *raw;
2311
2312 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002313 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002314
2315 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2316 &raw, &buffer_size, &max_buffer_size)) {
2317 return -1;
2318 }
2319
Benjamin Peterson59406a92009-03-26 17:10:29 +00002320 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2321 return -1;
2322
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002323 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002324 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002325 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002326 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002327 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002328 return -1;
2329
2330 Py_CLEAR(self->raw);
2331 Py_INCREF(raw);
2332 self->raw = raw;
2333 self->buffer_size = buffer_size;
2334 self->readable = 1;
2335 self->writable = 1;
2336
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002337 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002338 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002339 _bufferedreader_reset_buf(self);
2340 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002341 self->pos = 0;
2342
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002343 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2344 Py_TYPE(raw) == &PyFileIO_Type);
2345
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002346 self->ok = 1;
2347 return 0;
2348}
2349
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002350static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002351 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002352 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2353 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2354 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2355 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2356 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2357 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2358 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002359 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002360 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002361
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002362 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002363
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002364 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2365 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2366 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2367 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2368 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2369 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2370 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2371 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2372 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002373 {NULL, NULL}
2374};
2375
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002376static PyMemberDef bufferedrandom_members[] = {
Antoine Pitrou7f8f4182010-12-21 21:20:59 +00002377 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002378 {NULL}
2379};
2380
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002381static PyGetSetDef bufferedrandom_getset[] = {
2382 {"closed", (getter)buffered_closed_get, NULL, NULL},
2383 {"name", (getter)buffered_name_get, NULL, NULL},
2384 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002385 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002386};
2387
2388
2389PyTypeObject PyBufferedRandom_Type = {
2390 PyVarObject_HEAD_INIT(NULL, 0)
2391 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002392 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002393 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002394 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002395 0, /*tp_print*/
2396 0, /*tp_getattr*/
2397 0, /*tp_setattr*/
2398 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002399 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002400 0, /*tp_as_number*/
2401 0, /*tp_as_sequence*/
2402 0, /*tp_as_mapping*/
2403 0, /*tp_hash */
2404 0, /*tp_call*/
2405 0, /*tp_str*/
2406 0, /*tp_getattro*/
2407 0, /*tp_setattro*/
2408 0, /*tp_as_buffer*/
2409 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2410 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002411 bufferedrandom_doc, /* tp_doc */
2412 (traverseproc)buffered_traverse, /* tp_traverse */
2413 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002414 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002415 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002416 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002417 (iternextfunc)buffered_iternext, /* tp_iternext */
2418 bufferedrandom_methods, /* tp_methods */
2419 bufferedrandom_members, /* tp_members */
2420 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002421 0, /* tp_base */
2422 0, /*tp_dict*/
2423 0, /* tp_descr_get */
2424 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002425 offsetof(buffered, dict), /*tp_dictoffset*/
2426 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002427 0, /* tp_alloc */
2428 PyType_GenericNew, /* tp_new */
2429};