1/*
2    An implementation of the I/O abstract base classes hierarchy
3    as defined by PEP 3116 - "New I/O"
4
5    Classes defined here: IOBase, RawIOBase.
6
7    Written by Amaury Forgeot d'Arc and Antoine Pitrou
8*/
9
10
11#define PY_SSIZE_T_CLEAN
12#include "Python.h"
13#include "structmember.h"
14#include "_iomodule.h"
15
16/*
17 * IOBase class, an abstract class
18 */
19
20typedef struct {
21    PyObject_HEAD
22
23    PyObject *dict;
24    PyObject *weakreflist;
25} iobase;
26
27PyDoc_STRVAR(iobase_doc,
28    "The abstract base class for all I/O classes, acting on streams of\n"
29    "bytes. There is no public constructor.\n"
30    "\n"
31    "This class provides dummy implementations for many methods that\n"
32    "derived classes can override selectively; the default implementations\n"
33    "represent a file that cannot be read, written or seeked.\n"
34    "\n"
35    "Even though IOBase does not declare read, readinto, or write because\n"
36    "their signatures will vary, implementations and clients should\n"
37    "consider those methods part of the interface. Also, implementations\n"
38    "may raise a IOError when operations they do not support are called.\n"
39    "\n"
40    "The basic type used for binary data read from or written to a file is\n"
41    "bytes. bytearrays are accepted too, and in some cases (such as\n"
42    "readinto) needed. Text I/O classes work with str data.\n"
43    "\n"
44    "Note that calling any method (except additional calls to close(),\n"
45    "which are ignored) on a closed stream should raise a ValueError.\n"
46    "\n"
47    "IOBase (and its subclasses) support the iterator protocol, meaning\n"
48    "that an IOBase object can be iterated over yielding the lines in a\n"
49    "stream.\n"
50    "\n"
51    "IOBase also supports the :keyword:`with` statement. In this example,\n"
52    "fp is closed after the suite of the with statement is complete:\n"
53    "\n"
54    "with open('spam.txt', 'r') as fp:\n"
55    "    fp.write('Spam and eggs!')\n");
56
57/* Use this macro whenever you want to check the internal `closed` status
58   of the IOBase object rather than the virtual `closed` attribute as returned
59   by whatever subclass. */
60
61#define IS_CLOSED(self) \
62    PyObject_HasAttrString(self, "__IOBase_closed")
63
64/* Internal methods */
65static PyObject *
66iobase_unsupported(const char *message)
67{
68    PyErr_SetString(_PyIO_unsupported_operation, message);
69    return NULL;
70}
71
72/* Positionning */
73
74PyDoc_STRVAR(iobase_seek_doc,
75    "Change stream position.\n"
76    "\n"
77    "Change the stream position to the given byte offset. The offset is\n"
78    "interpreted relative to the position indicated by whence.  Values\n"
79    "for whence are:\n"
80    "\n"
81    "* 0 -- start of stream (the default); offset should be zero or positive\n"
82    "* 1 -- current stream position; offset may be negative\n"
83    "* 2 -- end of stream; offset is usually negative\n"
84    "\n"
85    "Return the new absolute position.");
86
87static PyObject *
88iobase_seek(PyObject *self, PyObject *args)
89{
90    return iobase_unsupported("seek");
91}
92
93PyDoc_STRVAR(iobase_tell_doc,
94             "Return current stream position.");
95
96static PyObject *
97iobase_tell(PyObject *self, PyObject *args)
98{
99    return PyObject_CallMethod(self, "seek", "ii", 0, 1);
100}
101
102PyDoc_STRVAR(iobase_truncate_doc,
103    "Truncate file to size bytes.\n"
104    "\n"
105    "File pointer is left unchanged.  Size defaults to the current IO\n"
106    "position as reported by tell().  Returns the new size.");
107
108static PyObject *
109iobase_truncate(PyObject *self, PyObject *args)
110{
111    return iobase_unsupported("truncate");
112}
113
114/* Flush and close methods */
115
116PyDoc_STRVAR(iobase_flush_doc,
117    "Flush write buffers, if applicable.\n"
118    "\n"
119    "This is not implemented for read-only and non-blocking streams.\n");
120
121static PyObject *
122iobase_flush(PyObject *self, PyObject *args)
123{
124    /* XXX Should this return the number of bytes written??? */
125    if (IS_CLOSED(self)) {
126        PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
127        return NULL;
128    }
129    Py_RETURN_NONE;
130}
131
132PyDoc_STRVAR(iobase_close_doc,
133    "Flush and close the IO object.\n"
134    "\n"
135    "This method has no effect if the file is already closed.\n");
136
137static int
138iobase_closed(PyObject *self)
139{
140    PyObject *res;
141    int closed;
142    /* This gets the derived attribute, which is *not* __IOBase_closed
143       in most cases! */
144    res = PyObject_GetAttr(self, _PyIO_str_closed);
145    if (res == NULL)
146        return 0;
147    closed = PyObject_IsTrue(res);
148    Py_DECREF(res);
149    return closed;
150}
151
152static PyObject *
153iobase_closed_get(PyObject *self, void *context)
154{
155    return PyBool_FromLong(IS_CLOSED(self));
156}
157
158PyObject *
159_PyIOBase_check_closed(PyObject *self, PyObject *args)
160{
161    if (iobase_closed(self)) {
162        PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
163        return NULL;
164    }
165    if (args == Py_True)
166        return Py_None;
167    else
168        Py_RETURN_NONE;
169}
170
171/* XXX: IOBase thinks it has to maintain its own internal state in
172   `__IOBase_closed` and call flush() by itself, but it is redundant with
173   whatever behaviour a non-trivial derived class will implement. */
174
175static PyObject *
176iobase_close(PyObject *self, PyObject *args)
177{
178    PyObject *res;
179
180    if (IS_CLOSED(self))
181        Py_RETURN_NONE;
182
183    res = PyObject_CallMethodObjArgs(self, _PyIO_str_flush, NULL);
184    PyObject_SetAttrString(self, "__IOBase_closed", Py_True);
185    if (res == NULL) {
186        return NULL;
187    }
188    Py_XDECREF(res);
189    Py_RETURN_NONE;
190}
191
192/* Finalization and garbage collection support */
193
194int
195_PyIOBase_finalize(PyObject *self)
196{
197    PyObject *res;
198    PyObject *tp, *v, *tb;
199    int closed = 1;
200    int is_zombie;
201
202    /* If _PyIOBase_finalize() is called from a destructor, we need to
203       resurrect the object as calling close() can invoke arbitrary code. */
204    is_zombie = (Py_REFCNT(self) == 0);
205    if (is_zombie) {
206        ++Py_REFCNT(self);
207    }
208    PyErr_Fetch(&tp, &v, &tb);
209    /* If `closed` doesn't exist or can't be evaluated as bool, then the
210       object is probably in an unusable state, so ignore. */
211    res = PyObject_GetAttr(self, _PyIO_str_closed);
212    if (res == NULL)
213        PyErr_Clear();
214    else {
215        closed = PyObject_IsTrue(res);
216        Py_DECREF(res);
217        if (closed == -1)
218            PyErr_Clear();
219    }
220    if (closed == 0) {
221        res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close,
222                                          NULL);
223        /* Silencing I/O errors is bad, but printing spurious tracebacks is
224           equally as bad, and potentially more frequent (because of
225           shutdown issues). */
226        if (res == NULL)
227            PyErr_Clear();
228        else
229            Py_DECREF(res);
230    }
231    PyErr_Restore(tp, v, tb);
232    if (is_zombie) {
233        if (--Py_REFCNT(self) != 0) {
234            /* The object lives again. The following code is taken from
235               slot_tp_del in typeobject.c. */
236            Py_ssize_t refcnt = Py_REFCNT(self);
237            _Py_NewReference(self);
238            Py_REFCNT(self) = refcnt;
239            /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
240             * we need to undo that. */
241            _Py_DEC_REFTOTAL;
242            /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
243             * chain, so no more to do there.
244             * If COUNT_ALLOCS, the original decref bumped tp_frees, and
245             * _Py_NewReference bumped tp_allocs:  both of those need to be
246             * undone.
247             */
248#ifdef COUNT_ALLOCS
249            --Py_TYPE(self)->tp_frees;
250            --Py_TYPE(self)->tp_allocs;
251#endif
252            return -1;
253        }
254    }
255    return 0;
256}
257
258static int
259iobase_traverse(iobase *self, visitproc visit, void *arg)
260{
261    Py_VISIT(self->dict);
262    return 0;
263}
264
265static int
266iobase_clear(iobase *self)
267{
268    if (_PyIOBase_finalize((PyObject *) self) < 0)
269        return -1;
270    Py_CLEAR(self->dict);
271    return 0;
272}
273
274/* Destructor */
275
276static void
277iobase_dealloc(iobase *self)
278{
279    /* NOTE: since IOBaseObject has its own dict, Python-defined attributes
280       are still available here for close() to use.
281       However, if the derived class declares a __slots__, those slots are
282       already gone.
283    */
284    if (_PyIOBase_finalize((PyObject *) self) < 0) {
285        /* When called from a heap type's dealloc, the type will be
286           decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
287        if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE))
288            Py_INCREF(Py_TYPE(self));
289        return;
290    }
291    _PyObject_GC_UNTRACK(self);
292    if (self->weakreflist != NULL)
293        PyObject_ClearWeakRefs((PyObject *) self);
294    Py_CLEAR(self->dict);
295    Py_TYPE(self)->tp_free((PyObject *) self);
296}
297
298/* Inquiry methods */
299
300PyDoc_STRVAR(iobase_seekable_doc,
301    "Return whether object supports random access.\n"
302    "\n"
303    "If False, seek(), tell() and truncate() will raise IOError.\n"
304    "This method may need to do a test seek().");
305
306static PyObject *
307iobase_seekable(PyObject *self, PyObject *args)
308{
309    Py_RETURN_FALSE;
310}
311
312PyObject *
313_PyIOBase_check_seekable(PyObject *self, PyObject *args)
314{
315    PyObject *res  = PyObject_CallMethodObjArgs(self, _PyIO_str_seekable, NULL);
316    if (res == NULL)
317        return NULL;
318    if (res != Py_True) {
319        Py_CLEAR(res);
320        PyErr_SetString(PyExc_IOError, "File or stream is not seekable.");
321        return NULL;
322    }
323    if (args == Py_True) {
324        Py_DECREF(res);
325    }
326    return res;
327}
328
329PyDoc_STRVAR(iobase_readable_doc,
330    "Return whether object was opened for reading.\n"
331    "\n"
332    "If False, read() will raise IOError.");
333
334static PyObject *
335iobase_readable(PyObject *self, PyObject *args)
336{
337    Py_RETURN_FALSE;
338}
339
340/* May be called with any object */
341PyObject *
342_PyIOBase_check_readable(PyObject *self, PyObject *args)
343{
344    PyObject *res  = PyObject_CallMethodObjArgs(self, _PyIO_str_readable, NULL);
345    if (res == NULL)
346        return NULL;
347    if (res != Py_True) {
348        Py_CLEAR(res);
349        PyErr_SetString(PyExc_IOError, "File or stream is not readable.");
350        return NULL;
351    }
352    if (args == Py_True) {
353        Py_DECREF(res);
354    }
355    return res;
356}
357
358PyDoc_STRVAR(iobase_writable_doc,
359    "Return whether object was opened for writing.\n"
360    "\n"
361    "If False, read() will raise IOError.");
362
363static PyObject *
364iobase_writable(PyObject *self, PyObject *args)
365{
366    Py_RETURN_FALSE;
367}
368
369/* May be called with any object */
370PyObject *
371_PyIOBase_check_writable(PyObject *self, PyObject *args)
372{
373    PyObject *res  = PyObject_CallMethodObjArgs(self, _PyIO_str_writable, NULL);
374    if (res == NULL)
375        return NULL;
376    if (res != Py_True) {
377        Py_CLEAR(res);
378        PyErr_SetString(PyExc_IOError, "File or stream is not writable.");
379        return NULL;
380    }
381    if (args == Py_True) {
382        Py_DECREF(res);
383    }
384    return res;
385}
386
387/* Context manager */
388
389static PyObject *
390iobase_enter(PyObject *self, PyObject *args)
391{
392    if (_PyIOBase_check_closed(self, Py_True) == NULL)
393        return NULL;
394
395    Py_INCREF(self);
396    return self;
397}
398
399static PyObject *
400iobase_exit(PyObject *self, PyObject *args)
401{
402    return PyObject_CallMethodObjArgs(self, _PyIO_str_close, NULL);
403}
404
405/* Lower-level APIs */
406
407/* XXX Should these be present even if unimplemented? */
408
409PyDoc_STRVAR(iobase_fileno_doc,
410    "Returns underlying file descriptor if one exists.\n"
411    "\n"
412    "An IOError is raised if the IO object does not use a file descriptor.\n");
413
414static PyObject *
415iobase_fileno(PyObject *self, PyObject *args)
416{
417    return iobase_unsupported("fileno");
418}
419
420PyDoc_STRVAR(iobase_isatty_doc,
421    "Return whether this is an 'interactive' stream.\n"
422    "\n"
423    "Return False if it can't be determined.\n");
424
425static PyObject *
426iobase_isatty(PyObject *self, PyObject *args)
427{
428    if (_PyIOBase_check_closed(self, Py_True) == NULL)
429        return NULL;
430    Py_RETURN_FALSE;
431}
432
433/* Readline(s) and writelines */
434
435PyDoc_STRVAR(iobase_readline_doc,
436    "Read and return a line from the stream.\n"
437    "\n"
438    "If limit is specified, at most limit bytes will be read.\n"
439    "\n"
440    "The line terminator is always b'\\n' for binary files; for text\n"
441    "files, the newlines argument to open can be used to select the line\n"
442    "terminator(s) recognized.\n");
443
444static PyObject *
445iobase_readline(PyObject *self, PyObject *args)
446{
447    /* For backwards compatibility, a (slowish) readline(). */
448
449    Py_ssize_t limit = -1;
450    int has_peek = 0;
451    PyObject *buffer, *result;
452    Py_ssize_t old_size = -1;
453
454    if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) {
455        return NULL;
456    }
457
458    if (PyObject_HasAttrString(self, "peek"))
459        has_peek = 1;
460
461    buffer = PyByteArray_FromStringAndSize(NULL, 0);
462    if (buffer == NULL)
463        return NULL;
464
465    while (limit < 0 || Py_SIZE(buffer) < limit) {
466        Py_ssize_t nreadahead = 1;
467        PyObject *b;
468
469        if (has_peek) {
470            PyObject *readahead = PyObject_CallMethod(self, "peek", "i", 1);
471            if (readahead == NULL) {
472                /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
473                   when EINTR occurs so we needn't do it ourselves. */
474                if (_PyIO_trap_eintr()) {
475                    continue;
476                }
477                goto fail;
478            }
479            if (!PyBytes_Check(readahead)) {
480                PyErr_Format(PyExc_IOError,
481                             "peek() should have returned a bytes object, "
482                             "not '%.200s'", Py_TYPE(readahead)->tp_name);
483                Py_DECREF(readahead);
484                goto fail;
485            }
486            if (PyBytes_GET_SIZE(readahead) > 0) {
487                Py_ssize_t n = 0;
488                const char *buf = PyBytes_AS_STRING(readahead);
489                if (limit >= 0) {
490                    do {
491                        if (n >= PyBytes_GET_SIZE(readahead) || n >= limit)
492                            break;
493                        if (buf[n++] == '\n')
494                            break;
495                    } while (1);
496                }
497                else {
498                    do {
499                        if (n >= PyBytes_GET_SIZE(readahead))
500                            break;
501                        if (buf[n++] == '\n')
502                            break;
503                    } while (1);
504                }
505                nreadahead = n;
506            }
507            Py_DECREF(readahead);
508        }
509
510        b = PyObject_CallMethod(self, "read", "n", nreadahead);
511        if (b == NULL) {
512            /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
513               when EINTR occurs so we needn't do it ourselves. */
514            if (_PyIO_trap_eintr()) {
515                continue;
516            }
517            goto fail;
518        }
519        if (!PyBytes_Check(b)) {
520            PyErr_Format(PyExc_IOError,
521                         "read() should have returned a bytes object, "
522                         "not '%.200s'", Py_TYPE(b)->tp_name);
523            Py_DECREF(b);
524            goto fail;
525        }
526        if (PyBytes_GET_SIZE(b) == 0) {
527            Py_DECREF(b);
528            break;
529        }
530
531        old_size = PyByteArray_GET_SIZE(buffer);
532        PyByteArray_Resize(buffer, old_size + PyBytes_GET_SIZE(b));
533        memcpy(PyByteArray_AS_STRING(buffer) + old_size,
534               PyBytes_AS_STRING(b), PyBytes_GET_SIZE(b));
535
536        Py_DECREF(b);
537
538        if (PyByteArray_AS_STRING(buffer)[PyByteArray_GET_SIZE(buffer) - 1] == '\n')
539            break;
540    }
541
542    result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(buffer),
543                                       PyByteArray_GET_SIZE(buffer));
544    Py_DECREF(buffer);
545    return result;
546  fail:
547    Py_DECREF(buffer);
548    return NULL;
549}
550
551static PyObject *
552iobase_iter(PyObject *self)
553{
554    if (_PyIOBase_check_closed(self, Py_True) == NULL)
555        return NULL;
556
557    Py_INCREF(self);
558    return self;
559}
560
561static PyObject *
562iobase_iternext(PyObject *self)
563{
564    PyObject *line = PyObject_CallMethodObjArgs(self, _PyIO_str_readline, NULL);
565
566    if (line == NULL)
567        return NULL;
568
569    if (PyObject_Size(line) == 0) {
570        Py_DECREF(line);
571        return NULL;
572    }
573
574    return line;
575}
576
577PyDoc_STRVAR(iobase_readlines_doc,
578    "Return a list of lines from the stream.\n"
579    "\n"
580    "hint can be specified to control the number of lines read: no more\n"
581    "lines will be read if the total size (in bytes/characters) of all\n"
582    "lines so far exceeds hint.");
583
584static PyObject *
585iobase_readlines(PyObject *self, PyObject *args)
586{
587    Py_ssize_t hint = -1, length = 0;
588    PyObject *result;
589
590    if (!PyArg_ParseTuple(args, "|O&:readlines", &_PyIO_ConvertSsize_t, &hint)) {
591        return NULL;
592    }
593
594    result = PyList_New(0);
595    if (result == NULL)
596        return NULL;
597
598    if (hint <= 0) {
599        /* XXX special-casing this made sense in the Python version in order
600           to remove the bytecode interpretation overhead, but it could
601           probably be removed here. */
602        PyObject *ret = PyObject_CallMethod(result, "extend", "O", self);
603        if (ret == NULL) {
604            Py_DECREF(result);
605            return NULL;
606        }
607        Py_DECREF(ret);
608        return result;
609    }
610
611    while (1) {
612        PyObject *line = PyIter_Next(self);
613        if (line == NULL) {
614            if (PyErr_Occurred()) {
615                Py_DECREF(result);
616                return NULL;
617            }
618            else
619                break; /* StopIteration raised */
620        }
621
622        if (PyList_Append(result, line) < 0) {
623            Py_DECREF(line);
624            Py_DECREF(result);
625            return NULL;
626        }
627        length += PyObject_Size(line);
628        Py_DECREF(line);
629
630        if (length > hint)
631            break;
632    }
633    return result;
634}
635
636static PyObject *
637iobase_writelines(PyObject *self, PyObject *args)
638{
639    PyObject *lines, *iter, *res;
640
641    if (!PyArg_ParseTuple(args, "O:writelines", &lines)) {
642        return NULL;
643    }
644
645    if (_PyIOBase_check_closed(self, Py_True) == NULL)
646        return NULL;
647
648    iter = PyObject_GetIter(lines);
649    if (iter == NULL)
650        return NULL;
651
652    while (1) {
653        PyObject *line = PyIter_Next(iter);
654        if (line == NULL) {
655            if (PyErr_Occurred()) {
656                Py_DECREF(iter);
657                return NULL;
658            }
659            else
660                break; /* Stop Iteration */
661        }
662
663        res = NULL;
664        do {
665            res = PyObject_CallMethodObjArgs(self, _PyIO_str_write, line, NULL);
666        } while (res == NULL && _PyIO_trap_eintr());
667        Py_DECREF(line);
668        if (res == NULL) {
669            Py_DECREF(iter);
670            return NULL;
671        }
672        Py_DECREF(res);
673    }
674    Py_DECREF(iter);
675    Py_RETURN_NONE;
676}
677
678static PyMethodDef iobase_methods[] = {
679    {"seek", iobase_seek, METH_VARARGS, iobase_seek_doc},
680    {"tell", iobase_tell, METH_NOARGS, iobase_tell_doc},
681    {"truncate", iobase_truncate, METH_VARARGS, iobase_truncate_doc},
682    {"flush", iobase_flush, METH_NOARGS, iobase_flush_doc},
683    {"close", iobase_close, METH_NOARGS, iobase_close_doc},
684
685    {"seekable", iobase_seekable, METH_NOARGS, iobase_seekable_doc},
686    {"readable", iobase_readable, METH_NOARGS, iobase_readable_doc},
687    {"writable", iobase_writable, METH_NOARGS, iobase_writable_doc},
688
689    {"_checkClosed",   _PyIOBase_check_closed, METH_NOARGS},
690    {"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS},
691    {"_checkReadable", _PyIOBase_check_readable, METH_NOARGS},
692    {"_checkWritable", _PyIOBase_check_writable, METH_NOARGS},
693
694    {"fileno", iobase_fileno, METH_NOARGS, iobase_fileno_doc},
695    {"isatty", iobase_isatty, METH_NOARGS, iobase_isatty_doc},
696
697    {"__enter__", iobase_enter, METH_NOARGS},
698    {"__exit__", iobase_exit, METH_VARARGS},
699
700    {"readline", iobase_readline, METH_VARARGS, iobase_readline_doc},
701    {"readlines", iobase_readlines, METH_VARARGS, iobase_readlines_doc},
702    {"writelines", iobase_writelines, METH_VARARGS},
703
704    {NULL, NULL}
705};
706
707static PyGetSetDef iobase_getset[] = {
708    {"closed", (getter)iobase_closed_get, NULL, NULL},
709    {NULL}
710};
711
712
713PyTypeObject PyIOBase_Type = {
714    PyVarObject_HEAD_INIT(NULL, 0)
715    "_io._IOBase",              /*tp_name*/
716    sizeof(iobase),             /*tp_basicsize*/
717    0,                          /*tp_itemsize*/
718    (destructor)iobase_dealloc, /*tp_dealloc*/
719    0,                          /*tp_print*/
720    0,                          /*tp_getattr*/
721    0,                          /*tp_setattr*/
722    0,                          /*tp_compare */
723    0,                          /*tp_repr*/
724    0,                          /*tp_as_number*/
725    0,                          /*tp_as_sequence*/
726    0,                          /*tp_as_mapping*/
727    0,                          /*tp_hash */
728    0,                          /*tp_call*/
729    0,                          /*tp_str*/
730    0,                          /*tp_getattro*/
731    0,                          /*tp_setattro*/
732    0,                          /*tp_as_buffer*/
733    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
734        | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
735    iobase_doc,                 /* tp_doc */
736    (traverseproc)iobase_traverse, /* tp_traverse */
737    (inquiry)iobase_clear,      /* tp_clear */
738    0,                          /* tp_richcompare */
739    offsetof(iobase, weakreflist), /* tp_weaklistoffset */
740    iobase_iter,                /* tp_iter */
741    iobase_iternext,            /* tp_iternext */
742    iobase_methods,             /* tp_methods */
743    0,                          /* tp_members */
744    iobase_getset,              /* tp_getset */
745    0,                          /* tp_base */
746    0,                          /* tp_dict */
747    0,                          /* tp_descr_get */
748    0,                          /* tp_descr_set */
749    offsetof(iobase, dict),     /* tp_dictoffset */
750    0,                          /* tp_init */
751    0,                          /* tp_alloc */
752    PyType_GenericNew,          /* tp_new */
753};
754
755
756/*
757 * RawIOBase class, Inherits from IOBase.
758 */
759PyDoc_STRVAR(rawiobase_doc,
760             "Base class for raw binary I/O.");
761
762/*
763 * The read() method is implemented by calling readinto(); derived classes
764 * that want to support read() only need to implement readinto() as a
765 * primitive operation.  In general, readinto() can be more efficient than
766 * read().
767 *
768 * (It would be tempting to also provide an implementation of readinto() in
769 * terms of read(), in case the latter is a more suitable primitive operation,
770 * but that would lead to nasty recursion in case a subclass doesn't implement
771 * either.)
772*/
773
774static PyObject *
775rawiobase_read(PyObject *self, PyObject *args)
776{
777    Py_ssize_t n = -1;
778    PyObject *b, *res;
779
780    if (!PyArg_ParseTuple(args, "|n:read", &n)) {
781        return NULL;
782    }
783
784    if (n < 0)
785        return PyObject_CallMethod(self, "readall", NULL);
786
787    /* TODO: allocate a bytes object directly instead and manually construct
788       a writable memoryview pointing to it. */
789    b = PyByteArray_FromStringAndSize(NULL, n);
790    if (b == NULL)
791        return NULL;
792
793    res = PyObject_CallMethodObjArgs(self, _PyIO_str_readinto, b, NULL);
794    if (res == NULL || res == Py_None) {
795        Py_DECREF(b);
796        return res;
797    }
798
799    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
800    Py_DECREF(res);
801    if (n == -1 && PyErr_Occurred()) {
802        Py_DECREF(b);
803        return NULL;
804    }
805
806    res = PyBytes_FromStringAndSize(PyByteArray_AsString(b), n);
807    Py_DECREF(b);
808    return res;
809}
810
811
812PyDoc_STRVAR(rawiobase_readall_doc,
813             "Read until EOF, using multiple read() call.");
814
815static PyObject *
816rawiobase_readall(PyObject *self, PyObject *args)
817{
818    int r;
819    PyObject *chunks = PyList_New(0);
820    PyObject *result;
821
822    if (chunks == NULL)
823        return NULL;
824
825    while (1) {
826        PyObject *data = PyObject_CallMethod(self, "read",
827                                             "i", DEFAULT_BUFFER_SIZE);
828        if (!data) {
829            /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
830               when EINTR occurs so we needn't do it ourselves. */
831            if (_PyIO_trap_eintr()) {
832                continue;
833            }
834            Py_DECREF(chunks);
835            return NULL;
836        }
837        if (data == Py_None) {
838            if (PyList_GET_SIZE(chunks) == 0) {
839                Py_DECREF(chunks);
840                return data;
841            }
842            Py_DECREF(data);
843            break;
844        }
845        if (!PyBytes_Check(data)) {
846            Py_DECREF(chunks);
847            Py_DECREF(data);
848            PyErr_SetString(PyExc_TypeError, "read() should return bytes");
849            return NULL;
850        }
851        if (PyBytes_GET_SIZE(data) == 0) {
852            /* EOF */
853            Py_DECREF(data);
854            break;
855        }
856        r = PyList_Append(chunks, data);
857        Py_DECREF(data);
858        if (r < 0) {
859            Py_DECREF(chunks);
860            return NULL;
861        }
862    }
863    result = _PyBytes_Join(_PyIO_empty_bytes, chunks);
864    Py_DECREF(chunks);
865    return result;
866}
867
868static PyMethodDef rawiobase_methods[] = {
869    {"read", rawiobase_read, METH_VARARGS},
870    {"readall", rawiobase_readall, METH_NOARGS, rawiobase_readall_doc},
871    {NULL, NULL}
872};
873
874PyTypeObject PyRawIOBase_Type = {
875    PyVarObject_HEAD_INIT(NULL, 0)
876    "_io._RawIOBase",                /*tp_name*/
877    0,                          /*tp_basicsize*/
878    0,                          /*tp_itemsize*/
879    0,                          /*tp_dealloc*/
880    0,                          /*tp_print*/
881    0,                          /*tp_getattr*/
882    0,                          /*tp_setattr*/
883    0,                          /*tp_compare */
884    0,                          /*tp_repr*/
885    0,                          /*tp_as_number*/
886    0,                          /*tp_as_sequence*/
887    0,                          /*tp_as_mapping*/
888    0,                          /*tp_hash */
889    0,                          /*tp_call*/
890    0,                          /*tp_str*/
891    0,                          /*tp_getattro*/
892    0,                          /*tp_setattro*/
893    0,                          /*tp_as_buffer*/
894    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
895    rawiobase_doc,              /* tp_doc */
896    0,                          /* tp_traverse */
897    0,                          /* tp_clear */
898    0,                          /* tp_richcompare */
899    0,                          /* tp_weaklistoffset */
900    0,                          /* tp_iter */
901    0,                          /* tp_iternext */
902    rawiobase_methods,          /* tp_methods */
903    0,                          /* tp_members */
904    0,                          /* tp_getset */
905    &PyIOBase_Type,             /* tp_base */
906    0,                          /* tp_dict */
907    0,                          /* tp_descr_get */
908    0,                          /* tp_descr_set */
909    0,                          /* tp_dictoffset */
910    0,                          /* tp_init */
911    0,                          /* tp_alloc */
912    0,                          /* tp_new */
913};
914