]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | /*\r |
2 | An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"\r | |
3 | \r | |
4 | Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,\r | |
5 | BufferedRandom.\r | |
6 | \r | |
7 | Written by Amaury Forgeot d'Arc and Antoine Pitrou\r | |
8 | */\r | |
9 | \r | |
10 | #define PY_SSIZE_T_CLEAN\r | |
11 | #include "Python.h"\r | |
12 | #include "structmember.h"\r | |
13 | #include "pythread.h"\r | |
14 | #include "_iomodule.h"\r | |
15 | \r | |
16 | /*\r | |
17 | * BufferedIOBase class, inherits from IOBase.\r | |
18 | */\r | |
19 | PyDoc_STRVAR(bufferediobase_doc,\r | |
20 | "Base class for buffered IO objects.\n"\r | |
21 | "\n"\r | |
22 | "The main difference with RawIOBase is that the read() method\n"\r | |
23 | "supports omitting the size argument, and does not have a default\n"\r | |
24 | "implementation that defers to readinto().\n"\r | |
25 | "\n"\r | |
26 | "In addition, read(), readinto() and write() may raise\n"\r | |
27 | "BlockingIOError if the underlying raw stream is in non-blocking\n"\r | |
28 | "mode and not ready; unlike their raw counterparts, they will never\n"\r | |
29 | "return None.\n"\r | |
30 | "\n"\r | |
31 | "A typical implementation should not inherit from a RawIOBase\n"\r | |
32 | "implementation, but wrap one.\n"\r | |
33 | );\r | |
34 | \r | |
35 | static PyObject *\r | |
36 | bufferediobase_readinto(PyObject *self, PyObject *args)\r | |
37 | {\r | |
38 | Py_buffer buf;\r | |
39 | Py_ssize_t len;\r | |
40 | PyObject *data;\r | |
41 | \r | |
42 | if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {\r | |
43 | return NULL;\r | |
44 | }\r | |
45 | \r | |
46 | data = PyObject_CallMethod(self, "read", "n", buf.len);\r | |
47 | if (data == NULL)\r | |
48 | goto error;\r | |
49 | \r | |
50 | if (!PyBytes_Check(data)) {\r | |
51 | Py_DECREF(data);\r | |
52 | PyErr_SetString(PyExc_TypeError, "read() should return bytes");\r | |
53 | goto error;\r | |
54 | }\r | |
55 | \r | |
56 | len = Py_SIZE(data);\r | |
57 | memcpy(buf.buf, PyBytes_AS_STRING(data), len);\r | |
58 | \r | |
59 | PyBuffer_Release(&buf);\r | |
60 | Py_DECREF(data);\r | |
61 | \r | |
62 | return PyLong_FromSsize_t(len);\r | |
63 | \r | |
64 | error:\r | |
65 | PyBuffer_Release(&buf);\r | |
66 | return NULL;\r | |
67 | }\r | |
68 | \r | |
69 | static PyObject *\r | |
70 | bufferediobase_unsupported(const char *message)\r | |
71 | {\r | |
72 | PyErr_SetString(_PyIO_unsupported_operation, message);\r | |
73 | return NULL;\r | |
74 | }\r | |
75 | \r | |
76 | PyDoc_STRVAR(bufferediobase_detach_doc,\r | |
77 | "Disconnect this buffer from its underlying raw stream and return it.\n"\r | |
78 | "\n"\r | |
79 | "After the raw stream has been detached, the buffer is in an unusable\n"\r | |
80 | "state.\n");\r | |
81 | \r | |
82 | static PyObject *\r | |
83 | bufferediobase_detach(PyObject *self)\r | |
84 | {\r | |
85 | return bufferediobase_unsupported("detach");\r | |
86 | }\r | |
87 | \r | |
88 | PyDoc_STRVAR(bufferediobase_read_doc,\r | |
89 | "Read and return up to n bytes.\n"\r | |
90 | "\n"\r | |
91 | "If the argument is omitted, None, or negative, reads and\n"\r | |
92 | "returns all data until EOF.\n"\r | |
93 | "\n"\r | |
94 | "If the argument is positive, and the underlying raw stream is\n"\r | |
95 | "not 'interactive', multiple raw reads may be issued to satisfy\n"\r | |
96 | "the byte count (unless EOF is reached first). But for\n"\r | |
97 | "interactive raw streams (as well as sockets and pipes), at most\n"\r | |
98 | "one raw read will be issued, and a short result does not imply\n"\r | |
99 | "that EOF is imminent.\n"\r | |
100 | "\n"\r | |
101 | "Returns an empty bytes object on EOF.\n"\r | |
102 | "\n"\r | |
103 | "Returns None if the underlying raw stream was open in non-blocking\n"\r | |
104 | "mode and no data is available at the moment.\n");\r | |
105 | \r | |
106 | static PyObject *\r | |
107 | bufferediobase_read(PyObject *self, PyObject *args)\r | |
108 | {\r | |
109 | return bufferediobase_unsupported("read");\r | |
110 | }\r | |
111 | \r | |
112 | PyDoc_STRVAR(bufferediobase_read1_doc,\r | |
113 | "Read and return up to n bytes, with at most one read() call\n"\r | |
114 | "to the underlying raw stream. A short result does not imply\n"\r | |
115 | "that EOF is imminent.\n"\r | |
116 | "\n"\r | |
117 | "Returns an empty bytes object on EOF.\n");\r | |
118 | \r | |
119 | static PyObject *\r | |
120 | bufferediobase_read1(PyObject *self, PyObject *args)\r | |
121 | {\r | |
122 | return bufferediobase_unsupported("read1");\r | |
123 | }\r | |
124 | \r | |
125 | PyDoc_STRVAR(bufferediobase_write_doc,\r | |
126 | "Write the given buffer to the IO stream.\n"\r | |
127 | "\n"\r | |
128 | "Returns the number of bytes written, which is never less than\n"\r | |
129 | "len(b).\n"\r | |
130 | "\n"\r | |
131 | "Raises BlockingIOError if the buffer is full and the\n"\r | |
132 | "underlying raw stream cannot accept more data at the moment.\n");\r | |
133 | \r | |
134 | static PyObject *\r | |
135 | bufferediobase_write(PyObject *self, PyObject *args)\r | |
136 | {\r | |
137 | return bufferediobase_unsupported("write");\r | |
138 | }\r | |
139 | \r | |
140 | \r | |
141 | static PyMethodDef bufferediobase_methods[] = {\r | |
142 | {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},\r | |
143 | {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},\r | |
144 | {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},\r | |
145 | {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},\r | |
146 | {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},\r | |
147 | {NULL, NULL}\r | |
148 | };\r | |
149 | \r | |
150 | PyTypeObject PyBufferedIOBase_Type = {\r | |
151 | PyVarObject_HEAD_INIT(NULL, 0)\r | |
152 | "_io._BufferedIOBase", /*tp_name*/\r | |
153 | 0, /*tp_basicsize*/\r | |
154 | 0, /*tp_itemsize*/\r | |
155 | 0, /*tp_dealloc*/\r | |
156 | 0, /*tp_print*/\r | |
157 | 0, /*tp_getattr*/\r | |
158 | 0, /*tp_setattr*/\r | |
159 | 0, /*tp_compare */\r | |
160 | 0, /*tp_repr*/\r | |
161 | 0, /*tp_as_number*/\r | |
162 | 0, /*tp_as_sequence*/\r | |
163 | 0, /*tp_as_mapping*/\r | |
164 | 0, /*tp_hash */\r | |
165 | 0, /*tp_call*/\r | |
166 | 0, /*tp_str*/\r | |
167 | 0, /*tp_getattro*/\r | |
168 | 0, /*tp_setattro*/\r | |
169 | 0, /*tp_as_buffer*/\r | |
170 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\r | |
171 | bufferediobase_doc, /* tp_doc */\r | |
172 | 0, /* tp_traverse */\r | |
173 | 0, /* tp_clear */\r | |
174 | 0, /* tp_richcompare */\r | |
175 | 0, /* tp_weaklistoffset */\r | |
176 | 0, /* tp_iter */\r | |
177 | 0, /* tp_iternext */\r | |
178 | bufferediobase_methods, /* tp_methods */\r | |
179 | 0, /* tp_members */\r | |
180 | 0, /* tp_getset */\r | |
181 | &PyIOBase_Type, /* tp_base */\r | |
182 | 0, /* tp_dict */\r | |
183 | 0, /* tp_descr_get */\r | |
184 | 0, /* tp_descr_set */\r | |
185 | 0, /* tp_dictoffset */\r | |
186 | 0, /* tp_init */\r | |
187 | 0, /* tp_alloc */\r | |
188 | 0, /* tp_new */\r | |
189 | };\r | |
190 | \r | |
191 | \r | |
192 | typedef struct {\r | |
193 | PyObject_HEAD\r | |
194 | \r | |
195 | PyObject *raw;\r | |
196 | int ok; /* Initialized? */\r | |
197 | int detached;\r | |
198 | int readable;\r | |
199 | int writable;\r | |
200 | \r | |
201 | /* True if this is a vanilla Buffered object (rather than a user derived\r | |
202 | class) *and* the raw stream is a vanilla FileIO object. */\r | |
203 | int fast_closed_checks;\r | |
204 | \r | |
205 | /* Absolute position inside the raw stream (-1 if unknown). */\r | |
206 | Py_off_t abs_pos;\r | |
207 | \r | |
208 | /* A static buffer of size `buffer_size` */\r | |
209 | char *buffer;\r | |
210 | /* Current logical position in the buffer. */\r | |
211 | Py_off_t pos;\r | |
212 | /* Position of the raw stream in the buffer. */\r | |
213 | Py_off_t raw_pos;\r | |
214 | \r | |
215 | /* Just after the last buffered byte in the buffer, or -1 if the buffer\r | |
216 | isn't ready for reading. */\r | |
217 | Py_off_t read_end;\r | |
218 | \r | |
219 | /* Just after the last byte actually written */\r | |
220 | Py_off_t write_pos;\r | |
221 | /* Just after the last byte waiting to be written, or -1 if the buffer\r | |
222 | isn't ready for writing. */\r | |
223 | Py_off_t write_end;\r | |
224 | \r | |
225 | #ifdef WITH_THREAD\r | |
226 | PyThread_type_lock lock;\r | |
227 | volatile long owner;\r | |
228 | #endif\r | |
229 | \r | |
230 | Py_ssize_t buffer_size;\r | |
231 | Py_ssize_t buffer_mask;\r | |
232 | \r | |
233 | PyObject *dict;\r | |
234 | PyObject *weakreflist;\r | |
235 | } buffered;\r | |
236 | \r | |
237 | /*\r | |
238 | Implementation notes:\r | |
239 | \r | |
240 | * BufferedReader, BufferedWriter and BufferedRandom try to share most\r | |
241 | methods (this is helped by the members `readable` and `writable`, which\r | |
242 | are initialized in the respective constructors)\r | |
243 | * They also share a single buffer for reading and writing. This enables\r | |
244 | interleaved reads and writes without flushing. It also makes the logic\r | |
245 | a bit trickier to get right.\r | |
246 | * The absolute position of the raw stream is cached, if possible, in the\r | |
247 | `abs_pos` member. It must be updated every time an operation is done\r | |
248 | on the raw stream. If not sure, it can be reinitialized by calling\r | |
249 | _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()\r | |
250 | also does it). To read it, use RAW_TELL().\r | |
251 | * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and\r | |
252 | _bufferedwriter_flush_unlocked do a lot of useful housekeeping.\r | |
253 | \r | |
254 | NOTE: we should try to maintain block alignment of reads and writes to the\r | |
255 | raw stream (according to the buffer size), but for now it is only done\r | |
256 | in read() and friends.\r | |
257 | \r | |
258 | */\r | |
259 | \r | |
260 | /* These macros protect the buffered object against concurrent operations. */\r | |
261 | \r | |
262 | #ifdef WITH_THREAD\r | |
263 | \r | |
264 | static int\r | |
265 | _enter_buffered_busy(buffered *self)\r | |
266 | {\r | |
267 | if (self->owner == PyThread_get_thread_ident()) {\r | |
268 | PyObject *r = PyObject_Repr((PyObject *) self);\r | |
269 | if (r != NULL) {\r | |
270 | PyErr_Format(PyExc_RuntimeError,\r | |
271 | "reentrant call inside %s",\r | |
272 | PyString_AS_STRING(r));\r | |
273 | Py_DECREF(r);\r | |
274 | }\r | |
275 | return 0;\r | |
276 | }\r | |
277 | Py_BEGIN_ALLOW_THREADS\r | |
278 | PyThread_acquire_lock(self->lock, 1);\r | |
279 | Py_END_ALLOW_THREADS\r | |
280 | return 1;\r | |
281 | }\r | |
282 | \r | |
283 | #define ENTER_BUFFERED(self) \\r | |
284 | ( (PyThread_acquire_lock(self->lock, 0) ? \\r | |
285 | 1 : _enter_buffered_busy(self)) \\r | |
286 | && (self->owner = PyThread_get_thread_ident(), 1) )\r | |
287 | \r | |
288 | #define LEAVE_BUFFERED(self) \\r | |
289 | do { \\r | |
290 | self->owner = 0; \\r | |
291 | PyThread_release_lock(self->lock); \\r | |
292 | } while(0);\r | |
293 | \r | |
294 | #else\r | |
295 | #define ENTER_BUFFERED(self) 1\r | |
296 | #define LEAVE_BUFFERED(self)\r | |
297 | #endif\r | |
298 | \r | |
299 | #define CHECK_INITIALIZED(self) \\r | |
300 | if (self->ok <= 0) { \\r | |
301 | if (self->detached) { \\r | |
302 | PyErr_SetString(PyExc_ValueError, \\r | |
303 | "raw stream has been detached"); \\r | |
304 | } else { \\r | |
305 | PyErr_SetString(PyExc_ValueError, \\r | |
306 | "I/O operation on uninitialized object"); \\r | |
307 | } \\r | |
308 | return NULL; \\r | |
309 | }\r | |
310 | \r | |
311 | #define CHECK_INITIALIZED_INT(self) \\r | |
312 | if (self->ok <= 0) { \\r | |
313 | if (self->detached) { \\r | |
314 | PyErr_SetString(PyExc_ValueError, \\r | |
315 | "raw stream has been detached"); \\r | |
316 | } else { \\r | |
317 | PyErr_SetString(PyExc_ValueError, \\r | |
318 | "I/O operation on uninitialized object"); \\r | |
319 | } \\r | |
320 | return -1; \\r | |
321 | }\r | |
322 | \r | |
323 | #define IS_CLOSED(self) \\r | |
324 | (self->fast_closed_checks \\r | |
325 | ? _PyFileIO_closed(self->raw) \\r | |
326 | : buffered_closed(self))\r | |
327 | \r | |
328 | #define CHECK_CLOSED(self, error_msg) \\r | |
329 | if (IS_CLOSED(self)) { \\r | |
330 | PyErr_SetString(PyExc_ValueError, error_msg); \\r | |
331 | return NULL; \\r | |
332 | }\r | |
333 | \r | |
334 | \r | |
335 | #define VALID_READ_BUFFER(self) \\r | |
336 | (self->readable && self->read_end != -1)\r | |
337 | \r | |
338 | #define VALID_WRITE_BUFFER(self) \\r | |
339 | (self->writable && self->write_end != -1)\r | |
340 | \r | |
341 | #define ADJUST_POSITION(self, _new_pos) \\r | |
342 | do { \\r | |
343 | self->pos = _new_pos; \\r | |
344 | if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \\r | |
345 | self->read_end = self->pos; \\r | |
346 | } while(0)\r | |
347 | \r | |
348 | #define READAHEAD(self) \\r | |
349 | ((self->readable && VALID_READ_BUFFER(self)) \\r | |
350 | ? (self->read_end - self->pos) : 0)\r | |
351 | \r | |
352 | #define RAW_OFFSET(self) \\r | |
353 | (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \\r | |
354 | && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)\r | |
355 | \r | |
356 | #define RAW_TELL(self) \\r | |
357 | (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))\r | |
358 | \r | |
359 | #define MINUS_LAST_BLOCK(self, size) \\r | |
360 | (self->buffer_mask ? \\r | |
361 | (size & ~self->buffer_mask) : \\r | |
362 | (self->buffer_size * (size / self->buffer_size)))\r | |
363 | \r | |
364 | \r | |
365 | static void\r | |
366 | buffered_dealloc(buffered *self)\r | |
367 | {\r | |
368 | if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)\r | |
369 | return;\r | |
370 | _PyObject_GC_UNTRACK(self);\r | |
371 | self->ok = 0;\r | |
372 | if (self->weakreflist != NULL)\r | |
373 | PyObject_ClearWeakRefs((PyObject *)self);\r | |
374 | Py_CLEAR(self->raw);\r | |
375 | if (self->buffer) {\r | |
376 | PyMem_Free(self->buffer);\r | |
377 | self->buffer = NULL;\r | |
378 | }\r | |
379 | #ifdef WITH_THREAD\r | |
380 | if (self->lock) {\r | |
381 | PyThread_free_lock(self->lock);\r | |
382 | self->lock = NULL;\r | |
383 | }\r | |
384 | #endif\r | |
385 | Py_CLEAR(self->dict);\r | |
386 | Py_TYPE(self)->tp_free((PyObject *)self);\r | |
387 | }\r | |
388 | \r | |
389 | static int\r | |
390 | buffered_traverse(buffered *self, visitproc visit, void *arg)\r | |
391 | {\r | |
392 | Py_VISIT(self->raw);\r | |
393 | Py_VISIT(self->dict);\r | |
394 | return 0;\r | |
395 | }\r | |
396 | \r | |
397 | static int\r | |
398 | buffered_clear(buffered *self)\r | |
399 | {\r | |
400 | if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)\r | |
401 | return -1;\r | |
402 | self->ok = 0;\r | |
403 | Py_CLEAR(self->raw);\r | |
404 | Py_CLEAR(self->dict);\r | |
405 | return 0;\r | |
406 | }\r | |
407 | \r | |
408 | /*\r | |
409 | * _BufferedIOMixin methods\r | |
410 | * This is not a class, just a collection of methods that will be reused\r | |
411 | * by BufferedReader and BufferedWriter\r | |
412 | */\r | |
413 | \r | |
414 | /* Flush and close */\r | |
415 | \r | |
416 | static PyObject *\r | |
417 | buffered_simple_flush(buffered *self, PyObject *args)\r | |
418 | {\r | |
419 | CHECK_INITIALIZED(self)\r | |
420 | return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);\r | |
421 | }\r | |
422 | \r | |
423 | static int\r | |
424 | buffered_closed(buffered *self)\r | |
425 | {\r | |
426 | int closed;\r | |
427 | PyObject *res;\r | |
428 | CHECK_INITIALIZED_INT(self)\r | |
429 | res = PyObject_GetAttr(self->raw, _PyIO_str_closed);\r | |
430 | if (res == NULL)\r | |
431 | return -1;\r | |
432 | closed = PyObject_IsTrue(res);\r | |
433 | Py_DECREF(res);\r | |
434 | return closed;\r | |
435 | }\r | |
436 | \r | |
437 | static PyObject *\r | |
438 | buffered_closed_get(buffered *self, void *context)\r | |
439 | {\r | |
440 | CHECK_INITIALIZED(self)\r | |
441 | return PyObject_GetAttr(self->raw, _PyIO_str_closed);\r | |
442 | }\r | |
443 | \r | |
444 | static PyObject *\r | |
445 | buffered_close(buffered *self, PyObject *args)\r | |
446 | {\r | |
447 | PyObject *res = NULL;\r | |
448 | int r;\r | |
449 | \r | |
450 | CHECK_INITIALIZED(self)\r | |
451 | if (!ENTER_BUFFERED(self))\r | |
452 | return NULL;\r | |
453 | \r | |
454 | r = buffered_closed(self);\r | |
455 | if (r < 0)\r | |
456 | goto end;\r | |
457 | if (r > 0) {\r | |
458 | res = Py_None;\r | |
459 | Py_INCREF(res);\r | |
460 | goto end;\r | |
461 | }\r | |
462 | /* flush() will most probably re-take the lock, so drop it first */\r | |
463 | LEAVE_BUFFERED(self)\r | |
464 | res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);\r | |
465 | if (!ENTER_BUFFERED(self))\r | |
466 | return NULL;\r | |
467 | if (res == NULL) {\r | |
468 | goto end;\r | |
469 | }\r | |
470 | Py_XDECREF(res);\r | |
471 | \r | |
472 | res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);\r | |
473 | \r | |
474 | end:\r | |
475 | LEAVE_BUFFERED(self)\r | |
476 | return res;\r | |
477 | }\r | |
478 | \r | |
479 | /* detach */\r | |
480 | \r | |
481 | static PyObject *\r | |
482 | buffered_detach(buffered *self, PyObject *args)\r | |
483 | {\r | |
484 | PyObject *raw, *res;\r | |
485 | CHECK_INITIALIZED(self)\r | |
486 | res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);\r | |
487 | if (res == NULL)\r | |
488 | return NULL;\r | |
489 | Py_DECREF(res);\r | |
490 | raw = self->raw;\r | |
491 | self->raw = NULL;\r | |
492 | self->detached = 1;\r | |
493 | self->ok = 0;\r | |
494 | return raw;\r | |
495 | }\r | |
496 | \r | |
497 | /* Inquiries */\r | |
498 | \r | |
499 | static PyObject *\r | |
500 | buffered_seekable(buffered *self, PyObject *args)\r | |
501 | {\r | |
502 | CHECK_INITIALIZED(self)\r | |
503 | return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);\r | |
504 | }\r | |
505 | \r | |
506 | static PyObject *\r | |
507 | buffered_readable(buffered *self, PyObject *args)\r | |
508 | {\r | |
509 | CHECK_INITIALIZED(self)\r | |
510 | return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);\r | |
511 | }\r | |
512 | \r | |
513 | static PyObject *\r | |
514 | buffered_writable(buffered *self, PyObject *args)\r | |
515 | {\r | |
516 | CHECK_INITIALIZED(self)\r | |
517 | return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);\r | |
518 | }\r | |
519 | \r | |
520 | static PyObject *\r | |
521 | buffered_name_get(buffered *self, void *context)\r | |
522 | {\r | |
523 | CHECK_INITIALIZED(self)\r | |
524 | return PyObject_GetAttrString(self->raw, "name");\r | |
525 | }\r | |
526 | \r | |
527 | static PyObject *\r | |
528 | buffered_mode_get(buffered *self, void *context)\r | |
529 | {\r | |
530 | CHECK_INITIALIZED(self)\r | |
531 | return PyObject_GetAttrString(self->raw, "mode");\r | |
532 | }\r | |
533 | \r | |
534 | /* Lower-level APIs */\r | |
535 | \r | |
536 | static PyObject *\r | |
537 | buffered_fileno(buffered *self, PyObject *args)\r | |
538 | {\r | |
539 | CHECK_INITIALIZED(self)\r | |
540 | return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);\r | |
541 | }\r | |
542 | \r | |
543 | static PyObject *\r | |
544 | buffered_isatty(buffered *self, PyObject *args)\r | |
545 | {\r | |
546 | CHECK_INITIALIZED(self)\r | |
547 | return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);\r | |
548 | }\r | |
549 | \r | |
550 | \r | |
551 | /* Forward decls */\r | |
552 | static PyObject *\r | |
553 | _bufferedwriter_flush_unlocked(buffered *, int);\r | |
554 | static Py_ssize_t\r | |
555 | _bufferedreader_fill_buffer(buffered *self);\r | |
556 | static void\r | |
557 | _bufferedreader_reset_buf(buffered *self);\r | |
558 | static void\r | |
559 | _bufferedwriter_reset_buf(buffered *self);\r | |
560 | static PyObject *\r | |
561 | _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);\r | |
562 | static PyObject *\r | |
563 | _bufferedreader_read_all(buffered *self);\r | |
564 | static PyObject *\r | |
565 | _bufferedreader_read_fast(buffered *self, Py_ssize_t);\r | |
566 | static PyObject *\r | |
567 | _bufferedreader_read_generic(buffered *self, Py_ssize_t);\r | |
568 | \r | |
569 | \r | |
570 | /*\r | |
571 | * Helpers\r | |
572 | */\r | |
573 | \r | |
574 | /* Returns the address of the `written` member if a BlockingIOError was\r | |
575 | raised, NULL otherwise. The error is always re-raised. */\r | |
576 | static Py_ssize_t *\r | |
577 | _buffered_check_blocking_error(void)\r | |
578 | {\r | |
579 | PyObject *t, *v, *tb;\r | |
580 | PyBlockingIOErrorObject *err;\r | |
581 | \r | |
582 | PyErr_Fetch(&t, &v, &tb);\r | |
583 | if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {\r | |
584 | PyErr_Restore(t, v, tb);\r | |
585 | return NULL;\r | |
586 | }\r | |
587 | err = (PyBlockingIOErrorObject *) v;\r | |
588 | /* TODO: sanity check (err->written >= 0) */\r | |
589 | PyErr_Restore(t, v, tb);\r | |
590 | return &err->written;\r | |
591 | }\r | |
592 | \r | |
593 | static Py_off_t\r | |
594 | _buffered_raw_tell(buffered *self)\r | |
595 | {\r | |
596 | Py_off_t n;\r | |
597 | PyObject *res;\r | |
598 | res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);\r | |
599 | if (res == NULL)\r | |
600 | return -1;\r | |
601 | n = PyNumber_AsOff_t(res, PyExc_ValueError);\r | |
602 | Py_DECREF(res);\r | |
603 | if (n < 0) {\r | |
604 | if (!PyErr_Occurred())\r | |
605 | PyErr_Format(PyExc_IOError,\r | |
606 | "Raw stream returned invalid position %" PY_PRIdOFF,\r | |
607 | (PY_OFF_T_COMPAT)n);\r | |
608 | return -1;\r | |
609 | }\r | |
610 | self->abs_pos = n;\r | |
611 | return n;\r | |
612 | }\r | |
613 | \r | |
614 | static Py_off_t\r | |
615 | _buffered_raw_seek(buffered *self, Py_off_t target, int whence)\r | |
616 | {\r | |
617 | PyObject *res, *posobj, *whenceobj;\r | |
618 | Py_off_t n;\r | |
619 | \r | |
620 | posobj = PyLong_FromOff_t(target);\r | |
621 | if (posobj == NULL)\r | |
622 | return -1;\r | |
623 | whenceobj = PyLong_FromLong(whence);\r | |
624 | if (whenceobj == NULL) {\r | |
625 | Py_DECREF(posobj);\r | |
626 | return -1;\r | |
627 | }\r | |
628 | res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,\r | |
629 | posobj, whenceobj, NULL);\r | |
630 | Py_DECREF(posobj);\r | |
631 | Py_DECREF(whenceobj);\r | |
632 | if (res == NULL)\r | |
633 | return -1;\r | |
634 | n = PyNumber_AsOff_t(res, PyExc_ValueError);\r | |
635 | Py_DECREF(res);\r | |
636 | if (n < 0) {\r | |
637 | if (!PyErr_Occurred())\r | |
638 | PyErr_Format(PyExc_IOError,\r | |
639 | "Raw stream returned invalid position %" PY_PRIdOFF,\r | |
640 | (PY_OFF_T_COMPAT)n);\r | |
641 | return -1;\r | |
642 | }\r | |
643 | self->abs_pos = n;\r | |
644 | return n;\r | |
645 | }\r | |
646 | \r | |
647 | static int\r | |
648 | _buffered_init(buffered *self)\r | |
649 | {\r | |
650 | Py_ssize_t n;\r | |
651 | if (self->buffer_size <= 0) {\r | |
652 | PyErr_SetString(PyExc_ValueError,\r | |
653 | "buffer size must be strictly positive");\r | |
654 | return -1;\r | |
655 | }\r | |
656 | if (self->buffer)\r | |
657 | PyMem_Free(self->buffer);\r | |
658 | self->buffer = PyMem_Malloc(self->buffer_size);\r | |
659 | if (self->buffer == NULL) {\r | |
660 | PyErr_NoMemory();\r | |
661 | return -1;\r | |
662 | }\r | |
663 | #ifdef WITH_THREAD\r | |
664 | if (self->lock)\r | |
665 | PyThread_free_lock(self->lock);\r | |
666 | self->lock = PyThread_allocate_lock();\r | |
667 | if (self->lock == NULL) {\r | |
668 | PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");\r | |
669 | return -1;\r | |
670 | }\r | |
671 | self->owner = 0;\r | |
672 | #endif\r | |
673 | /* Find out whether buffer_size is a power of 2 */\r | |
674 | /* XXX is this optimization useful? */\r | |
675 | for (n = self->buffer_size - 1; n & 1; n >>= 1)\r | |
676 | ;\r | |
677 | if (n == 0)\r | |
678 | self->buffer_mask = self->buffer_size - 1;\r | |
679 | else\r | |
680 | self->buffer_mask = 0;\r | |
681 | if (_buffered_raw_tell(self) == -1)\r | |
682 | PyErr_Clear();\r | |
683 | return 0;\r | |
684 | }\r | |
685 | \r | |
686 | /* Return 1 if an EnvironmentError with errno == EINTR is set (and then\r | |
687 | clears the error indicator), 0 otherwise.\r | |
688 | Should only be called when PyErr_Occurred() is true.\r | |
689 | */\r | |
690 | static int\r | |
691 | _trap_eintr(void)\r | |
692 | {\r | |
693 | static PyObject *eintr_int = NULL;\r | |
694 | PyObject *typ, *val, *tb;\r | |
695 | PyEnvironmentErrorObject *env_err;\r | |
696 | \r | |
697 | if (eintr_int == NULL) {\r | |
698 | eintr_int = PyLong_FromLong(EINTR);\r | |
699 | assert(eintr_int != NULL);\r | |
700 | }\r | |
701 | if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))\r | |
702 | return 0;\r | |
703 | PyErr_Fetch(&typ, &val, &tb);\r | |
704 | PyErr_NormalizeException(&typ, &val, &tb);\r | |
705 | env_err = (PyEnvironmentErrorObject *) val;\r | |
706 | assert(env_err != NULL);\r | |
707 | if (env_err->myerrno != NULL &&\r | |
708 | PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {\r | |
709 | Py_DECREF(typ);\r | |
710 | Py_DECREF(val);\r | |
711 | Py_XDECREF(tb);\r | |
712 | return 1;\r | |
713 | }\r | |
714 | /* This silences any error set by PyObject_RichCompareBool() */\r | |
715 | PyErr_Restore(typ, val, tb);\r | |
716 | return 0;\r | |
717 | }\r | |
718 | \r | |
719 | /*\r | |
720 | * Shared methods and wrappers\r | |
721 | */\r | |
722 | \r | |
723 | static PyObject *\r | |
724 | buffered_flush(buffered *self, PyObject *args)\r | |
725 | {\r | |
726 | PyObject *res;\r | |
727 | \r | |
728 | CHECK_INITIALIZED(self)\r | |
729 | CHECK_CLOSED(self, "flush of closed file")\r | |
730 | \r | |
731 | if (!ENTER_BUFFERED(self))\r | |
732 | return NULL;\r | |
733 | res = _bufferedwriter_flush_unlocked(self, 0);\r | |
734 | if (res != NULL && self->readable) {\r | |
735 | /* Rewind the raw stream so that its position corresponds to\r | |
736 | the current logical position. */\r | |
737 | Py_off_t n;\r | |
738 | n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);\r | |
739 | if (n == -1)\r | |
740 | Py_CLEAR(res);\r | |
741 | _bufferedreader_reset_buf(self);\r | |
742 | }\r | |
743 | LEAVE_BUFFERED(self)\r | |
744 | \r | |
745 | return res;\r | |
746 | }\r | |
747 | \r | |
748 | static PyObject *\r | |
749 | buffered_peek(buffered *self, PyObject *args)\r | |
750 | {\r | |
751 | Py_ssize_t n = 0;\r | |
752 | PyObject *res = NULL;\r | |
753 | \r | |
754 | CHECK_INITIALIZED(self)\r | |
755 | if (!PyArg_ParseTuple(args, "|n:peek", &n)) {\r | |
756 | return NULL;\r | |
757 | }\r | |
758 | \r | |
759 | if (!ENTER_BUFFERED(self))\r | |
760 | return NULL;\r | |
761 | \r | |
762 | if (self->writable) {\r | |
763 | res = _bufferedwriter_flush_unlocked(self, 1);\r | |
764 | if (res == NULL)\r | |
765 | goto end;\r | |
766 | Py_CLEAR(res);\r | |
767 | }\r | |
768 | res = _bufferedreader_peek_unlocked(self, n);\r | |
769 | \r | |
770 | end:\r | |
771 | LEAVE_BUFFERED(self)\r | |
772 | return res;\r | |
773 | }\r | |
774 | \r | |
775 | static PyObject *\r | |
776 | buffered_read(buffered *self, PyObject *args)\r | |
777 | {\r | |
778 | Py_ssize_t n = -1;\r | |
779 | PyObject *res;\r | |
780 | \r | |
781 | CHECK_INITIALIZED(self)\r | |
782 | if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {\r | |
783 | return NULL;\r | |
784 | }\r | |
785 | if (n < -1) {\r | |
786 | PyErr_SetString(PyExc_ValueError,\r | |
787 | "read length must be positive or -1");\r | |
788 | return NULL;\r | |
789 | }\r | |
790 | \r | |
791 | CHECK_CLOSED(self, "read of closed file")\r | |
792 | \r | |
793 | if (n == -1) {\r | |
794 | /* The number of bytes is unspecified, read until the end of stream */\r | |
795 | if (!ENTER_BUFFERED(self))\r | |
796 | return NULL;\r | |
797 | res = _bufferedreader_read_all(self);\r | |
798 | LEAVE_BUFFERED(self)\r | |
799 | }\r | |
800 | else {\r | |
801 | res = _bufferedreader_read_fast(self, n);\r | |
802 | if (res == Py_None) {\r | |
803 | Py_DECREF(res);\r | |
804 | if (!ENTER_BUFFERED(self))\r | |
805 | return NULL;\r | |
806 | res = _bufferedreader_read_generic(self, n);\r | |
807 | LEAVE_BUFFERED(self)\r | |
808 | }\r | |
809 | }\r | |
810 | \r | |
811 | return res;\r | |
812 | }\r | |
813 | \r | |
814 | static PyObject *\r | |
815 | buffered_read1(buffered *self, PyObject *args)\r | |
816 | {\r | |
817 | Py_ssize_t n, have, r;\r | |
818 | PyObject *res = NULL;\r | |
819 | \r | |
820 | CHECK_INITIALIZED(self)\r | |
821 | if (!PyArg_ParseTuple(args, "n:read1", &n)) {\r | |
822 | return NULL;\r | |
823 | }\r | |
824 | \r | |
825 | if (n < 0) {\r | |
826 | PyErr_SetString(PyExc_ValueError,\r | |
827 | "read length must be positive");\r | |
828 | return NULL;\r | |
829 | }\r | |
830 | if (n == 0)\r | |
831 | return PyBytes_FromStringAndSize(NULL, 0);\r | |
832 | \r | |
833 | if (!ENTER_BUFFERED(self))\r | |
834 | return NULL;\r | |
835 | \r | |
836 | if (self->writable) {\r | |
837 | res = _bufferedwriter_flush_unlocked(self, 1);\r | |
838 | if (res == NULL)\r | |
839 | goto end;\r | |
840 | Py_CLEAR(res);\r | |
841 | }\r | |
842 | \r | |
843 | /* Return up to n bytes. If at least one byte is buffered, we\r | |
844 | only return buffered bytes. Otherwise, we do one raw read. */\r | |
845 | \r | |
846 | /* XXX: this mimicks the io.py implementation but is probably wrong.\r | |
847 | If we need to read from the raw stream, then we could actually read\r | |
848 | all `n` bytes asked by the caller (and possibly more, so as to fill\r | |
849 | our buffer for the next reads). */\r | |
850 | \r | |
851 | have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);\r | |
852 | if (have > 0) {\r | |
853 | if (n > have)\r | |
854 | n = have;\r | |
855 | res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);\r | |
856 | if (res == NULL)\r | |
857 | goto end;\r | |
858 | self->pos += n;\r | |
859 | goto end;\r | |
860 | }\r | |
861 | \r | |
862 | /* Fill the buffer from the raw stream, and copy it to the result. */\r | |
863 | _bufferedreader_reset_buf(self);\r | |
864 | r = _bufferedreader_fill_buffer(self);\r | |
865 | if (r == -1)\r | |
866 | goto end;\r | |
867 | if (r == -2)\r | |
868 | r = 0;\r | |
869 | if (n > r)\r | |
870 | n = r;\r | |
871 | res = PyBytes_FromStringAndSize(self->buffer, n);\r | |
872 | if (res == NULL)\r | |
873 | goto end;\r | |
874 | self->pos = n;\r | |
875 | \r | |
876 | end:\r | |
877 | LEAVE_BUFFERED(self)\r | |
878 | return res;\r | |
879 | }\r | |
880 | \r | |
881 | static PyObject *\r | |
882 | buffered_readinto(buffered *self, PyObject *args)\r | |
883 | {\r | |
884 | PyObject *res = NULL;\r | |
885 | \r | |
886 | CHECK_INITIALIZED(self)\r | |
887 | \r | |
888 | /* TODO: use raw.readinto() instead! */\r | |
889 | if (self->writable) {\r | |
890 | if (!ENTER_BUFFERED(self))\r | |
891 | return NULL;\r | |
892 | res = _bufferedwriter_flush_unlocked(self, 0);\r | |
893 | LEAVE_BUFFERED(self)\r | |
894 | if (res == NULL)\r | |
895 | goto end;\r | |
896 | Py_DECREF(res);\r | |
897 | }\r | |
898 | res = bufferediobase_readinto((PyObject *)self, args);\r | |
899 | \r | |
900 | end:\r | |
901 | return res;\r | |
902 | }\r | |
903 | \r | |
904 | static PyObject *\r | |
905 | _buffered_readline(buffered *self, Py_ssize_t limit)\r | |
906 | {\r | |
907 | PyObject *res = NULL;\r | |
908 | PyObject *chunks = NULL;\r | |
909 | Py_ssize_t n, written = 0;\r | |
910 | const char *start, *s, *end;\r | |
911 | \r | |
912 | CHECK_CLOSED(self, "readline of closed file")\r | |
913 | \r | |
914 | /* First, try to find a line in the buffer. This can run unlocked because\r | |
915 | the calls to the C API are simple enough that they can't trigger\r | |
916 | any thread switch. */\r | |
917 | n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);\r | |
918 | if (limit >= 0 && n > limit)\r | |
919 | n = limit;\r | |
920 | start = self->buffer + self->pos;\r | |
921 | s = memchr(start, '\n', n);\r | |
922 | if (s != NULL) {\r | |
923 | res = PyBytes_FromStringAndSize(start, s - start + 1);\r | |
924 | if (res != NULL)\r | |
925 | self->pos += s - start + 1;\r | |
926 | goto end_unlocked;\r | |
927 | }\r | |
928 | if (n == limit) {\r | |
929 | res = PyBytes_FromStringAndSize(start, n);\r | |
930 | if (res != NULL)\r | |
931 | self->pos += n;\r | |
932 | goto end_unlocked;\r | |
933 | }\r | |
934 | \r | |
935 | if (!ENTER_BUFFERED(self))\r | |
936 | goto end_unlocked;\r | |
937 | \r | |
938 | /* Now we try to get some more from the raw stream */\r | |
939 | if (self->writable) {\r | |
940 | res = _bufferedwriter_flush_unlocked(self, 1);\r | |
941 | if (res == NULL)\r | |
942 | goto end;\r | |
943 | Py_CLEAR(res);\r | |
944 | }\r | |
945 | chunks = PyList_New(0);\r | |
946 | if (chunks == NULL)\r | |
947 | goto end;\r | |
948 | if (n > 0) {\r | |
949 | res = PyBytes_FromStringAndSize(start, n);\r | |
950 | if (res == NULL)\r | |
951 | goto end;\r | |
952 | if (PyList_Append(chunks, res) < 0) {\r | |
953 | Py_CLEAR(res);\r | |
954 | goto end;\r | |
955 | }\r | |
956 | Py_CLEAR(res);\r | |
957 | written += n;\r | |
958 | if (limit >= 0)\r | |
959 | limit -= n;\r | |
960 | }\r | |
961 | \r | |
962 | for (;;) {\r | |
963 | _bufferedreader_reset_buf(self);\r | |
964 | n = _bufferedreader_fill_buffer(self);\r | |
965 | if (n == -1)\r | |
966 | goto end;\r | |
967 | if (n <= 0)\r | |
968 | break;\r | |
969 | if (limit >= 0 && n > limit)\r | |
970 | n = limit;\r | |
971 | start = self->buffer;\r | |
972 | end = start + n;\r | |
973 | s = start;\r | |
974 | while (s < end) {\r | |
975 | if (*s++ == '\n') {\r | |
976 | res = PyBytes_FromStringAndSize(start, s - start);\r | |
977 | if (res == NULL)\r | |
978 | goto end;\r | |
979 | self->pos = s - start;\r | |
980 | goto found;\r | |
981 | }\r | |
982 | }\r | |
983 | res = PyBytes_FromStringAndSize(start, n);\r | |
984 | if (res == NULL)\r | |
985 | goto end;\r | |
986 | if (n == limit) {\r | |
987 | self->pos = n;\r | |
988 | break;\r | |
989 | }\r | |
990 | if (PyList_Append(chunks, res) < 0) {\r | |
991 | Py_CLEAR(res);\r | |
992 | goto end;\r | |
993 | }\r | |
994 | Py_CLEAR(res);\r | |
995 | written += n;\r | |
996 | if (limit >= 0)\r | |
997 | limit -= n;\r | |
998 | }\r | |
999 | found:\r | |
1000 | if (res != NULL && PyList_Append(chunks, res) < 0) {\r | |
1001 | Py_CLEAR(res);\r | |
1002 | goto end;\r | |
1003 | }\r | |
1004 | Py_CLEAR(res);\r | |
1005 | res = _PyBytes_Join(_PyIO_empty_bytes, chunks);\r | |
1006 | \r | |
1007 | end:\r | |
1008 | LEAVE_BUFFERED(self)\r | |
1009 | end_unlocked:\r | |
1010 | Py_XDECREF(chunks);\r | |
1011 | return res;\r | |
1012 | }\r | |
1013 | \r | |
1014 | static PyObject *\r | |
1015 | buffered_readline(buffered *self, PyObject *args)\r | |
1016 | {\r | |
1017 | Py_ssize_t limit = -1;\r | |
1018 | \r | |
1019 | CHECK_INITIALIZED(self)\r | |
1020 | if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))\r | |
1021 | return NULL;\r | |
1022 | return _buffered_readline(self, limit);\r | |
1023 | }\r | |
1024 | \r | |
1025 | \r | |
1026 | static PyObject *\r | |
1027 | buffered_tell(buffered *self, PyObject *args)\r | |
1028 | {\r | |
1029 | Py_off_t pos;\r | |
1030 | \r | |
1031 | CHECK_INITIALIZED(self)\r | |
1032 | pos = _buffered_raw_tell(self);\r | |
1033 | if (pos == -1)\r | |
1034 | return NULL;\r | |
1035 | pos -= RAW_OFFSET(self);\r | |
1036 | /* TODO: sanity check (pos >= 0) */\r | |
1037 | return PyLong_FromOff_t(pos);\r | |
1038 | }\r | |
1039 | \r | |
1040 | static PyObject *\r | |
1041 | buffered_seek(buffered *self, PyObject *args)\r | |
1042 | {\r | |
1043 | Py_off_t target, n;\r | |
1044 | int whence = 0;\r | |
1045 | PyObject *targetobj, *res = NULL;\r | |
1046 | \r | |
1047 | CHECK_INITIALIZED(self)\r | |
1048 | if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {\r | |
1049 | return NULL;\r | |
1050 | }\r | |
1051 | if (whence < 0 || whence > 2) {\r | |
1052 | PyErr_Format(PyExc_ValueError,\r | |
1053 | "whence must be between 0 and 2, not %d", whence);\r | |
1054 | return NULL;\r | |
1055 | }\r | |
1056 | \r | |
1057 | CHECK_CLOSED(self, "seek of closed file")\r | |
1058 | \r | |
1059 | target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);\r | |
1060 | if (target == -1 && PyErr_Occurred())\r | |
1061 | return NULL;\r | |
1062 | \r | |
1063 | if (whence != 2 && self->readable) {\r | |
1064 | Py_off_t current, avail;\r | |
1065 | /* Check if seeking leaves us inside the current buffer,\r | |
1066 | so as to return quickly if possible. Also, we needn't take the\r | |
1067 | lock in this fast path.\r | |
1068 | Don't know how to do that when whence == 2, though. */\r | |
1069 | /* NOTE: RAW_TELL() can release the GIL but the object is in a stable\r | |
1070 | state at this point. */\r | |
1071 | current = RAW_TELL(self);\r | |
1072 | avail = READAHEAD(self);\r | |
1073 | if (avail > 0) {\r | |
1074 | Py_off_t offset;\r | |
1075 | if (whence == 0)\r | |
1076 | offset = target - (current - RAW_OFFSET(self));\r | |
1077 | else\r | |
1078 | offset = target;\r | |
1079 | if (offset >= -self->pos && offset <= avail) {\r | |
1080 | self->pos += offset;\r | |
1081 | return PyLong_FromOff_t(current - avail + offset);\r | |
1082 | }\r | |
1083 | }\r | |
1084 | }\r | |
1085 | \r | |
1086 | if (!ENTER_BUFFERED(self))\r | |
1087 | return NULL;\r | |
1088 | \r | |
1089 | /* Fallback: invoke raw seek() method and clear buffer */\r | |
1090 | if (self->writable) {\r | |
1091 | res = _bufferedwriter_flush_unlocked(self, 0);\r | |
1092 | if (res == NULL)\r | |
1093 | goto end;\r | |
1094 | Py_CLEAR(res);\r | |
1095 | _bufferedwriter_reset_buf(self);\r | |
1096 | }\r | |
1097 | \r | |
1098 | /* TODO: align on block boundary and read buffer if needed? */\r | |
1099 | if (whence == 1)\r | |
1100 | target -= RAW_OFFSET(self);\r | |
1101 | n = _buffered_raw_seek(self, target, whence);\r | |
1102 | if (n == -1)\r | |
1103 | goto end;\r | |
1104 | self->raw_pos = -1;\r | |
1105 | res = PyLong_FromOff_t(n);\r | |
1106 | if (res != NULL && self->readable)\r | |
1107 | _bufferedreader_reset_buf(self);\r | |
1108 | \r | |
1109 | end:\r | |
1110 | LEAVE_BUFFERED(self)\r | |
1111 | return res;\r | |
1112 | }\r | |
1113 | \r | |
1114 | static PyObject *\r | |
1115 | buffered_truncate(buffered *self, PyObject *args)\r | |
1116 | {\r | |
1117 | PyObject *pos = Py_None;\r | |
1118 | PyObject *res = NULL;\r | |
1119 | \r | |
1120 | CHECK_INITIALIZED(self)\r | |
1121 | if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {\r | |
1122 | return NULL;\r | |
1123 | }\r | |
1124 | \r | |
1125 | if (!ENTER_BUFFERED(self))\r | |
1126 | return NULL;\r | |
1127 | \r | |
1128 | if (self->writable) {\r | |
1129 | res = _bufferedwriter_flush_unlocked(self, 0);\r | |
1130 | if (res == NULL)\r | |
1131 | goto end;\r | |
1132 | Py_CLEAR(res);\r | |
1133 | }\r | |
1134 | if (self->readable) {\r | |
1135 | if (pos == Py_None) {\r | |
1136 | /* Rewind the raw stream so that its position corresponds to\r | |
1137 | the current logical position. */\r | |
1138 | if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)\r | |
1139 | goto end;\r | |
1140 | }\r | |
1141 | _bufferedreader_reset_buf(self);\r | |
1142 | }\r | |
1143 | res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);\r | |
1144 | if (res == NULL)\r | |
1145 | goto end;\r | |
1146 | /* Reset cached position */\r | |
1147 | if (_buffered_raw_tell(self) == -1)\r | |
1148 | PyErr_Clear();\r | |
1149 | \r | |
1150 | end:\r | |
1151 | LEAVE_BUFFERED(self)\r | |
1152 | return res;\r | |
1153 | }\r | |
1154 | \r | |
1155 | static PyObject *\r | |
1156 | buffered_iternext(buffered *self)\r | |
1157 | {\r | |
1158 | PyObject *line;\r | |
1159 | PyTypeObject *tp;\r | |
1160 | \r | |
1161 | CHECK_INITIALIZED(self);\r | |
1162 | \r | |
1163 | tp = Py_TYPE(self);\r | |
1164 | if (tp == &PyBufferedReader_Type ||\r | |
1165 | tp == &PyBufferedRandom_Type) {\r | |
1166 | /* Skip method call overhead for speed */\r | |
1167 | line = _buffered_readline(self, -1);\r | |
1168 | }\r | |
1169 | else {\r | |
1170 | line = PyObject_CallMethodObjArgs((PyObject *)self,\r | |
1171 | _PyIO_str_readline, NULL);\r | |
1172 | if (line && !PyBytes_Check(line)) {\r | |
1173 | PyErr_Format(PyExc_IOError,\r | |
1174 | "readline() should have returned a bytes object, "\r | |
1175 | "not '%.200s'", Py_TYPE(line)->tp_name);\r | |
1176 | Py_DECREF(line);\r | |
1177 | return NULL;\r | |
1178 | }\r | |
1179 | }\r | |
1180 | \r | |
1181 | if (line == NULL)\r | |
1182 | return NULL;\r | |
1183 | \r | |
1184 | if (PyBytes_GET_SIZE(line) == 0) {\r | |
1185 | /* Reached EOF or would have blocked */\r | |
1186 | Py_DECREF(line);\r | |
1187 | return NULL;\r | |
1188 | }\r | |
1189 | \r | |
1190 | return line;\r | |
1191 | }\r | |
1192 | \r | |
1193 | static PyObject *\r | |
1194 | buffered_repr(buffered *self)\r | |
1195 | {\r | |
1196 | PyObject *nameobj, *res;\r | |
1197 | \r | |
1198 | nameobj = PyObject_GetAttrString((PyObject *) self, "name");\r | |
1199 | if (nameobj == NULL) {\r | |
1200 | if (PyErr_ExceptionMatches(PyExc_AttributeError))\r | |
1201 | PyErr_Clear();\r | |
1202 | else\r | |
1203 | return NULL;\r | |
1204 | res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);\r | |
1205 | }\r | |
1206 | else {\r | |
1207 | PyObject *repr = PyObject_Repr(nameobj);\r | |
1208 | Py_DECREF(nameobj);\r | |
1209 | if (repr == NULL)\r | |
1210 | return NULL;\r | |
1211 | res = PyString_FromFormat("<%s name=%s>",\r | |
1212 | Py_TYPE(self)->tp_name,\r | |
1213 | PyString_AS_STRING(repr));\r | |
1214 | Py_DECREF(repr);\r | |
1215 | }\r | |
1216 | return res;\r | |
1217 | }\r | |
1218 | \r | |
1219 | /*\r | |
1220 | * class BufferedReader\r | |
1221 | */\r | |
1222 | \r | |
1223 | PyDoc_STRVAR(bufferedreader_doc,\r | |
1224 | "Create a new buffered reader using the given readable raw IO object.");\r | |
1225 | \r | |
1226 | static void _bufferedreader_reset_buf(buffered *self)\r | |
1227 | {\r | |
1228 | self->read_end = -1;\r | |
1229 | }\r | |
1230 | \r | |
1231 | static int\r | |
1232 | bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)\r | |
1233 | {\r | |
1234 | char *kwlist[] = {"raw", "buffer_size", NULL};\r | |
1235 | Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;\r | |
1236 | PyObject *raw;\r | |
1237 | \r | |
1238 | self->ok = 0;\r | |
1239 | self->detached = 0;\r | |
1240 | \r | |
1241 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,\r | |
1242 | &raw, &buffer_size)) {\r | |
1243 | return -1;\r | |
1244 | }\r | |
1245 | \r | |
1246 | if (_PyIOBase_check_readable(raw, Py_True) == NULL)\r | |
1247 | return -1;\r | |
1248 | \r | |
1249 | Py_CLEAR(self->raw);\r | |
1250 | Py_INCREF(raw);\r | |
1251 | self->raw = raw;\r | |
1252 | self->buffer_size = buffer_size;\r | |
1253 | self->readable = 1;\r | |
1254 | self->writable = 0;\r | |
1255 | \r | |
1256 | if (_buffered_init(self) < 0)\r | |
1257 | return -1;\r | |
1258 | _bufferedreader_reset_buf(self);\r | |
1259 | \r | |
1260 | self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&\r | |
1261 | Py_TYPE(raw) == &PyFileIO_Type);\r | |
1262 | \r | |
1263 | self->ok = 1;\r | |
1264 | return 0;\r | |
1265 | }\r | |
1266 | \r | |
1267 | static Py_ssize_t\r | |
1268 | _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)\r | |
1269 | {\r | |
1270 | Py_buffer buf;\r | |
1271 | PyObject *memobj, *res;\r | |
1272 | Py_ssize_t n;\r | |
1273 | /* NOTE: the buffer needn't be released as its object is NULL. */\r | |
1274 | if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)\r | |
1275 | return -1;\r | |
1276 | memobj = PyMemoryView_FromBuffer(&buf);\r | |
1277 | if (memobj == NULL)\r | |
1278 | return -1;\r | |
1279 | /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR\r | |
1280 | occurs so we needn't do it ourselves.\r | |
1281 | We then retry reading, ignoring the signal if no handler has\r | |
1282 | raised (see issue #10956).\r | |
1283 | */\r | |
1284 | do {\r | |
1285 | res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);\r | |
1286 | } while (res == NULL && _trap_eintr());\r | |
1287 | Py_DECREF(memobj);\r | |
1288 | if (res == NULL)\r | |
1289 | return -1;\r | |
1290 | if (res == Py_None) {\r | |
1291 | /* Non-blocking stream would have blocked. Special return code! */\r | |
1292 | Py_DECREF(res);\r | |
1293 | return -2;\r | |
1294 | }\r | |
1295 | n = PyNumber_AsSsize_t(res, PyExc_ValueError);\r | |
1296 | Py_DECREF(res);\r | |
1297 | if (n < 0 || n > len) {\r | |
1298 | PyErr_Format(PyExc_IOError,\r | |
1299 | "raw readinto() returned invalid length %zd "\r | |
1300 | "(should have been between 0 and %zd)", n, len);\r | |
1301 | return -1;\r | |
1302 | }\r | |
1303 | if (n > 0 && self->abs_pos != -1)\r | |
1304 | self->abs_pos += n;\r | |
1305 | return n;\r | |
1306 | }\r | |
1307 | \r | |
1308 | static Py_ssize_t\r | |
1309 | _bufferedreader_fill_buffer(buffered *self)\r | |
1310 | {\r | |
1311 | Py_ssize_t start, len, n;\r | |
1312 | if (VALID_READ_BUFFER(self))\r | |
1313 | start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);\r | |
1314 | else\r | |
1315 | start = 0;\r | |
1316 | len = self->buffer_size - start;\r | |
1317 | n = _bufferedreader_raw_read(self, self->buffer + start, len);\r | |
1318 | if (n <= 0)\r | |
1319 | return n;\r | |
1320 | self->read_end = start + n;\r | |
1321 | self->raw_pos = start + n;\r | |
1322 | return n;\r | |
1323 | }\r | |
1324 | \r | |
1325 | static PyObject *\r | |
1326 | _bufferedreader_read_all(buffered *self)\r | |
1327 | {\r | |
1328 | Py_ssize_t current_size;\r | |
1329 | PyObject *res, *data = NULL;\r | |
1330 | PyObject *chunks = PyList_New(0);\r | |
1331 | \r | |
1332 | if (chunks == NULL)\r | |
1333 | return NULL;\r | |
1334 | \r | |
1335 | /* First copy what we have in the current buffer. */\r | |
1336 | current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);\r | |
1337 | if (current_size) {\r | |
1338 | data = PyBytes_FromStringAndSize(\r | |
1339 | self->buffer + self->pos, current_size);\r | |
1340 | if (data == NULL) {\r | |
1341 | Py_DECREF(chunks);\r | |
1342 | return NULL;\r | |
1343 | }\r | |
1344 | }\r | |
1345 | _bufferedreader_reset_buf(self);\r | |
1346 | /* We're going past the buffer's bounds, flush it */\r | |
1347 | if (self->writable) {\r | |
1348 | res = _bufferedwriter_flush_unlocked(self, 1);\r | |
1349 | if (res == NULL) {\r | |
1350 | Py_DECREF(chunks);\r | |
1351 | return NULL;\r | |
1352 | }\r | |
1353 | Py_CLEAR(res);\r | |
1354 | }\r | |
1355 | while (1) {\r | |
1356 | if (data) {\r | |
1357 | if (PyList_Append(chunks, data) < 0) {\r | |
1358 | Py_DECREF(data);\r | |
1359 | Py_DECREF(chunks);\r | |
1360 | return NULL;\r | |
1361 | }\r | |
1362 | Py_DECREF(data);\r | |
1363 | }\r | |
1364 | \r | |
1365 | /* Read until EOF or until read() would block. */\r | |
1366 | data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);\r | |
1367 | if (data == NULL) {\r | |
1368 | Py_DECREF(chunks);\r | |
1369 | return NULL;\r | |
1370 | }\r | |
1371 | if (data != Py_None && !PyBytes_Check(data)) {\r | |
1372 | Py_DECREF(data);\r | |
1373 | Py_DECREF(chunks);\r | |
1374 | PyErr_SetString(PyExc_TypeError, "read() should return bytes");\r | |
1375 | return NULL;\r | |
1376 | }\r | |
1377 | if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {\r | |
1378 | if (current_size == 0) {\r | |
1379 | Py_DECREF(chunks);\r | |
1380 | return data;\r | |
1381 | }\r | |
1382 | else {\r | |
1383 | res = _PyBytes_Join(_PyIO_empty_bytes, chunks);\r | |
1384 | Py_DECREF(data);\r | |
1385 | Py_DECREF(chunks);\r | |
1386 | return res;\r | |
1387 | }\r | |
1388 | }\r | |
1389 | current_size += PyBytes_GET_SIZE(data);\r | |
1390 | if (self->abs_pos != -1)\r | |
1391 | self->abs_pos += PyBytes_GET_SIZE(data);\r | |
1392 | }\r | |
1393 | }\r | |
1394 | \r | |
1395 | /* Read n bytes from the buffer if it can, otherwise return None.\r | |
1396 | This function is simple enough that it can run unlocked. */\r | |
1397 | static PyObject *\r | |
1398 | _bufferedreader_read_fast(buffered *self, Py_ssize_t n)\r | |
1399 | {\r | |
1400 | Py_ssize_t current_size;\r | |
1401 | \r | |
1402 | current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);\r | |
1403 | if (n <= current_size) {\r | |
1404 | /* Fast path: the data to read is fully buffered. */\r | |
1405 | PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);\r | |
1406 | if (res != NULL)\r | |
1407 | self->pos += n;\r | |
1408 | return res;\r | |
1409 | }\r | |
1410 | Py_RETURN_NONE;\r | |
1411 | }\r | |
1412 | \r | |
1413 | /* Generic read function: read from the stream until enough bytes are read,\r | |
1414 | * or until an EOF occurs or until read() would block.\r | |
1415 | */\r | |
1416 | static PyObject *\r | |
1417 | _bufferedreader_read_generic(buffered *self, Py_ssize_t n)\r | |
1418 | {\r | |
1419 | PyObject *res = NULL;\r | |
1420 | Py_ssize_t current_size, remaining, written;\r | |
1421 | char *out;\r | |
1422 | \r | |
1423 | current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);\r | |
1424 | if (n <= current_size)\r | |
1425 | return _bufferedreader_read_fast(self, n);\r | |
1426 | \r | |
1427 | res = PyBytes_FromStringAndSize(NULL, n);\r | |
1428 | if (res == NULL)\r | |
1429 | goto error;\r | |
1430 | out = PyBytes_AS_STRING(res);\r | |
1431 | remaining = n;\r | |
1432 | written = 0;\r | |
1433 | if (current_size > 0) {\r | |
1434 | memcpy(out, self->buffer + self->pos, current_size);\r | |
1435 | remaining -= current_size;\r | |
1436 | written += current_size;\r | |
1437 | }\r | |
1438 | _bufferedreader_reset_buf(self);\r | |
1439 | while (remaining > 0) {\r | |
1440 | /* We want to read a whole block at the end into buffer.\r | |
1441 | If we had readv() we could do this in one pass. */\r | |
1442 | Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);\r | |
1443 | if (r == 0)\r | |
1444 | break;\r | |
1445 | r = _bufferedreader_raw_read(self, out + written, r);\r | |
1446 | if (r == -1)\r | |
1447 | goto error;\r | |
1448 | if (r == 0 || r == -2) {\r | |
1449 | /* EOF occurred or read() would block. */\r | |
1450 | if (r == 0 || written > 0) {\r | |
1451 | if (_PyBytes_Resize(&res, written))\r | |
1452 | goto error;\r | |
1453 | return res;\r | |
1454 | }\r | |
1455 | Py_DECREF(res);\r | |
1456 | Py_INCREF(Py_None);\r | |
1457 | return Py_None;\r | |
1458 | }\r | |
1459 | remaining -= r;\r | |
1460 | written += r;\r | |
1461 | }\r | |
1462 | assert(remaining <= self->buffer_size);\r | |
1463 | self->pos = 0;\r | |
1464 | self->raw_pos = 0;\r | |
1465 | self->read_end = 0;\r | |
1466 | /* NOTE: when the read is satisfied, we avoid issuing any additional\r | |
1467 | reads, which could block indefinitely (e.g. on a socket).\r | |
1468 | See issue #9550. */\r | |
1469 | while (remaining > 0 && self->read_end < self->buffer_size) {\r | |
1470 | Py_ssize_t r = _bufferedreader_fill_buffer(self);\r | |
1471 | if (r == -1)\r | |
1472 | goto error;\r | |
1473 | if (r == 0 || r == -2) {\r | |
1474 | /* EOF occurred or read() would block. */\r | |
1475 | if (r == 0 || written > 0) {\r | |
1476 | if (_PyBytes_Resize(&res, written))\r | |
1477 | goto error;\r | |
1478 | return res;\r | |
1479 | }\r | |
1480 | Py_DECREF(res);\r | |
1481 | Py_INCREF(Py_None);\r | |
1482 | return Py_None;\r | |
1483 | }\r | |
1484 | if (remaining > r) {\r | |
1485 | memcpy(out + written, self->buffer + self->pos, r);\r | |
1486 | written += r;\r | |
1487 | self->pos += r;\r | |
1488 | remaining -= r;\r | |
1489 | }\r | |
1490 | else if (remaining > 0) {\r | |
1491 | memcpy(out + written, self->buffer + self->pos, remaining);\r | |
1492 | written += remaining;\r | |
1493 | self->pos += remaining;\r | |
1494 | remaining = 0;\r | |
1495 | }\r | |
1496 | if (remaining == 0)\r | |
1497 | break;\r | |
1498 | }\r | |
1499 | \r | |
1500 | return res;\r | |
1501 | \r | |
1502 | error:\r | |
1503 | Py_XDECREF(res);\r | |
1504 | return NULL;\r | |
1505 | }\r | |
1506 | \r | |
1507 | static PyObject *\r | |
1508 | _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)\r | |
1509 | {\r | |
1510 | Py_ssize_t have, r;\r | |
1511 | \r | |
1512 | have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);\r | |
1513 | /* Constraints:\r | |
1514 | 1. we don't want to advance the file position.\r | |
1515 | 2. we don't want to lose block alignment, so we can't shift the buffer\r | |
1516 | to make some place.\r | |
1517 | Therefore, we either return `have` bytes (if > 0), or a full buffer.\r | |
1518 | */\r | |
1519 | if (have > 0) {\r | |
1520 | return PyBytes_FromStringAndSize(self->buffer + self->pos, have);\r | |
1521 | }\r | |
1522 | \r | |
1523 | /* Fill the buffer from the raw stream, and copy it to the result. */\r | |
1524 | _bufferedreader_reset_buf(self);\r | |
1525 | r = _bufferedreader_fill_buffer(self);\r | |
1526 | if (r == -1)\r | |
1527 | return NULL;\r | |
1528 | if (r == -2)\r | |
1529 | r = 0;\r | |
1530 | self->pos = 0;\r | |
1531 | return PyBytes_FromStringAndSize(self->buffer, r);\r | |
1532 | }\r | |
1533 | \r | |
1534 | static PyMethodDef bufferedreader_methods[] = {\r | |
1535 | /* BufferedIOMixin methods */\r | |
1536 | {"detach", (PyCFunction)buffered_detach, METH_NOARGS},\r | |
1537 | {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},\r | |
1538 | {"close", (PyCFunction)buffered_close, METH_NOARGS},\r | |
1539 | {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},\r | |
1540 | {"readable", (PyCFunction)buffered_readable, METH_NOARGS},\r | |
1541 | {"writable", (PyCFunction)buffered_writable, METH_NOARGS},\r | |
1542 | {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},\r | |
1543 | {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},\r | |
1544 | \r | |
1545 | {"read", (PyCFunction)buffered_read, METH_VARARGS},\r | |
1546 | {"peek", (PyCFunction)buffered_peek, METH_VARARGS},\r | |
1547 | {"read1", (PyCFunction)buffered_read1, METH_VARARGS},\r | |
1548 | {"readline", (PyCFunction)buffered_readline, METH_VARARGS},\r | |
1549 | {"seek", (PyCFunction)buffered_seek, METH_VARARGS},\r | |
1550 | {"tell", (PyCFunction)buffered_tell, METH_NOARGS},\r | |
1551 | {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},\r | |
1552 | {NULL, NULL}\r | |
1553 | };\r | |
1554 | \r | |
1555 | static PyMemberDef bufferedreader_members[] = {\r | |
1556 | {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},\r | |
1557 | {NULL}\r | |
1558 | };\r | |
1559 | \r | |
1560 | static PyGetSetDef bufferedreader_getset[] = {\r | |
1561 | {"closed", (getter)buffered_closed_get, NULL, NULL},\r | |
1562 | {"name", (getter)buffered_name_get, NULL, NULL},\r | |
1563 | {"mode", (getter)buffered_mode_get, NULL, NULL},\r | |
1564 | {NULL}\r | |
1565 | };\r | |
1566 | \r | |
1567 | \r | |
1568 | PyTypeObject PyBufferedReader_Type = {\r | |
1569 | PyVarObject_HEAD_INIT(NULL, 0)\r | |
1570 | "_io.BufferedReader", /*tp_name*/\r | |
1571 | sizeof(buffered), /*tp_basicsize*/\r | |
1572 | 0, /*tp_itemsize*/\r | |
1573 | (destructor)buffered_dealloc, /*tp_dealloc*/\r | |
1574 | 0, /*tp_print*/\r | |
1575 | 0, /*tp_getattr*/\r | |
1576 | 0, /*tp_setattr*/\r | |
1577 | 0, /*tp_compare */\r | |
1578 | (reprfunc)buffered_repr, /*tp_repr*/\r | |
1579 | 0, /*tp_as_number*/\r | |
1580 | 0, /*tp_as_sequence*/\r | |
1581 | 0, /*tp_as_mapping*/\r | |
1582 | 0, /*tp_hash */\r | |
1583 | 0, /*tp_call*/\r | |
1584 | 0, /*tp_str*/\r | |
1585 | 0, /*tp_getattro*/\r | |
1586 | 0, /*tp_setattro*/\r | |
1587 | 0, /*tp_as_buffer*/\r | |
1588 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE\r | |
1589 | | Py_TPFLAGS_HAVE_GC, /*tp_flags*/\r | |
1590 | bufferedreader_doc, /* tp_doc */\r | |
1591 | (traverseproc)buffered_traverse, /* tp_traverse */\r | |
1592 | (inquiry)buffered_clear, /* tp_clear */\r | |
1593 | 0, /* tp_richcompare */\r | |
1594 | offsetof(buffered, weakreflist), /*tp_weaklistoffset*/\r | |
1595 | 0, /* tp_iter */\r | |
1596 | (iternextfunc)buffered_iternext, /* tp_iternext */\r | |
1597 | bufferedreader_methods, /* tp_methods */\r | |
1598 | bufferedreader_members, /* tp_members */\r | |
1599 | bufferedreader_getset, /* tp_getset */\r | |
1600 | 0, /* tp_base */\r | |
1601 | 0, /* tp_dict */\r | |
1602 | 0, /* tp_descr_get */\r | |
1603 | 0, /* tp_descr_set */\r | |
1604 | offsetof(buffered, dict), /* tp_dictoffset */\r | |
1605 | (initproc)bufferedreader_init, /* tp_init */\r | |
1606 | 0, /* tp_alloc */\r | |
1607 | PyType_GenericNew, /* tp_new */\r | |
1608 | };\r | |
1609 | \f\r | |
1610 | \r | |
1611 | \r | |
1612 | static int\r | |
1613 | complain_about_max_buffer_size(void)\r | |
1614 | {\r | |
1615 | if (PyErr_WarnEx(PyExc_DeprecationWarning,\r | |
1616 | "max_buffer_size is deprecated", 1) < 0)\r | |
1617 | return 0;\r | |
1618 | return 1;\r | |
1619 | }\r | |
1620 | \r | |
1621 | /*\r | |
1622 | * class BufferedWriter\r | |
1623 | */\r | |
1624 | PyDoc_STRVAR(bufferedwriter_doc,\r | |
1625 | "A buffer for a writeable sequential RawIO object.\n"\r | |
1626 | "\n"\r | |
1627 | "The constructor creates a BufferedWriter for the given writeable raw\n"\r | |
1628 | "stream. If the buffer_size is not given, it defaults to\n"\r | |
1629 | "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"\r | |
1630 | );\r | |
1631 | \r | |
1632 | static void\r | |
1633 | _bufferedwriter_reset_buf(buffered *self)\r | |
1634 | {\r | |
1635 | self->write_pos = 0;\r | |
1636 | self->write_end = -1;\r | |
1637 | }\r | |
1638 | \r | |
1639 | static int\r | |
1640 | bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)\r | |
1641 | {\r | |
1642 | /* TODO: properly deprecate max_buffer_size */\r | |
1643 | char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};\r | |
1644 | Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;\r | |
1645 | Py_ssize_t max_buffer_size = -234;\r | |
1646 | PyObject *raw;\r | |
1647 | \r | |
1648 | self->ok = 0;\r | |
1649 | self->detached = 0;\r | |
1650 | \r | |
1651 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,\r | |
1652 | &raw, &buffer_size, &max_buffer_size)) {\r | |
1653 | return -1;\r | |
1654 | }\r | |
1655 | \r | |
1656 | if (max_buffer_size != -234 && !complain_about_max_buffer_size())\r | |
1657 | return -1;\r | |
1658 | \r | |
1659 | if (_PyIOBase_check_writable(raw, Py_True) == NULL)\r | |
1660 | return -1;\r | |
1661 | \r | |
1662 | Py_CLEAR(self->raw);\r | |
1663 | Py_INCREF(raw);\r | |
1664 | self->raw = raw;\r | |
1665 | self->readable = 0;\r | |
1666 | self->writable = 1;\r | |
1667 | \r | |
1668 | self->buffer_size = buffer_size;\r | |
1669 | if (_buffered_init(self) < 0)\r | |
1670 | return -1;\r | |
1671 | _bufferedwriter_reset_buf(self);\r | |
1672 | self->pos = 0;\r | |
1673 | \r | |
1674 | self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&\r | |
1675 | Py_TYPE(raw) == &PyFileIO_Type);\r | |
1676 | \r | |
1677 | self->ok = 1;\r | |
1678 | return 0;\r | |
1679 | }\r | |
1680 | \r | |
1681 | static Py_ssize_t\r | |
1682 | _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)\r | |
1683 | {\r | |
1684 | Py_buffer buf;\r | |
1685 | PyObject *memobj, *res;\r | |
1686 | Py_ssize_t n;\r | |
1687 | /* NOTE: the buffer needn't be released as its object is NULL. */\r | |
1688 | if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)\r | |
1689 | return -1;\r | |
1690 | memobj = PyMemoryView_FromBuffer(&buf);\r | |
1691 | if (memobj == NULL)\r | |
1692 | return -1;\r | |
1693 | /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR\r | |
1694 | occurs so we needn't do it ourselves.\r | |
1695 | We then retry writing, ignoring the signal if no handler has\r | |
1696 | raised (see issue #10956).\r | |
1697 | */\r | |
1698 | do {\r | |
1699 | res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);\r | |
1700 | } while (res == NULL && _trap_eintr());\r | |
1701 | Py_DECREF(memobj);\r | |
1702 | if (res == NULL)\r | |
1703 | return -1;\r | |
1704 | n = PyNumber_AsSsize_t(res, PyExc_ValueError);\r | |
1705 | Py_DECREF(res);\r | |
1706 | if (n < 0 || n > len) {\r | |
1707 | PyErr_Format(PyExc_IOError,\r | |
1708 | "raw write() returned invalid length %zd "\r | |
1709 | "(should have been between 0 and %zd)", n, len);\r | |
1710 | return -1;\r | |
1711 | }\r | |
1712 | if (n > 0 && self->abs_pos != -1)\r | |
1713 | self->abs_pos += n;\r | |
1714 | return n;\r | |
1715 | }\r | |
1716 | \r | |
1717 | /* `restore_pos` is 1 if we need to restore the raw stream position at\r | |
1718 | the end, 0 otherwise. */\r | |
1719 | static PyObject *\r | |
1720 | _bufferedwriter_flush_unlocked(buffered *self, int restore_pos)\r | |
1721 | {\r | |
1722 | Py_ssize_t written = 0;\r | |
1723 | Py_off_t n, rewind;\r | |
1724 | \r | |
1725 | if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)\r | |
1726 | goto end;\r | |
1727 | /* First, rewind */\r | |
1728 | rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);\r | |
1729 | if (rewind != 0) {\r | |
1730 | n = _buffered_raw_seek(self, -rewind, 1);\r | |
1731 | if (n < 0) {\r | |
1732 | goto error;\r | |
1733 | }\r | |
1734 | self->raw_pos -= rewind;\r | |
1735 | }\r | |
1736 | while (self->write_pos < self->write_end) {\r | |
1737 | n = _bufferedwriter_raw_write(self,\r | |
1738 | self->buffer + self->write_pos,\r | |
1739 | Py_SAFE_DOWNCAST(self->write_end - self->write_pos,\r | |
1740 | Py_off_t, Py_ssize_t));\r | |
1741 | if (n == -1) {\r | |
1742 | Py_ssize_t *w = _buffered_check_blocking_error();\r | |
1743 | if (w == NULL)\r | |
1744 | goto error;\r | |
1745 | self->write_pos += *w;\r | |
1746 | self->raw_pos = self->write_pos;\r | |
1747 | written += *w;\r | |
1748 | *w = written;\r | |
1749 | /* Already re-raised */\r | |
1750 | goto error;\r | |
1751 | }\r | |
1752 | self->write_pos += n;\r | |
1753 | self->raw_pos = self->write_pos;\r | |
1754 | written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);\r | |
1755 | /* Partial writes can return successfully when interrupted by a\r | |
1756 | signal (see write(2)). We must run signal handlers before\r | |
1757 | blocking another time, possibly indefinitely. */\r | |
1758 | if (PyErr_CheckSignals() < 0)\r | |
1759 | goto error;\r | |
1760 | }\r | |
1761 | \r | |
1762 | if (restore_pos) {\r | |
1763 | Py_off_t forward = rewind - written;\r | |
1764 | if (forward != 0) {\r | |
1765 | n = _buffered_raw_seek(self, forward, 1);\r | |
1766 | if (n < 0) {\r | |
1767 | goto error;\r | |
1768 | }\r | |
1769 | self->raw_pos += forward;\r | |
1770 | }\r | |
1771 | }\r | |
1772 | _bufferedwriter_reset_buf(self);\r | |
1773 | \r | |
1774 | end:\r | |
1775 | Py_RETURN_NONE;\r | |
1776 | \r | |
1777 | error:\r | |
1778 | return NULL;\r | |
1779 | }\r | |
1780 | \r | |
1781 | static PyObject *\r | |
1782 | bufferedwriter_write(buffered *self, PyObject *args)\r | |
1783 | {\r | |
1784 | PyObject *res = NULL;\r | |
1785 | Py_buffer buf;\r | |
1786 | Py_ssize_t written, avail, remaining;\r | |
1787 | Py_off_t offset;\r | |
1788 | \r | |
1789 | CHECK_INITIALIZED(self)\r | |
1790 | if (!PyArg_ParseTuple(args, "s*:write", &buf)) {\r | |
1791 | return NULL;\r | |
1792 | }\r | |
1793 | \r | |
1794 | if (IS_CLOSED(self)) {\r | |
1795 | PyErr_SetString(PyExc_ValueError, "write to closed file");\r | |
1796 | PyBuffer_Release(&buf);\r | |
1797 | return NULL;\r | |
1798 | }\r | |
1799 | \r | |
1800 | if (!ENTER_BUFFERED(self)) {\r | |
1801 | PyBuffer_Release(&buf);\r | |
1802 | return NULL;\r | |
1803 | }\r | |
1804 | \r | |
1805 | /* Fast path: the data to write can be fully buffered. */\r | |
1806 | if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {\r | |
1807 | self->pos = 0;\r | |
1808 | self->raw_pos = 0;\r | |
1809 | }\r | |
1810 | avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);\r | |
1811 | if (buf.len <= avail) {\r | |
1812 | memcpy(self->buffer + self->pos, buf.buf, buf.len);\r | |
1813 | if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {\r | |
1814 | self->write_pos = self->pos;\r | |
1815 | }\r | |
1816 | ADJUST_POSITION(self, self->pos + buf.len);\r | |
1817 | if (self->pos > self->write_end)\r | |
1818 | self->write_end = self->pos;\r | |
1819 | written = buf.len;\r | |
1820 | goto end;\r | |
1821 | }\r | |
1822 | \r | |
1823 | /* First write the current buffer */\r | |
1824 | res = _bufferedwriter_flush_unlocked(self, 0);\r | |
1825 | if (res == NULL) {\r | |
1826 | Py_ssize_t *w = _buffered_check_blocking_error();\r | |
1827 | if (w == NULL)\r | |
1828 | goto error;\r | |
1829 | if (self->readable)\r | |
1830 | _bufferedreader_reset_buf(self);\r | |
1831 | /* Make some place by shifting the buffer. */\r | |
1832 | assert(VALID_WRITE_BUFFER(self));\r | |
1833 | memmove(self->buffer, self->buffer + self->write_pos,\r | |
1834 | Py_SAFE_DOWNCAST(self->write_end - self->write_pos,\r | |
1835 | Py_off_t, Py_ssize_t));\r | |
1836 | self->write_end -= self->write_pos;\r | |
1837 | self->raw_pos -= self->write_pos;\r | |
1838 | self->pos -= self->write_pos;\r | |
1839 | self->write_pos = 0;\r | |
1840 | avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,\r | |
1841 | Py_off_t, Py_ssize_t);\r | |
1842 | if (buf.len <= avail) {\r | |
1843 | /* Everything can be buffered */\r | |
1844 | PyErr_Clear();\r | |
1845 | memcpy(self->buffer + self->write_end, buf.buf, buf.len);\r | |
1846 | self->write_end += buf.len;\r | |
1847 | written = buf.len;\r | |
1848 | goto end;\r | |
1849 | }\r | |
1850 | /* Buffer as much as possible. */\r | |
1851 | memcpy(self->buffer + self->write_end, buf.buf, avail);\r | |
1852 | self->write_end += avail;\r | |
1853 | /* Already re-raised */\r | |
1854 | *w = avail;\r | |
1855 | goto error;\r | |
1856 | }\r | |
1857 | Py_CLEAR(res);\r | |
1858 | \r | |
1859 | /* Adjust the raw stream position if it is away from the logical stream\r | |
1860 | position. This happens if the read buffer has been filled but not\r | |
1861 | modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind\r | |
1862 | the raw stream by itself).\r | |
1863 | Fixes issue #6629.\r | |
1864 | */\r | |
1865 | offset = RAW_OFFSET(self);\r | |
1866 | if (offset != 0) {\r | |
1867 | if (_buffered_raw_seek(self, -offset, 1) < 0)\r | |
1868 | goto error;\r | |
1869 | self->raw_pos -= offset;\r | |
1870 | }\r | |
1871 | \r | |
1872 | /* Then write buf itself. At this point the buffer has been emptied. */\r | |
1873 | remaining = buf.len;\r | |
1874 | written = 0;\r | |
1875 | while (remaining > self->buffer_size) {\r | |
1876 | Py_ssize_t n = _bufferedwriter_raw_write(\r | |
1877 | self, (char *) buf.buf + written, buf.len - written);\r | |
1878 | if (n == -1) {\r | |
1879 | Py_ssize_t *w = _buffered_check_blocking_error();\r | |
1880 | if (w == NULL)\r | |
1881 | goto error;\r | |
1882 | written += *w;\r | |
1883 | remaining -= *w;\r | |
1884 | if (remaining > self->buffer_size) {\r | |
1885 | /* Can't buffer everything, still buffer as much as possible */\r | |
1886 | memcpy(self->buffer,\r | |
1887 | (char *) buf.buf + written, self->buffer_size);\r | |
1888 | self->raw_pos = 0;\r | |
1889 | ADJUST_POSITION(self, self->buffer_size);\r | |
1890 | self->write_end = self->buffer_size;\r | |
1891 | *w = written + self->buffer_size;\r | |
1892 | /* Already re-raised */\r | |
1893 | goto error;\r | |
1894 | }\r | |
1895 | PyErr_Clear();\r | |
1896 | break;\r | |
1897 | }\r | |
1898 | written += n;\r | |
1899 | remaining -= n;\r | |
1900 | /* Partial writes can return successfully when interrupted by a\r | |
1901 | signal (see write(2)). We must run signal handlers before\r | |
1902 | blocking another time, possibly indefinitely. */\r | |
1903 | if (PyErr_CheckSignals() < 0)\r | |
1904 | goto error;\r | |
1905 | }\r | |
1906 | if (self->readable)\r | |
1907 | _bufferedreader_reset_buf(self);\r | |
1908 | if (remaining > 0) {\r | |
1909 | memcpy(self->buffer, (char *) buf.buf + written, remaining);\r | |
1910 | written += remaining;\r | |
1911 | }\r | |
1912 | self->write_pos = 0;\r | |
1913 | /* TODO: sanity check (remaining >= 0) */\r | |
1914 | self->write_end = remaining;\r | |
1915 | ADJUST_POSITION(self, remaining);\r | |
1916 | self->raw_pos = 0;\r | |
1917 | \r | |
1918 | end:\r | |
1919 | res = PyLong_FromSsize_t(written);\r | |
1920 | \r | |
1921 | error:\r | |
1922 | LEAVE_BUFFERED(self)\r | |
1923 | PyBuffer_Release(&buf);\r | |
1924 | return res;\r | |
1925 | }\r | |
1926 | \r | |
1927 | static PyMethodDef bufferedwriter_methods[] = {\r | |
1928 | /* BufferedIOMixin methods */\r | |
1929 | {"close", (PyCFunction)buffered_close, METH_NOARGS},\r | |
1930 | {"detach", (PyCFunction)buffered_detach, METH_NOARGS},\r | |
1931 | {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},\r | |
1932 | {"readable", (PyCFunction)buffered_readable, METH_NOARGS},\r | |
1933 | {"writable", (PyCFunction)buffered_writable, METH_NOARGS},\r | |
1934 | {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},\r | |
1935 | {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},\r | |
1936 | \r | |
1937 | {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},\r | |
1938 | {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},\r | |
1939 | {"flush", (PyCFunction)buffered_flush, METH_NOARGS},\r | |
1940 | {"seek", (PyCFunction)buffered_seek, METH_VARARGS},\r | |
1941 | {"tell", (PyCFunction)buffered_tell, METH_NOARGS},\r | |
1942 | {NULL, NULL}\r | |
1943 | };\r | |
1944 | \r | |
1945 | static PyMemberDef bufferedwriter_members[] = {\r | |
1946 | {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},\r | |
1947 | {NULL}\r | |
1948 | };\r | |
1949 | \r | |
1950 | static PyGetSetDef bufferedwriter_getset[] = {\r | |
1951 | {"closed", (getter)buffered_closed_get, NULL, NULL},\r | |
1952 | {"name", (getter)buffered_name_get, NULL, NULL},\r | |
1953 | {"mode", (getter)buffered_mode_get, NULL, NULL},\r | |
1954 | {NULL}\r | |
1955 | };\r | |
1956 | \r | |
1957 | \r | |
1958 | PyTypeObject PyBufferedWriter_Type = {\r | |
1959 | PyVarObject_HEAD_INIT(NULL, 0)\r | |
1960 | "_io.BufferedWriter", /*tp_name*/\r | |
1961 | sizeof(buffered), /*tp_basicsize*/\r | |
1962 | 0, /*tp_itemsize*/\r | |
1963 | (destructor)buffered_dealloc, /*tp_dealloc*/\r | |
1964 | 0, /*tp_print*/\r | |
1965 | 0, /*tp_getattr*/\r | |
1966 | 0, /*tp_setattr*/\r | |
1967 | 0, /*tp_compare */\r | |
1968 | (reprfunc)buffered_repr, /*tp_repr*/\r | |
1969 | 0, /*tp_as_number*/\r | |
1970 | 0, /*tp_as_sequence*/\r | |
1971 | 0, /*tp_as_mapping*/\r | |
1972 | 0, /*tp_hash */\r | |
1973 | 0, /*tp_call*/\r | |
1974 | 0, /*tp_str*/\r | |
1975 | 0, /*tp_getattro*/\r | |
1976 | 0, /*tp_setattro*/\r | |
1977 | 0, /*tp_as_buffer*/\r | |
1978 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE\r | |
1979 | | Py_TPFLAGS_HAVE_GC, /*tp_flags*/\r | |
1980 | bufferedwriter_doc, /* tp_doc */\r | |
1981 | (traverseproc)buffered_traverse, /* tp_traverse */\r | |
1982 | (inquiry)buffered_clear, /* tp_clear */\r | |
1983 | 0, /* tp_richcompare */\r | |
1984 | offsetof(buffered, weakreflist), /*tp_weaklistoffset*/\r | |
1985 | 0, /* tp_iter */\r | |
1986 | 0, /* tp_iternext */\r | |
1987 | bufferedwriter_methods, /* tp_methods */\r | |
1988 | bufferedwriter_members, /* tp_members */\r | |
1989 | bufferedwriter_getset, /* tp_getset */\r | |
1990 | 0, /* tp_base */\r | |
1991 | 0, /* tp_dict */\r | |
1992 | 0, /* tp_descr_get */\r | |
1993 | 0, /* tp_descr_set */\r | |
1994 | offsetof(buffered, dict), /* tp_dictoffset */\r | |
1995 | (initproc)bufferedwriter_init, /* tp_init */\r | |
1996 | 0, /* tp_alloc */\r | |
1997 | PyType_GenericNew, /* tp_new */\r | |
1998 | };\r | |
1999 | \f\r | |
2000 | \r | |
2001 | \r | |
2002 | /*\r | |
2003 | * BufferedRWPair\r | |
2004 | */\r | |
2005 | \r | |
2006 | PyDoc_STRVAR(bufferedrwpair_doc,\r | |
2007 | "A buffered reader and writer object together.\n"\r | |
2008 | "\n"\r | |
2009 | "A buffered reader object and buffered writer object put together to\n"\r | |
2010 | "form a sequential IO object that can read and write. This is typically\n"\r | |
2011 | "used with a socket or two-way pipe.\n"\r | |
2012 | "\n"\r | |
2013 | "reader and writer are RawIOBase objects that are readable and\n"\r | |
2014 | "writeable respectively. If the buffer_size is omitted it defaults to\n"\r | |
2015 | "DEFAULT_BUFFER_SIZE.\n"\r | |
2016 | );\r | |
2017 | \r | |
2018 | /* XXX The usefulness of this (compared to having two separate IO objects) is\r | |
2019 | * questionable.\r | |
2020 | */\r | |
2021 | \r | |
2022 | typedef struct {\r | |
2023 | PyObject_HEAD\r | |
2024 | buffered *reader;\r | |
2025 | buffered *writer;\r | |
2026 | PyObject *dict;\r | |
2027 | PyObject *weakreflist;\r | |
2028 | } rwpair;\r | |
2029 | \r | |
2030 | static int\r | |
2031 | bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)\r | |
2032 | {\r | |
2033 | PyObject *reader, *writer;\r | |
2034 | Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;\r | |
2035 | Py_ssize_t max_buffer_size = -234;\r | |
2036 | \r | |
2037 | if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,\r | |
2038 | &buffer_size, &max_buffer_size)) {\r | |
2039 | return -1;\r | |
2040 | }\r | |
2041 | \r | |
2042 | if (max_buffer_size != -234 && !complain_about_max_buffer_size())\r | |
2043 | return -1;\r | |
2044 | \r | |
2045 | if (_PyIOBase_check_readable(reader, Py_True) == NULL)\r | |
2046 | return -1;\r | |
2047 | if (_PyIOBase_check_writable(writer, Py_True) == NULL)\r | |
2048 | return -1;\r | |
2049 | \r | |
2050 | self->reader = (buffered *) PyObject_CallFunction(\r | |
2051 | (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);\r | |
2052 | if (self->reader == NULL)\r | |
2053 | return -1;\r | |
2054 | \r | |
2055 | self->writer = (buffered *) PyObject_CallFunction(\r | |
2056 | (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);\r | |
2057 | if (self->writer == NULL) {\r | |
2058 | Py_CLEAR(self->reader);\r | |
2059 | return -1;\r | |
2060 | }\r | |
2061 | \r | |
2062 | return 0;\r | |
2063 | }\r | |
2064 | \r | |
2065 | static int\r | |
2066 | bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)\r | |
2067 | {\r | |
2068 | Py_VISIT(self->dict);\r | |
2069 | return 0;\r | |
2070 | }\r | |
2071 | \r | |
2072 | static int\r | |
2073 | bufferedrwpair_clear(rwpair *self)\r | |
2074 | {\r | |
2075 | Py_CLEAR(self->reader);\r | |
2076 | Py_CLEAR(self->writer);\r | |
2077 | Py_CLEAR(self->dict);\r | |
2078 | return 0;\r | |
2079 | }\r | |
2080 | \r | |
2081 | static void\r | |
2082 | bufferedrwpair_dealloc(rwpair *self)\r | |
2083 | {\r | |
2084 | _PyObject_GC_UNTRACK(self);\r | |
2085 | Py_CLEAR(self->reader);\r | |
2086 | Py_CLEAR(self->writer);\r | |
2087 | Py_CLEAR(self->dict);\r | |
2088 | Py_TYPE(self)->tp_free((PyObject *) self);\r | |
2089 | }\r | |
2090 | \r | |
2091 | static PyObject *\r | |
2092 | _forward_call(buffered *self, const char *name, PyObject *args)\r | |
2093 | {\r | |
2094 | PyObject *func = PyObject_GetAttrString((PyObject *)self, name);\r | |
2095 | PyObject *ret;\r | |
2096 | \r | |
2097 | if (func == NULL) {\r | |
2098 | PyErr_SetString(PyExc_AttributeError, name);\r | |
2099 | return NULL;\r | |
2100 | }\r | |
2101 | \r | |
2102 | ret = PyObject_CallObject(func, args);\r | |
2103 | Py_DECREF(func);\r | |
2104 | return ret;\r | |
2105 | }\r | |
2106 | \r | |
2107 | static PyObject *\r | |
2108 | bufferedrwpair_read(rwpair *self, PyObject *args)\r | |
2109 | {\r | |
2110 | return _forward_call(self->reader, "read", args);\r | |
2111 | }\r | |
2112 | \r | |
2113 | static PyObject *\r | |
2114 | bufferedrwpair_peek(rwpair *self, PyObject *args)\r | |
2115 | {\r | |
2116 | return _forward_call(self->reader, "peek", args);\r | |
2117 | }\r | |
2118 | \r | |
2119 | static PyObject *\r | |
2120 | bufferedrwpair_read1(rwpair *self, PyObject *args)\r | |
2121 | {\r | |
2122 | return _forward_call(self->reader, "read1", args);\r | |
2123 | }\r | |
2124 | \r | |
2125 | static PyObject *\r | |
2126 | bufferedrwpair_readinto(rwpair *self, PyObject *args)\r | |
2127 | {\r | |
2128 | return _forward_call(self->reader, "readinto", args);\r | |
2129 | }\r | |
2130 | \r | |
2131 | static PyObject *\r | |
2132 | bufferedrwpair_write(rwpair *self, PyObject *args)\r | |
2133 | {\r | |
2134 | return _forward_call(self->writer, "write", args);\r | |
2135 | }\r | |
2136 | \r | |
2137 | static PyObject *\r | |
2138 | bufferedrwpair_flush(rwpair *self, PyObject *args)\r | |
2139 | {\r | |
2140 | return _forward_call(self->writer, "flush", args);\r | |
2141 | }\r | |
2142 | \r | |
2143 | static PyObject *\r | |
2144 | bufferedrwpair_readable(rwpair *self, PyObject *args)\r | |
2145 | {\r | |
2146 | return _forward_call(self->reader, "readable", args);\r | |
2147 | }\r | |
2148 | \r | |
2149 | static PyObject *\r | |
2150 | bufferedrwpair_writable(rwpair *self, PyObject *args)\r | |
2151 | {\r | |
2152 | return _forward_call(self->writer, "writable", args);\r | |
2153 | }\r | |
2154 | \r | |
2155 | static PyObject *\r | |
2156 | bufferedrwpair_close(rwpair *self, PyObject *args)\r | |
2157 | {\r | |
2158 | PyObject *ret = _forward_call(self->writer, "close", args);\r | |
2159 | if (ret == NULL)\r | |
2160 | return NULL;\r | |
2161 | Py_DECREF(ret);\r | |
2162 | \r | |
2163 | return _forward_call(self->reader, "close", args);\r | |
2164 | }\r | |
2165 | \r | |
2166 | static PyObject *\r | |
2167 | bufferedrwpair_isatty(rwpair *self, PyObject *args)\r | |
2168 | {\r | |
2169 | PyObject *ret = _forward_call(self->writer, "isatty", args);\r | |
2170 | \r | |
2171 | if (ret != Py_False) {\r | |
2172 | /* either True or exception */\r | |
2173 | return ret;\r | |
2174 | }\r | |
2175 | Py_DECREF(ret);\r | |
2176 | \r | |
2177 | return _forward_call(self->reader, "isatty", args);\r | |
2178 | }\r | |
2179 | \r | |
2180 | static PyObject *\r | |
2181 | bufferedrwpair_closed_get(rwpair *self, void *context)\r | |
2182 | {\r | |
2183 | return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);\r | |
2184 | }\r | |
2185 | \r | |
2186 | static PyMethodDef bufferedrwpair_methods[] = {\r | |
2187 | {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},\r | |
2188 | {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},\r | |
2189 | {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},\r | |
2190 | {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},\r | |
2191 | \r | |
2192 | {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},\r | |
2193 | {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},\r | |
2194 | \r | |
2195 | {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},\r | |
2196 | {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},\r | |
2197 | \r | |
2198 | {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},\r | |
2199 | {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},\r | |
2200 | \r | |
2201 | {NULL, NULL}\r | |
2202 | };\r | |
2203 | \r | |
2204 | static PyGetSetDef bufferedrwpair_getset[] = {\r | |
2205 | {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},\r | |
2206 | {NULL}\r | |
2207 | };\r | |
2208 | \r | |
2209 | PyTypeObject PyBufferedRWPair_Type = {\r | |
2210 | PyVarObject_HEAD_INIT(NULL, 0)\r | |
2211 | "_io.BufferedRWPair", /*tp_name*/\r | |
2212 | sizeof(rwpair), /*tp_basicsize*/\r | |
2213 | 0, /*tp_itemsize*/\r | |
2214 | (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/\r | |
2215 | 0, /*tp_print*/\r | |
2216 | 0, /*tp_getattr*/\r | |
2217 | 0, /*tp_setattr*/\r | |
2218 | 0, /*tp_compare */\r | |
2219 | 0, /*tp_repr*/\r | |
2220 | 0, /*tp_as_number*/\r | |
2221 | 0, /*tp_as_sequence*/\r | |
2222 | 0, /*tp_as_mapping*/\r | |
2223 | 0, /*tp_hash */\r | |
2224 | 0, /*tp_call*/\r | |
2225 | 0, /*tp_str*/\r | |
2226 | 0, /*tp_getattro*/\r | |
2227 | 0, /*tp_setattro*/\r | |
2228 | 0, /*tp_as_buffer*/\r | |
2229 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE\r | |
2230 | | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r | |
2231 | bufferedrwpair_doc, /* tp_doc */\r | |
2232 | (traverseproc)bufferedrwpair_traverse, /* tp_traverse */\r | |
2233 | (inquiry)bufferedrwpair_clear, /* tp_clear */\r | |
2234 | 0, /* tp_richcompare */\r | |
2235 | offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/\r | |
2236 | 0, /* tp_iter */\r | |
2237 | 0, /* tp_iternext */\r | |
2238 | bufferedrwpair_methods, /* tp_methods */\r | |
2239 | 0, /* tp_members */\r | |
2240 | bufferedrwpair_getset, /* tp_getset */\r | |
2241 | 0, /* tp_base */\r | |
2242 | 0, /* tp_dict */\r | |
2243 | 0, /* tp_descr_get */\r | |
2244 | 0, /* tp_descr_set */\r | |
2245 | offsetof(rwpair, dict), /* tp_dictoffset */\r | |
2246 | (initproc)bufferedrwpair_init, /* tp_init */\r | |
2247 | 0, /* tp_alloc */\r | |
2248 | PyType_GenericNew, /* tp_new */\r | |
2249 | };\r | |
2250 | \f\r | |
2251 | \r | |
2252 | \r | |
2253 | /*\r | |
2254 | * BufferedRandom\r | |
2255 | */\r | |
2256 | \r | |
2257 | PyDoc_STRVAR(bufferedrandom_doc,\r | |
2258 | "A buffered interface to random access streams.\n"\r | |
2259 | "\n"\r | |
2260 | "The constructor creates a reader and writer for a seekable stream,\n"\r | |
2261 | "raw, given in the first argument. If the buffer_size is omitted it\n"\r | |
2262 | "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"\r | |
2263 | );\r | |
2264 | \r | |
2265 | static int\r | |
2266 | bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)\r | |
2267 | {\r | |
2268 | char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};\r | |
2269 | Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;\r | |
2270 | Py_ssize_t max_buffer_size = -234;\r | |
2271 | PyObject *raw;\r | |
2272 | \r | |
2273 | self->ok = 0;\r | |
2274 | self->detached = 0;\r | |
2275 | \r | |
2276 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,\r | |
2277 | &raw, &buffer_size, &max_buffer_size)) {\r | |
2278 | return -1;\r | |
2279 | }\r | |
2280 | \r | |
2281 | if (max_buffer_size != -234 && !complain_about_max_buffer_size())\r | |
2282 | return -1;\r | |
2283 | \r | |
2284 | if (_PyIOBase_check_seekable(raw, Py_True) == NULL)\r | |
2285 | return -1;\r | |
2286 | if (_PyIOBase_check_readable(raw, Py_True) == NULL)\r | |
2287 | return -1;\r | |
2288 | if (_PyIOBase_check_writable(raw, Py_True) == NULL)\r | |
2289 | return -1;\r | |
2290 | \r | |
2291 | Py_CLEAR(self->raw);\r | |
2292 | Py_INCREF(raw);\r | |
2293 | self->raw = raw;\r | |
2294 | self->buffer_size = buffer_size;\r | |
2295 | self->readable = 1;\r | |
2296 | self->writable = 1;\r | |
2297 | \r | |
2298 | if (_buffered_init(self) < 0)\r | |
2299 | return -1;\r | |
2300 | _bufferedreader_reset_buf(self);\r | |
2301 | _bufferedwriter_reset_buf(self);\r | |
2302 | self->pos = 0;\r | |
2303 | \r | |
2304 | self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&\r | |
2305 | Py_TYPE(raw) == &PyFileIO_Type);\r | |
2306 | \r | |
2307 | self->ok = 1;\r | |
2308 | return 0;\r | |
2309 | }\r | |
2310 | \r | |
2311 | static PyMethodDef bufferedrandom_methods[] = {\r | |
2312 | /* BufferedIOMixin methods */\r | |
2313 | {"close", (PyCFunction)buffered_close, METH_NOARGS},\r | |
2314 | {"detach", (PyCFunction)buffered_detach, METH_NOARGS},\r | |
2315 | {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},\r | |
2316 | {"readable", (PyCFunction)buffered_readable, METH_NOARGS},\r | |
2317 | {"writable", (PyCFunction)buffered_writable, METH_NOARGS},\r | |
2318 | {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},\r | |
2319 | {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},\r | |
2320 | \r | |
2321 | {"flush", (PyCFunction)buffered_flush, METH_NOARGS},\r | |
2322 | \r | |
2323 | {"seek", (PyCFunction)buffered_seek, METH_VARARGS},\r | |
2324 | {"tell", (PyCFunction)buffered_tell, METH_NOARGS},\r | |
2325 | {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},\r | |
2326 | {"read", (PyCFunction)buffered_read, METH_VARARGS},\r | |
2327 | {"read1", (PyCFunction)buffered_read1, METH_VARARGS},\r | |
2328 | {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},\r | |
2329 | {"readline", (PyCFunction)buffered_readline, METH_VARARGS},\r | |
2330 | {"peek", (PyCFunction)buffered_peek, METH_VARARGS},\r | |
2331 | {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},\r | |
2332 | {NULL, NULL}\r | |
2333 | };\r | |
2334 | \r | |
2335 | static PyMemberDef bufferedrandom_members[] = {\r | |
2336 | {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},\r | |
2337 | {NULL}\r | |
2338 | };\r | |
2339 | \r | |
2340 | static PyGetSetDef bufferedrandom_getset[] = {\r | |
2341 | {"closed", (getter)buffered_closed_get, NULL, NULL},\r | |
2342 | {"name", (getter)buffered_name_get, NULL, NULL},\r | |
2343 | {"mode", (getter)buffered_mode_get, NULL, NULL},\r | |
2344 | {NULL}\r | |
2345 | };\r | |
2346 | \r | |
2347 | \r | |
2348 | PyTypeObject PyBufferedRandom_Type = {\r | |
2349 | PyVarObject_HEAD_INIT(NULL, 0)\r | |
2350 | "_io.BufferedRandom", /*tp_name*/\r | |
2351 | sizeof(buffered), /*tp_basicsize*/\r | |
2352 | 0, /*tp_itemsize*/\r | |
2353 | (destructor)buffered_dealloc, /*tp_dealloc*/\r | |
2354 | 0, /*tp_print*/\r | |
2355 | 0, /*tp_getattr*/\r | |
2356 | 0, /*tp_setattr*/\r | |
2357 | 0, /*tp_compare */\r | |
2358 | (reprfunc)buffered_repr, /*tp_repr*/\r | |
2359 | 0, /*tp_as_number*/\r | |
2360 | 0, /*tp_as_sequence*/\r | |
2361 | 0, /*tp_as_mapping*/\r | |
2362 | 0, /*tp_hash */\r | |
2363 | 0, /*tp_call*/\r | |
2364 | 0, /*tp_str*/\r | |
2365 | 0, /*tp_getattro*/\r | |
2366 | 0, /*tp_setattro*/\r | |
2367 | 0, /*tp_as_buffer*/\r | |
2368 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE\r | |
2369 | | Py_TPFLAGS_HAVE_GC, /*tp_flags*/\r | |
2370 | bufferedrandom_doc, /* tp_doc */\r | |
2371 | (traverseproc)buffered_traverse, /* tp_traverse */\r | |
2372 | (inquiry)buffered_clear, /* tp_clear */\r | |
2373 | 0, /* tp_richcompare */\r | |
2374 | offsetof(buffered, weakreflist), /*tp_weaklistoffset*/\r | |
2375 | 0, /* tp_iter */\r | |
2376 | (iternextfunc)buffered_iternext, /* tp_iternext */\r | |
2377 | bufferedrandom_methods, /* tp_methods */\r | |
2378 | bufferedrandom_members, /* tp_members */\r | |
2379 | bufferedrandom_getset, /* tp_getset */\r | |
2380 | 0, /* tp_base */\r | |
2381 | 0, /*tp_dict*/\r | |
2382 | 0, /* tp_descr_get */\r | |
2383 | 0, /* tp_descr_set */\r | |
2384 | offsetof(buffered, dict), /*tp_dictoffset*/\r | |
2385 | (initproc)bufferedrandom_init, /* tp_init */\r | |
2386 | 0, /* tp_alloc */\r | |
2387 | PyType_GenericNew, /* tp_new */\r | |
2388 | };\r | |
2389 | \r |