blob: f7e34a8daccf7f05873ce70743c5140d5d1fafba [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
717/*
718 * Shared methods and wrappers
719 */
720
721static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000722buffered_flush(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000723{
724 PyObject *res;
725
726 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000727 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000728
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000729 if (!ENTER_BUFFERED(self))
730 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000731 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000732 if (res != NULL && self->readable) {
733 /* Rewind the raw stream so that its position corresponds to
734 the current logical position. */
735 Py_off_t n;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000736 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000737 if (n == -1)
738 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000739 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000740 }
741 LEAVE_BUFFERED(self)
742
743 return res;
744}
745
746static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000747buffered_peek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000748{
749 Py_ssize_t n = 0;
750 PyObject *res = NULL;
751
752 CHECK_INITIALIZED(self)
753 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
754 return NULL;
755 }
756
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000757 if (!ENTER_BUFFERED(self))
758 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000759
760 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000761 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000762 if (res == NULL)
763 goto end;
764 Py_CLEAR(res);
765 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000766 res = _bufferedreader_peek_unlocked(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000767
768end:
769 LEAVE_BUFFERED(self)
770 return res;
771}
772
773static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000774buffered_read(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000775{
776 Py_ssize_t n = -1;
777 PyObject *res;
778
779 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +0000780 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000781 return NULL;
782 }
783 if (n < -1) {
784 PyErr_SetString(PyExc_ValueError,
785 "read length must be positive or -1");
786 return NULL;
787 }
788
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000789 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000790
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000791 if (n == -1) {
792 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000793 if (!ENTER_BUFFERED(self))
794 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000795 res = _bufferedreader_read_all(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000796 LEAVE_BUFFERED(self)
797 }
798 else {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000799 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000800 if (res == Py_None) {
801 Py_DECREF(res);
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000802 if (!ENTER_BUFFERED(self))
803 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000804 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000805 LEAVE_BUFFERED(self)
806 }
807 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000808
809 return res;
810}
811
812static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000813buffered_read1(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000814{
815 Py_ssize_t n, have, r;
816 PyObject *res = NULL;
817
818 CHECK_INITIALIZED(self)
819 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
820 return NULL;
821 }
822
823 if (n < 0) {
824 PyErr_SetString(PyExc_ValueError,
825 "read length must be positive");
826 return NULL;
827 }
828 if (n == 0)
829 return PyBytes_FromStringAndSize(NULL, 0);
830
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000831 if (!ENTER_BUFFERED(self))
832 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000833
834 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000835 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000836 if (res == NULL)
837 goto end;
838 Py_CLEAR(res);
839 }
840
841 /* Return up to n bytes. If at least one byte is buffered, we
842 only return buffered bytes. Otherwise, we do one raw read. */
843
844 /* XXX: this mimicks the io.py implementation but is probably wrong.
845 If we need to read from the raw stream, then we could actually read
846 all `n` bytes asked by the caller (and possibly more, so as to fill
847 our buffer for the next reads). */
848
849 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
850 if (have > 0) {
851 if (n > have)
852 n = have;
853 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
854 if (res == NULL)
855 goto end;
856 self->pos += n;
857 goto end;
858 }
859
860 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000861 _bufferedreader_reset_buf(self);
862 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000863 if (r == -1)
864 goto end;
865 if (r == -2)
866 r = 0;
867 if (n > r)
868 n = r;
869 res = PyBytes_FromStringAndSize(self->buffer, n);
870 if (res == NULL)
871 goto end;
872 self->pos = n;
873
874end:
875 LEAVE_BUFFERED(self)
876 return res;
877}
878
879static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000880buffered_readinto(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000881{
882 PyObject *res = NULL;
883
884 CHECK_INITIALIZED(self)
885
886 /* TODO: use raw.readinto() instead! */
887 if (self->writable) {
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000888 if (!ENTER_BUFFERED(self))
889 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000890 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000891 LEAVE_BUFFERED(self)
892 if (res == NULL)
893 goto end;
894 Py_DECREF(res);
895 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000896 res = bufferediobase_readinto((PyObject *)self, args);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000897
898end:
899 return res;
900}
901
902static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000903_buffered_readline(buffered *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000904{
905 PyObject *res = NULL;
906 PyObject *chunks = NULL;
907 Py_ssize_t n, written = 0;
908 const char *start, *s, *end;
909
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000910 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000911
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000912 /* First, try to find a line in the buffer. This can run unlocked because
913 the calls to the C API are simple enough that they can't trigger
914 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000915 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
916 if (limit >= 0 && n > limit)
917 n = limit;
918 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000919 s = memchr(start, '\n', n);
920 if (s != NULL) {
921 res = PyBytes_FromStringAndSize(start, s - start + 1);
922 if (res != NULL)
923 self->pos += s - start + 1;
924 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000925 }
926 if (n == limit) {
927 res = PyBytes_FromStringAndSize(start, n);
928 if (res != NULL)
929 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000930 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000931 }
932
Antoine Pitrouf3b68b32010-12-03 18:41:39 +0000933 if (!ENTER_BUFFERED(self))
934 goto end_unlocked;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000935
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000936 /* Now we try to get some more from the raw stream */
937 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000938 res = _bufferedwriter_flush_unlocked(self, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000939 if (res == NULL)
940 goto end;
941 Py_CLEAR(res);
942 }
943 chunks = PyList_New(0);
944 if (chunks == NULL)
945 goto end;
946 if (n > 0) {
947 res = PyBytes_FromStringAndSize(start, n);
948 if (res == NULL)
949 goto end;
950 if (PyList_Append(chunks, res) < 0) {
951 Py_CLEAR(res);
952 goto end;
953 }
954 Py_CLEAR(res);
955 written += n;
956 if (limit >= 0)
957 limit -= n;
958 }
959
960 for (;;) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000961 _bufferedreader_reset_buf(self);
962 n = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000963 if (n == -1)
964 goto end;
965 if (n <= 0)
966 break;
967 if (limit >= 0 && n > limit)
968 n = limit;
969 start = self->buffer;
970 end = start + n;
971 s = start;
972 while (s < end) {
973 if (*s++ == '\n') {
974 res = PyBytes_FromStringAndSize(start, s - start);
975 if (res == NULL)
976 goto end;
977 self->pos = s - start;
978 goto found;
979 }
980 }
981 res = PyBytes_FromStringAndSize(start, n);
982 if (res == NULL)
983 goto end;
984 if (n == limit) {
985 self->pos = n;
986 break;
987 }
988 if (PyList_Append(chunks, res) < 0) {
989 Py_CLEAR(res);
990 goto end;
991 }
992 Py_CLEAR(res);
993 written += n;
994 if (limit >= 0)
995 limit -= n;
996 }
997found:
998 if (res != NULL && PyList_Append(chunks, res) < 0) {
999 Py_CLEAR(res);
1000 goto end;
1001 }
1002 Py_CLEAR(res);
1003 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1004
1005end:
1006 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001007end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001008 Py_XDECREF(chunks);
1009 return res;
1010}
1011
1012static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001013buffered_readline(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001014{
1015 Py_ssize_t limit = -1;
1016
1017 CHECK_INITIALIZED(self)
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001018 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001019 return NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001020 return _buffered_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001021}
1022
1023
1024static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001025buffered_tell(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001026{
1027 Py_off_t pos;
1028
1029 CHECK_INITIALIZED(self)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001030 pos = _buffered_raw_tell(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001031 if (pos == -1)
1032 return NULL;
1033 pos -= RAW_OFFSET(self);
1034 /* TODO: sanity check (pos >= 0) */
1035 return PyLong_FromOff_t(pos);
1036}
1037
1038static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001039buffered_seek(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001040{
1041 Py_off_t target, n;
1042 int whence = 0;
1043 PyObject *targetobj, *res = NULL;
1044
1045 CHECK_INITIALIZED(self)
1046 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1047 return NULL;
1048 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001049 if (whence < 0 || whence > 2) {
1050 PyErr_Format(PyExc_ValueError,
1051 "whence must be between 0 and 2, not %d", whence);
1052 return NULL;
1053 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001054
1055 CHECK_CLOSED(self, "seek of closed file")
1056
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001057 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1058 if (target == -1 && PyErr_Occurred())
1059 return NULL;
1060
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001061 if (whence != 2 && self->readable) {
1062 Py_off_t current, avail;
1063 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001064 so as to return quickly if possible. Also, we needn't take the
1065 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001066 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001067 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1068 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001069 current = RAW_TELL(self);
1070 avail = READAHEAD(self);
1071 if (avail > 0) {
1072 Py_off_t offset;
1073 if (whence == 0)
1074 offset = target - (current - RAW_OFFSET(self));
1075 else
1076 offset = target;
1077 if (offset >= -self->pos && offset <= avail) {
1078 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001079 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001080 }
1081 }
1082 }
1083
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001084 if (!ENTER_BUFFERED(self))
1085 return NULL;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001086
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001087 /* Fallback: invoke raw seek() method and clear buffer */
1088 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001089 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001090 if (res == NULL)
1091 goto end;
1092 Py_CLEAR(res);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001093 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001094 }
1095
1096 /* TODO: align on block boundary and read buffer if needed? */
1097 if (whence == 1)
1098 target -= RAW_OFFSET(self);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001099 n = _buffered_raw_seek(self, target, whence);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001100 if (n == -1)
1101 goto end;
1102 self->raw_pos = -1;
1103 res = PyLong_FromOff_t(n);
1104 if (res != NULL && self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001105 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001106
1107end:
1108 LEAVE_BUFFERED(self)
1109 return res;
1110}
1111
1112static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001113buffered_truncate(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001114{
1115 PyObject *pos = Py_None;
1116 PyObject *res = NULL;
1117
1118 CHECK_INITIALIZED(self)
1119 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1120 return NULL;
1121 }
1122
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001123 if (!ENTER_BUFFERED(self))
1124 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001125
1126 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001127 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001128 if (res == NULL)
1129 goto end;
1130 Py_CLEAR(res);
1131 }
1132 if (self->readable) {
1133 if (pos == Py_None) {
1134 /* Rewind the raw stream so that its position corresponds to
1135 the current logical position. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001136 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001137 goto end;
1138 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001139 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001140 }
1141 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1142 if (res == NULL)
1143 goto end;
1144 /* Reset cached position */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001145 if (_buffered_raw_tell(self) == -1)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001146 PyErr_Clear();
1147
1148end:
1149 LEAVE_BUFFERED(self)
1150 return res;
1151}
1152
1153static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001154buffered_iternext(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001155{
1156 PyObject *line;
1157 PyTypeObject *tp;
1158
1159 CHECK_INITIALIZED(self);
1160
1161 tp = Py_TYPE(self);
1162 if (tp == &PyBufferedReader_Type ||
1163 tp == &PyBufferedRandom_Type) {
1164 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001165 line = _buffered_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001166 }
1167 else {
1168 line = PyObject_CallMethodObjArgs((PyObject *)self,
1169 _PyIO_str_readline, NULL);
1170 if (line && !PyBytes_Check(line)) {
1171 PyErr_Format(PyExc_IOError,
1172 "readline() should have returned a bytes object, "
1173 "not '%.200s'", Py_TYPE(line)->tp_name);
1174 Py_DECREF(line);
1175 return NULL;
1176 }
1177 }
1178
1179 if (line == NULL)
1180 return NULL;
1181
1182 if (PyBytes_GET_SIZE(line) == 0) {
1183 /* Reached EOF or would have blocked */
1184 Py_DECREF(line);
1185 return NULL;
1186 }
1187
1188 return line;
1189}
1190
Antoine Pitrou716c4442009-05-23 19:04:03 +00001191static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001192buffered_repr(buffered *self)
Antoine Pitrou716c4442009-05-23 19:04:03 +00001193{
1194 PyObject *nameobj, *res;
1195
1196 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1197 if (nameobj == NULL) {
1198 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1199 PyErr_Clear();
1200 else
1201 return NULL;
1202 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1203 }
1204 else {
1205 res = PyUnicode_FromFormat("<%s name=%R>",
1206 Py_TYPE(self)->tp_name, nameobj);
1207 Py_DECREF(nameobj);
1208 }
1209 return res;
1210}
1211
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001212/*
1213 * class BufferedReader
1214 */
1215
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001216PyDoc_STRVAR(bufferedreader_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001217 "Create a new buffered reader using the given readable raw IO object.");
1218
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001219static void _bufferedreader_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001220{
1221 self->read_end = -1;
1222}
1223
1224static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001225bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001226{
1227 char *kwlist[] = {"raw", "buffer_size", NULL};
1228 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1229 PyObject *raw;
1230
1231 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001232 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001233
1234 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1235 &raw, &buffer_size)) {
1236 return -1;
1237 }
1238
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001239 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001240 return -1;
1241
1242 Py_CLEAR(self->raw);
1243 Py_INCREF(raw);
1244 self->raw = raw;
1245 self->buffer_size = buffer_size;
1246 self->readable = 1;
1247 self->writable = 0;
1248
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001249 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001250 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001251 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001252
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001253 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1254 Py_TYPE(raw) == &PyFileIO_Type);
1255
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001256 self->ok = 1;
1257 return 0;
1258}
1259
1260static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001261_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001262{
1263 Py_buffer buf;
1264 PyObject *memobj, *res;
1265 Py_ssize_t n;
1266 /* NOTE: the buffer needn't be released as its object is NULL. */
1267 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1268 return -1;
1269 memobj = PyMemoryView_FromBuffer(&buf);
1270 if (memobj == NULL)
1271 return -1;
1272 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1273 Py_DECREF(memobj);
1274 if (res == NULL)
1275 return -1;
1276 if (res == Py_None) {
1277 /* Non-blocking stream would have blocked. Special return code! */
1278 Py_DECREF(res);
1279 return -2;
1280 }
1281 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1282 Py_DECREF(res);
1283 if (n < 0 || n > len) {
1284 PyErr_Format(PyExc_IOError,
1285 "raw readinto() returned invalid length %zd "
1286 "(should have been between 0 and %zd)", n, len);
1287 return -1;
1288 }
1289 if (n > 0 && self->abs_pos != -1)
1290 self->abs_pos += n;
1291 return n;
1292}
1293
1294static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001295_bufferedreader_fill_buffer(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001296{
1297 Py_ssize_t start, len, n;
1298 if (VALID_READ_BUFFER(self))
1299 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1300 else
1301 start = 0;
1302 len = self->buffer_size - start;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001303 n = _bufferedreader_raw_read(self, self->buffer + start, len);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001304 if (n <= 0)
1305 return n;
1306 self->read_end = start + n;
1307 self->raw_pos = start + n;
1308 return n;
1309}
1310
1311static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001312_bufferedreader_read_all(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001313{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001314 Py_ssize_t current_size;
1315 PyObject *res, *data = NULL;
1316 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001317
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001318 if (chunks == NULL)
1319 return NULL;
1320
1321 /* First copy what we have in the current buffer. */
1322 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1323 if (current_size) {
1324 data = PyBytes_FromStringAndSize(
1325 self->buffer + self->pos, current_size);
1326 if (data == NULL) {
1327 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001328 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001329 }
1330 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001331 _bufferedreader_reset_buf(self);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001332 /* We're going past the buffer's bounds, flush it */
1333 if (self->writable) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001334 res = _bufferedwriter_flush_unlocked(self, 1);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001335 if (res == NULL) {
1336 Py_DECREF(chunks);
1337 return NULL;
1338 }
1339 Py_CLEAR(res);
1340 }
1341 while (1) {
1342 if (data) {
1343 if (PyList_Append(chunks, data) < 0) {
1344 Py_DECREF(data);
1345 Py_DECREF(chunks);
1346 return NULL;
1347 }
1348 Py_DECREF(data);
1349 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001350
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001351 /* Read until EOF or until read() would block. */
1352 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1353 if (data == NULL) {
1354 Py_DECREF(chunks);
1355 return NULL;
1356 }
1357 if (data != Py_None && !PyBytes_Check(data)) {
1358 Py_DECREF(data);
1359 Py_DECREF(chunks);
1360 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1361 return NULL;
1362 }
1363 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1364 if (current_size == 0) {
1365 Py_DECREF(chunks);
1366 return data;
1367 }
1368 else {
1369 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1370 Py_DECREF(data);
1371 Py_DECREF(chunks);
1372 return res;
1373 }
1374 }
1375 current_size += PyBytes_GET_SIZE(data);
1376 if (self->abs_pos != -1)
1377 self->abs_pos += PyBytes_GET_SIZE(data);
1378 }
1379}
1380
1381/* Read n bytes from the buffer if it can, otherwise return None.
1382 This function is simple enough that it can run unlocked. */
1383static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001384_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001385{
1386 Py_ssize_t current_size;
1387
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001388 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1389 if (n <= current_size) {
1390 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001391 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1392 if (res != NULL)
1393 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001394 return res;
1395 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001396 Py_RETURN_NONE;
1397}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001398
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001399/* Generic read function: read from the stream until enough bytes are read,
1400 * or until an EOF occurs or until read() would block.
1401 */
1402static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001403_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001404{
1405 PyObject *res = NULL;
1406 Py_ssize_t current_size, remaining, written;
1407 char *out;
1408
1409 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1410 if (n <= current_size)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001411 return _bufferedreader_read_fast(self, n);
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001412
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001413 res = PyBytes_FromStringAndSize(NULL, n);
1414 if (res == NULL)
1415 goto error;
1416 out = PyBytes_AS_STRING(res);
1417 remaining = n;
1418 written = 0;
1419 if (current_size > 0) {
1420 memcpy(out, self->buffer + self->pos, current_size);
1421 remaining -= current_size;
1422 written += current_size;
1423 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001424 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001425 while (remaining > 0) {
1426 /* We want to read a whole block at the end into buffer.
1427 If we had readv() we could do this in one pass. */
1428 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1429 if (r == 0)
1430 break;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001431 r = _bufferedreader_raw_read(self, out + written, r);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001432 if (r == -1)
1433 goto error;
1434 if (r == 0 || r == -2) {
1435 /* EOF occurred or read() would block. */
1436 if (r == 0 || written > 0) {
1437 if (_PyBytes_Resize(&res, written))
1438 goto error;
1439 return res;
1440 }
1441 Py_DECREF(res);
1442 Py_INCREF(Py_None);
1443 return Py_None;
1444 }
1445 remaining -= r;
1446 written += r;
1447 }
1448 assert(remaining <= self->buffer_size);
1449 self->pos = 0;
1450 self->raw_pos = 0;
1451 self->read_end = 0;
Antoine Pitrou32cfede2010-08-11 13:31:33 +00001452 /* NOTE: when the read is satisfied, we avoid issuing any additional
1453 reads, which could block indefinitely (e.g. on a socket).
1454 See issue #9550. */
1455 while (remaining > 0 && self->read_end < self->buffer_size) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001456 Py_ssize_t r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001457 if (r == -1)
1458 goto error;
1459 if (r == 0 || r == -2) {
1460 /* EOF occurred or read() would block. */
1461 if (r == 0 || written > 0) {
1462 if (_PyBytes_Resize(&res, written))
1463 goto error;
1464 return res;
1465 }
1466 Py_DECREF(res);
1467 Py_INCREF(Py_None);
1468 return Py_None;
1469 }
1470 if (remaining > r) {
1471 memcpy(out + written, self->buffer + self->pos, r);
1472 written += r;
1473 self->pos += r;
1474 remaining -= r;
1475 }
1476 else if (remaining > 0) {
1477 memcpy(out + written, self->buffer + self->pos, remaining);
1478 written += remaining;
1479 self->pos += remaining;
1480 remaining = 0;
1481 }
1482 if (remaining == 0)
1483 break;
1484 }
1485
1486 return res;
1487
1488error:
1489 Py_XDECREF(res);
1490 return NULL;
1491}
1492
1493static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001494_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001495{
1496 Py_ssize_t have, r;
1497
1498 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1499 /* Constraints:
1500 1. we don't want to advance the file position.
1501 2. we don't want to lose block alignment, so we can't shift the buffer
1502 to make some place.
1503 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1504 */
1505 if (have > 0) {
1506 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1507 }
1508
1509 /* Fill the buffer from the raw stream, and copy it to the result. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001510 _bufferedreader_reset_buf(self);
1511 r = _bufferedreader_fill_buffer(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001512 if (r == -1)
1513 return NULL;
1514 if (r == -2)
1515 r = 0;
1516 self->pos = 0;
1517 return PyBytes_FromStringAndSize(self->buffer, r);
1518}
1519
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001520static PyMethodDef bufferedreader_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001521 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001522 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1523 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1524 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1525 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1526 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1527 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1528 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1529 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001530 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001531 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001532
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001533 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1534 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1535 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1536 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1537 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1538 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1539 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001540 {NULL, NULL}
1541};
1542
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001543static PyMemberDef bufferedreader_members[] = {
1544 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001545 {NULL}
1546};
1547
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001548static PyGetSetDef bufferedreader_getset[] = {
1549 {"closed", (getter)buffered_closed_get, NULL, NULL},
1550 {"name", (getter)buffered_name_get, NULL, NULL},
1551 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001552 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001553};
1554
1555
1556PyTypeObject PyBufferedReader_Type = {
1557 PyVarObject_HEAD_INIT(NULL, 0)
1558 "_io.BufferedReader", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001559 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001560 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001561 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001562 0, /*tp_print*/
1563 0, /*tp_getattr*/
1564 0, /*tp_setattr*/
1565 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001566 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001567 0, /*tp_as_number*/
1568 0, /*tp_as_sequence*/
1569 0, /*tp_as_mapping*/
1570 0, /*tp_hash */
1571 0, /*tp_call*/
1572 0, /*tp_str*/
1573 0, /*tp_getattro*/
1574 0, /*tp_setattro*/
1575 0, /*tp_as_buffer*/
1576 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1577 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001578 bufferedreader_doc, /* tp_doc */
1579 (traverseproc)buffered_traverse, /* tp_traverse */
1580 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001581 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001582 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001583 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001584 (iternextfunc)buffered_iternext, /* tp_iternext */
1585 bufferedreader_methods, /* tp_methods */
1586 bufferedreader_members, /* tp_members */
1587 bufferedreader_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001588 0, /* tp_base */
1589 0, /* tp_dict */
1590 0, /* tp_descr_get */
1591 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001592 offsetof(buffered, dict), /* tp_dictoffset */
1593 (initproc)bufferedreader_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001594 0, /* tp_alloc */
1595 PyType_GenericNew, /* tp_new */
1596};
1597
1598
Benjamin Peterson59406a92009-03-26 17:10:29 +00001599
1600static int
1601complain_about_max_buffer_size(void)
1602{
1603 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1604 "max_buffer_size is deprecated", 1) < 0)
1605 return 0;
1606 return 1;
1607}
1608
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001609/*
1610 * class BufferedWriter
1611 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001612PyDoc_STRVAR(bufferedwriter_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001613 "A buffer for a writeable sequential RawIO object.\n"
1614 "\n"
1615 "The constructor creates a BufferedWriter for the given writeable raw\n"
1616 "stream. If the buffer_size is not given, it defaults to\n"
1617 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1618 );
1619
1620static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001621_bufferedwriter_reset_buf(buffered *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001622{
1623 self->write_pos = 0;
1624 self->write_end = -1;
1625}
1626
1627static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001628bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001629{
1630 /* TODO: properly deprecate max_buffer_size */
1631 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1632 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001633 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001634 PyObject *raw;
1635
1636 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001637 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001638
1639 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1640 &raw, &buffer_size, &max_buffer_size)) {
1641 return -1;
1642 }
1643
Benjamin Peterson59406a92009-03-26 17:10:29 +00001644 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1645 return -1;
1646
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001647 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001648 return -1;
1649
1650 Py_CLEAR(self->raw);
1651 Py_INCREF(raw);
1652 self->raw = raw;
1653 self->readable = 0;
1654 self->writable = 1;
1655
1656 self->buffer_size = buffer_size;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001657 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001658 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001659 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001660 self->pos = 0;
1661
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001662 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1663 Py_TYPE(raw) == &PyFileIO_Type);
1664
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001665 self->ok = 1;
1666 return 0;
1667}
1668
1669static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001670_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001671{
1672 Py_buffer buf;
1673 PyObject *memobj, *res;
1674 Py_ssize_t n;
1675 /* NOTE: the buffer needn't be released as its object is NULL. */
1676 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1677 return -1;
1678 memobj = PyMemoryView_FromBuffer(&buf);
1679 if (memobj == NULL)
1680 return -1;
1681 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1682 Py_DECREF(memobj);
1683 if (res == NULL)
1684 return -1;
1685 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1686 Py_DECREF(res);
1687 if (n < 0 || n > len) {
1688 PyErr_Format(PyExc_IOError,
1689 "raw write() returned invalid length %zd "
1690 "(should have been between 0 and %zd)", n, len);
1691 return -1;
1692 }
1693 if (n > 0 && self->abs_pos != -1)
1694 self->abs_pos += n;
1695 return n;
1696}
1697
1698/* `restore_pos` is 1 if we need to restore the raw stream position at
1699 the end, 0 otherwise. */
1700static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001701_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001702{
1703 Py_ssize_t written = 0;
1704 Py_off_t n, rewind;
1705
1706 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1707 goto end;
1708 /* First, rewind */
1709 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1710 if (rewind != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001711 n = _buffered_raw_seek(self, -rewind, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001712 if (n < 0) {
1713 goto error;
1714 }
1715 self->raw_pos -= rewind;
1716 }
1717 while (self->write_pos < self->write_end) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001718 n = _bufferedwriter_raw_write(self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001719 self->buffer + self->write_pos,
1720 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1721 Py_off_t, Py_ssize_t));
1722 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001723 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001724 if (w == NULL)
1725 goto error;
1726 self->write_pos += *w;
1727 self->raw_pos = self->write_pos;
1728 written += *w;
1729 *w = written;
1730 /* Already re-raised */
1731 goto error;
1732 }
1733 self->write_pos += n;
1734 self->raw_pos = self->write_pos;
1735 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001736 /* Partial writes can return successfully when interrupted by a
1737 signal (see write(2)). We must run signal handlers before
1738 blocking another time, possibly indefinitely. */
1739 if (PyErr_CheckSignals() < 0)
1740 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001741 }
1742
1743 if (restore_pos) {
1744 Py_off_t forward = rewind - written;
1745 if (forward != 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001746 n = _buffered_raw_seek(self, forward, 1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001747 if (n < 0) {
1748 goto error;
1749 }
1750 self->raw_pos += forward;
1751 }
1752 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001753 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001754
1755end:
1756 Py_RETURN_NONE;
1757
1758error:
1759 return NULL;
1760}
1761
1762static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001763bufferedwriter_write(buffered *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001764{
1765 PyObject *res = NULL;
1766 Py_buffer buf;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001767 Py_ssize_t written, avail, remaining;
1768 Py_off_t offset;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001769
1770 CHECK_INITIALIZED(self)
1771 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1772 return NULL;
1773 }
1774
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001775 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001776 PyErr_SetString(PyExc_ValueError, "write to closed file");
1777 PyBuffer_Release(&buf);
1778 return NULL;
1779 }
1780
Antoine Pitrouf3b68b32010-12-03 18:41:39 +00001781 if (!ENTER_BUFFERED(self)) {
1782 PyBuffer_Release(&buf);
1783 return NULL;
1784 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001785
1786 /* Fast path: the data to write can be fully buffered. */
1787 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1788 self->pos = 0;
1789 self->raw_pos = 0;
1790 }
1791 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1792 if (buf.len <= avail) {
1793 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1794 if (!VALID_WRITE_BUFFER(self)) {
1795 self->write_pos = self->pos;
1796 }
1797 ADJUST_POSITION(self, self->pos + buf.len);
1798 if (self->pos > self->write_end)
1799 self->write_end = self->pos;
1800 written = buf.len;
1801 goto end;
1802 }
1803
1804 /* First write the current buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001805 res = _bufferedwriter_flush_unlocked(self, 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001806 if (res == NULL) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001807 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001808 if (w == NULL)
1809 goto error;
1810 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001811 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001812 /* Make some place by shifting the buffer. */
1813 assert(VALID_WRITE_BUFFER(self));
1814 memmove(self->buffer, self->buffer + self->write_pos,
1815 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1816 Py_off_t, Py_ssize_t));
1817 self->write_end -= self->write_pos;
1818 self->raw_pos -= self->write_pos;
1819 self->pos -= self->write_pos;
1820 self->write_pos = 0;
1821 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1822 Py_off_t, Py_ssize_t);
1823 if (buf.len <= avail) {
1824 /* Everything can be buffered */
1825 PyErr_Clear();
1826 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1827 self->write_end += buf.len;
1828 written = buf.len;
1829 goto end;
1830 }
1831 /* Buffer as much as possible. */
1832 memcpy(self->buffer + self->write_end, buf.buf, avail);
1833 self->write_end += avail;
1834 /* Already re-raised */
1835 *w = avail;
1836 goto error;
1837 }
1838 Py_CLEAR(res);
1839
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001840 /* Adjust the raw stream position if it is away from the logical stream
1841 position. This happens if the read buffer has been filled but not
1842 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1843 the raw stream by itself).
1844 Fixes issue #6629.
1845 */
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001846 offset = RAW_OFFSET(self);
1847 if (offset != 0) {
1848 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001849 goto error;
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001850 self->raw_pos -= offset;
Antoine Pitroua0ceb732009-08-06 20:29:56 +00001851 }
1852
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001853 /* Then write buf itself. At this point the buffer has been emptied. */
1854 remaining = buf.len;
1855 written = 0;
1856 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arce1b60d42009-10-05 21:09:00 +00001857 Py_ssize_t n = _bufferedwriter_raw_write(
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001858 self, (char *) buf.buf + written, buf.len - written);
1859 if (n == -1) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001860 Py_ssize_t *w = _buffered_check_blocking_error();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001861 if (w == NULL)
1862 goto error;
1863 written += *w;
1864 remaining -= *w;
1865 if (remaining > self->buffer_size) {
1866 /* Can't buffer everything, still buffer as much as possible */
1867 memcpy(self->buffer,
1868 (char *) buf.buf + written, self->buffer_size);
1869 self->raw_pos = 0;
1870 ADJUST_POSITION(self, self->buffer_size);
1871 self->write_end = self->buffer_size;
1872 *w = written + self->buffer_size;
1873 /* Already re-raised */
1874 goto error;
1875 }
1876 PyErr_Clear();
1877 break;
1878 }
1879 written += n;
1880 remaining -= n;
Antoine Pitroub46b9d52010-08-21 19:09:32 +00001881 /* Partial writes can return successfully when interrupted by a
1882 signal (see write(2)). We must run signal handlers before
1883 blocking another time, possibly indefinitely. */
1884 if (PyErr_CheckSignals() < 0)
1885 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001886 }
1887 if (self->readable)
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001888 _bufferedreader_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001889 if (remaining > 0) {
1890 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1891 written += remaining;
1892 }
1893 self->write_pos = 0;
1894 /* TODO: sanity check (remaining >= 0) */
1895 self->write_end = remaining;
1896 ADJUST_POSITION(self, remaining);
1897 self->raw_pos = 0;
1898
1899end:
1900 res = PyLong_FromSsize_t(written);
1901
1902error:
1903 LEAVE_BUFFERED(self)
1904 PyBuffer_Release(&buf);
1905 return res;
1906}
1907
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001908static PyMethodDef bufferedwriter_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001909 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001910 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1911 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1912 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1913 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1914 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1915 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1916 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00001917 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001918 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001919
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001920 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1921 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1922 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1923 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1924 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001925 {NULL, NULL}
1926};
1927
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001928static PyMemberDef bufferedwriter_members[] = {
1929 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001930 {NULL}
1931};
1932
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001933static PyGetSetDef bufferedwriter_getset[] = {
1934 {"closed", (getter)buffered_closed_get, NULL, NULL},
1935 {"name", (getter)buffered_name_get, NULL, NULL},
1936 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001937 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001938};
1939
1940
1941PyTypeObject PyBufferedWriter_Type = {
1942 PyVarObject_HEAD_INIT(NULL, 0)
1943 "_io.BufferedWriter", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001944 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001945 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001946 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001947 0, /*tp_print*/
1948 0, /*tp_getattr*/
1949 0, /*tp_setattr*/
1950 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001951 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001952 0, /*tp_as_number*/
1953 0, /*tp_as_sequence*/
1954 0, /*tp_as_mapping*/
1955 0, /*tp_hash */
1956 0, /*tp_call*/
1957 0, /*tp_str*/
1958 0, /*tp_getattro*/
1959 0, /*tp_setattro*/
1960 0, /*tp_as_buffer*/
1961 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1962 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001963 bufferedwriter_doc, /* tp_doc */
1964 (traverseproc)buffered_traverse, /* tp_traverse */
1965 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001966 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001967 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001968 0, /* tp_iter */
1969 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001970 bufferedwriter_methods, /* tp_methods */
1971 bufferedwriter_members, /* tp_members */
1972 bufferedwriter_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001973 0, /* tp_base */
1974 0, /* tp_dict */
1975 0, /* tp_descr_get */
1976 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001977 offsetof(buffered, dict), /* tp_dictoffset */
1978 (initproc)bufferedwriter_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001979 0, /* tp_alloc */
1980 PyType_GenericNew, /* tp_new */
1981};
1982
1983
1984
1985/*
1986 * BufferedRWPair
1987 */
1988
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001989PyDoc_STRVAR(bufferedrwpair_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001990 "A buffered reader and writer object together.\n"
1991 "\n"
1992 "A buffered reader object and buffered writer object put together to\n"
1993 "form a sequential IO object that can read and write. This is typically\n"
1994 "used with a socket or two-way pipe.\n"
1995 "\n"
1996 "reader and writer are RawIOBase objects that are readable and\n"
1997 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001998 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001999 );
2000
2001/* XXX The usefulness of this (compared to having two separate IO objects) is
2002 * questionable.
2003 */
2004
2005typedef struct {
2006 PyObject_HEAD
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002007 buffered *reader;
2008 buffered *writer;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002009 PyObject *dict;
2010 PyObject *weakreflist;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002011} rwpair;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002012
2013static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002014bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002015{
2016 PyObject *reader, *writer;
2017 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002018 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002019
2020 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2021 &buffer_size, &max_buffer_size)) {
2022 return -1;
2023 }
2024
Benjamin Peterson59406a92009-03-26 17:10:29 +00002025 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2026 return -1;
2027
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002028 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002029 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002030 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002031 return -1;
2032
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002033 self->reader = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002034 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002035 if (self->reader == NULL)
2036 return -1;
2037
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002038 self->writer = (buffered *) PyObject_CallFunction(
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002039 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002040 if (self->writer == NULL) {
2041 Py_CLEAR(self->reader);
2042 return -1;
2043 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002044
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002045 return 0;
2046}
2047
2048static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002049bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002050{
2051 Py_VISIT(self->dict);
2052 return 0;
2053}
2054
2055static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002056bufferedrwpair_clear(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002057{
2058 Py_CLEAR(self->reader);
2059 Py_CLEAR(self->writer);
2060 Py_CLEAR(self->dict);
2061 return 0;
2062}
2063
2064static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002065bufferedrwpair_dealloc(rwpair *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002066{
2067 _PyObject_GC_UNTRACK(self);
2068 Py_CLEAR(self->reader);
2069 Py_CLEAR(self->writer);
2070 Py_CLEAR(self->dict);
2071 Py_TYPE(self)->tp_free((PyObject *) self);
2072}
2073
2074static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002075_forward_call(buffered *self, const char *name, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002076{
2077 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2078 PyObject *ret;
2079
2080 if (func == NULL) {
2081 PyErr_SetString(PyExc_AttributeError, name);
2082 return NULL;
2083 }
2084
2085 ret = PyObject_CallObject(func, args);
2086 Py_DECREF(func);
2087 return ret;
2088}
2089
2090static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002091bufferedrwpair_read(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002092{
2093 return _forward_call(self->reader, "read", args);
2094}
2095
2096static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002097bufferedrwpair_peek(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002098{
2099 return _forward_call(self->reader, "peek", args);
2100}
2101
2102static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002103bufferedrwpair_read1(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002104{
2105 return _forward_call(self->reader, "read1", args);
2106}
2107
2108static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002109bufferedrwpair_readinto(rwpair *self, PyObject *args)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002110{
2111 return _forward_call(self->reader, "readinto", args);
2112}
2113
2114static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002115bufferedrwpair_write(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002116{
2117 return _forward_call(self->writer, "write", args);
2118}
2119
2120static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002121bufferedrwpair_flush(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002122{
2123 return _forward_call(self->writer, "flush", args);
2124}
2125
2126static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002127bufferedrwpair_readable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002128{
2129 return _forward_call(self->reader, "readable", args);
2130}
2131
2132static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002133bufferedrwpair_writable(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002134{
2135 return _forward_call(self->writer, "writable", args);
2136}
2137
2138static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002139bufferedrwpair_close(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002140{
2141 PyObject *ret = _forward_call(self->writer, "close", args);
2142 if (ret == NULL)
2143 return NULL;
2144 Py_DECREF(ret);
2145
2146 return _forward_call(self->reader, "close", args);
2147}
2148
2149static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002150bufferedrwpair_isatty(rwpair *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002151{
2152 PyObject *ret = _forward_call(self->writer, "isatty", args);
2153
2154 if (ret != Py_False) {
2155 /* either True or exception */
2156 return ret;
2157 }
2158 Py_DECREF(ret);
2159
2160 return _forward_call(self->reader, "isatty", args);
2161}
2162
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002163static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002164bufferedrwpair_closed_get(rwpair *self, void *context)
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002165{
2166 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2167}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002168
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002169static PyMethodDef bufferedrwpair_methods[] = {
2170 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2171 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2172 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2173 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002174
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002175 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2176 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002177
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002178 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2179 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002180
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002181 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2182 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002183
Antoine Pitrou243757e2010-11-05 21:15:39 +00002184 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2185
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002186 {NULL, NULL}
2187};
2188
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002189static PyGetSetDef bufferedrwpair_getset[] = {
2190 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002191 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002192};
2193
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002194PyTypeObject PyBufferedRWPair_Type = {
2195 PyVarObject_HEAD_INIT(NULL, 0)
2196 "_io.BufferedRWPair", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002197 sizeof(rwpair), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002198 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002199 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002200 0, /*tp_print*/
2201 0, /*tp_getattr*/
2202 0, /*tp_setattr*/
2203 0, /*tp_compare */
2204 0, /*tp_repr*/
2205 0, /*tp_as_number*/
2206 0, /*tp_as_sequence*/
2207 0, /*tp_as_mapping*/
2208 0, /*tp_hash */
2209 0, /*tp_call*/
2210 0, /*tp_str*/
2211 0, /*tp_getattro*/
2212 0, /*tp_setattro*/
2213 0, /*tp_as_buffer*/
2214 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2215 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002216 bufferedrwpair_doc, /* tp_doc */
2217 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2218 (inquiry)bufferedrwpair_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002219 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002220 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002221 0, /* tp_iter */
2222 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002223 bufferedrwpair_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002224 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002225 bufferedrwpair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002226 0, /* tp_base */
2227 0, /* tp_dict */
2228 0, /* tp_descr_get */
2229 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002230 offsetof(rwpair, dict), /* tp_dictoffset */
2231 (initproc)bufferedrwpair_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002232 0, /* tp_alloc */
2233 PyType_GenericNew, /* tp_new */
2234};
2235
2236
2237
2238/*
2239 * BufferedRandom
2240 */
2241
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002242PyDoc_STRVAR(bufferedrandom_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002243 "A buffered interface to random access streams.\n"
2244 "\n"
2245 "The constructor creates a reader and writer for a seekable stream,\n"
2246 "raw, given in the first argument. If the buffer_size is omitted it\n"
2247 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2248 );
2249
2250static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002251bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002252{
2253 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2254 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002255 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002256 PyObject *raw;
2257
2258 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002259 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002260
2261 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2262 &raw, &buffer_size, &max_buffer_size)) {
2263 return -1;
2264 }
2265
Benjamin Peterson59406a92009-03-26 17:10:29 +00002266 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2267 return -1;
2268
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002269 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002270 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002271 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002272 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002273 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002274 return -1;
2275
2276 Py_CLEAR(self->raw);
2277 Py_INCREF(raw);
2278 self->raw = raw;
2279 self->buffer_size = buffer_size;
2280 self->readable = 1;
2281 self->writable = 1;
2282
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002283 if (_buffered_init(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002284 return -1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002285 _bufferedreader_reset_buf(self);
2286 _bufferedwriter_reset_buf(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002287 self->pos = 0;
2288
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002289 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2290 Py_TYPE(raw) == &PyFileIO_Type);
2291
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002292 self->ok = 1;
2293 return 0;
2294}
2295
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002296static PyMethodDef bufferedrandom_methods[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002297 /* BufferedIOMixin methods */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002298 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2299 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2300 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2301 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2302 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2303 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2304 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
Antoine Pitroue033e062010-10-29 10:38:18 +00002305 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002306 {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002307
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002308 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002309
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002310 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2311 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2312 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2313 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2314 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2315 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2316 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2317 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2318 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002319 {NULL, NULL}
2320};
2321
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002322static PyMemberDef bufferedrandom_members[] = {
2323 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002324 {NULL}
2325};
2326
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002327static PyGetSetDef bufferedrandom_getset[] = {
2328 {"closed", (getter)buffered_closed_get, NULL, NULL},
2329 {"name", (getter)buffered_name_get, NULL, NULL},
2330 {"mode", (getter)buffered_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002331 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002332};
2333
2334
2335PyTypeObject PyBufferedRandom_Type = {
2336 PyVarObject_HEAD_INIT(NULL, 0)
2337 "_io.BufferedRandom", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002338 sizeof(buffered), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002339 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002340 (destructor)buffered_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002341 0, /*tp_print*/
2342 0, /*tp_getattr*/
2343 0, /*tp_setattr*/
2344 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002345 (reprfunc)buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002346 0, /*tp_as_number*/
2347 0, /*tp_as_sequence*/
2348 0, /*tp_as_mapping*/
2349 0, /*tp_hash */
2350 0, /*tp_call*/
2351 0, /*tp_str*/
2352 0, /*tp_getattro*/
2353 0, /*tp_setattro*/
2354 0, /*tp_as_buffer*/
2355 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2356 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002357 bufferedrandom_doc, /* tp_doc */
2358 (traverseproc)buffered_traverse, /* tp_traverse */
2359 (inquiry)buffered_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002360 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002361 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002362 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002363 (iternextfunc)buffered_iternext, /* tp_iternext */
2364 bufferedrandom_methods, /* tp_methods */
2365 bufferedrandom_members, /* tp_members */
2366 bufferedrandom_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002367 0, /* tp_base */
2368 0, /*tp_dict*/
2369 0, /* tp_descr_get */
2370 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002371 offsetof(buffered, dict), /*tp_dictoffset*/
2372 (initproc)bufferedrandom_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002373 0, /* tp_alloc */
2374 PyType_GenericNew, /* tp_new */
2375};