LCOV - code coverage report
Current view: | top level - Modules/_io - bytesio.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 0 | 375 | 0.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 0 | 39 | 0.0 %
|  |  | Branches: | 0 | 258 | 0.0 %

               Branch data     Line data    Source code
           1                 :            : #include "Python.h"
           2                 :            : #include "pycore_object.h"
           3                 :            : #include <stddef.h>               // offsetof()
           4                 :            : #include "_iomodule.h"
           5                 :            :
           6                 :            : /*[clinic input]
           7                 :            : module _io
           8                 :            : class _io.BytesIO "bytesio *" "clinic_state()->PyBytesIO_Type"
           9                 :            : [clinic start generated code]*/
          10                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=48ede2f330f847c3]*/
          11                 :            :
          12                 :            : typedef struct {
          13                 :            :     PyObject_HEAD
          14                 :            :     PyObject *buf;
          15                 :            :     Py_ssize_t pos;
          16                 :            :     Py_ssize_t string_size;
          17                 :            :     PyObject *dict;
          18                 :            :     PyObject *weakreflist;
          19                 :            :     Py_ssize_t exports;
          20                 :            : } bytesio;
          21                 :            :
          22                 :            : typedef struct {
          23                 :            :     PyObject_HEAD
          24                 :            :     bytesio *source;
          25                 :            : } bytesiobuf;
          26                 :            :
          27                 :            : /* The bytesio object can be in three states:
          28                 :            :   * Py_REFCNT(buf) == 1, exports == 0.
          29                 :            :   * Py_REFCNT(buf) > 1.  exports == 0,
          30                 :            :     first modification or export causes the internal buffer copying.
          31                 :            :   * exports > 0.  Py_REFCNT(buf) == 1, any modifications are forbidden.
          32                 :            : */
          33                 :            :
          34                 :            : static int
          35                 :          0 : check_closed(bytesio *self)
          36                 :            : {
          37         [ #  # ]:          0 :     if (self->buf == NULL) {
          38                 :          0 :         PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
          39                 :          0 :         return 1;
          40                 :            :     }
          41                 :          0 :     return 0;
          42                 :            : }
          43                 :            :
          44                 :            : static int
          45                 :          0 : check_exports(bytesio *self)
          46                 :            : {
          47         [ #  # ]:          0 :     if (self->exports > 0) {
          48                 :          0 :         PyErr_SetString(PyExc_BufferError,
          49                 :            :                         "Existing exports of data: object cannot be re-sized");
          50                 :          0 :         return 1;
          51                 :            :     }
          52                 :          0 :     return 0;
          53                 :            : }
          54                 :            :
          55                 :            : #define CHECK_CLOSED(self)                                  \
          56                 :            :     if (check_closed(self)) {                               \
          57                 :            :         return NULL;                                        \
          58                 :            :     }
          59                 :            :
          60                 :            : #define CHECK_EXPORTS(self) \
          61                 :            :     if (check_exports(self)) { \
          62                 :            :         return NULL; \
          63                 :            :     }
          64                 :            :
          65                 :            : #define SHARED_BUF(self) (Py_REFCNT((self)->buf) > 1)
          66                 :            :
          67                 :            :
          68                 :            : /* Internal routine to get a line from the buffer of a BytesIO
          69                 :            :    object. Returns the length between the current position to the
          70                 :            :    next newline character. */
          71                 :            : static Py_ssize_t
          72                 :          0 : scan_eol(bytesio *self, Py_ssize_t len)
          73                 :            : {
          74                 :            :     const char *start, *n;
          75                 :            :     Py_ssize_t maxlen;
          76                 :            :
          77                 :            :     assert(self->buf != NULL);
          78                 :            :     assert(self->pos >= 0);
          79                 :            :
          80         [ #  # ]:          0 :     if (self->pos >= self->string_size)
          81                 :          0 :         return 0;
          82                 :            :
          83                 :            :     /* Move to the end of the line, up to the end of the string, s. */
          84                 :          0 :     maxlen = self->string_size - self->pos;
          85   [ #  #  #  # ]:          0 :     if (len < 0 || len > maxlen)
          86                 :          0 :         len = maxlen;
          87                 :            :
          88         [ #  # ]:          0 :     if (len) {
          89                 :          0 :         start = PyBytes_AS_STRING(self->buf) + self->pos;
          90                 :          0 :         n = memchr(start, '\n', len);
          91         [ #  # ]:          0 :         if (n)
          92                 :            :             /* Get the length from the current position to the end of
          93                 :            :                the line. */
          94                 :          0 :             len = n - start + 1;
          95                 :            :     }
          96                 :            :     assert(len >= 0);
          97                 :            :     assert(self->pos < PY_SSIZE_T_MAX - len);
          98                 :            :
          99                 :          0 :     return len;
         100                 :            : }
         101                 :            :
         102                 :            : /* Internal routine for detaching the shared buffer of BytesIO objects.
         103                 :            :    The caller should ensure that the 'size' argument is non-negative and
         104                 :            :    not lesser than self->string_size.  Returns 0 on success, -1 otherwise. */
         105                 :            : static int
         106                 :          0 : unshare_buffer(bytesio *self, size_t size)
         107                 :            : {
         108                 :            :     PyObject *new_buf;
         109                 :            :     assert(SHARED_BUF(self));
         110                 :            :     assert(self->exports == 0);
         111                 :            :     assert(size >= (size_t)self->string_size);
         112                 :          0 :     new_buf = PyBytes_FromStringAndSize(NULL, size);
         113         [ #  # ]:          0 :     if (new_buf == NULL)
         114                 :          0 :         return -1;
         115                 :          0 :     memcpy(PyBytes_AS_STRING(new_buf), PyBytes_AS_STRING(self->buf),
         116                 :          0 :            self->string_size);
         117                 :          0 :     Py_SETREF(self->buf, new_buf);
         118                 :          0 :     return 0;
         119                 :            : }
         120                 :            :
         121                 :            : /* Internal routine for changing the size of the buffer of BytesIO objects.
         122                 :            :    The caller should ensure that the 'size' argument is non-negative.  Returns
         123                 :            :    0 on success, -1 otherwise. */
         124                 :            : static int
         125                 :          0 : resize_buffer(bytesio *self, size_t size)
         126                 :            : {
         127                 :            :     /* Here, unsigned types are used to avoid dealing with signed integer
         128                 :            :        overflow, which is undefined in C. */
         129                 :          0 :     size_t alloc = PyBytes_GET_SIZE(self->buf);
         130                 :            :
         131                 :            :     assert(self->buf != NULL);
         132                 :            :
         133                 :            :     /* For simplicity, stay in the range of the signed type. Anyway, Python
         134                 :            :        doesn't allow strings to be longer than this. */
         135         [ #  # ]:          0 :     if (size > PY_SSIZE_T_MAX)
         136                 :          0 :         goto overflow;
         137                 :            :
         138         [ #  # ]:          0 :     if (size < alloc / 2) {
         139                 :            :         /* Major downsize; resize down to exact size. */
         140                 :          0 :         alloc = size + 1;
         141                 :            :     }
         142         [ #  # ]:          0 :     else if (size < alloc) {
         143                 :            :         /* Within allocated size; quick exit */
         144                 :          0 :         return 0;
         145                 :            :     }
         146         [ #  # ]:          0 :     else if (size <= alloc * 1.125) {
         147                 :            :         /* Moderate upsize; overallocate similar to list_resize() */
         148         [ #  # ]:          0 :         alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
         149                 :            :     }
         150                 :            :     else {
         151                 :            :         /* Major upsize; resize up to exact size */
         152                 :          0 :         alloc = size + 1;
         153                 :            :     }
         154                 :            :
         155                 :            :     if (alloc > ((size_t)-1) / sizeof(char))
         156                 :            :         goto overflow;
         157                 :            :
         158         [ #  # ]:          0 :     if (SHARED_BUF(self)) {
         159         [ #  # ]:          0 :         if (unshare_buffer(self, alloc) < 0)
         160                 :          0 :             return -1;
         161                 :            :     }
         162                 :            :     else {
         163         [ #  # ]:          0 :         if (_PyBytes_Resize(&self->buf, alloc) < 0)
         164                 :          0 :             return -1;
         165                 :            :     }
         166                 :            :
         167                 :          0 :     return 0;
         168                 :            :
         169                 :          0 :   overflow:
         170                 :          0 :     PyErr_SetString(PyExc_OverflowError,
         171                 :            :                     "new buffer size too large");
         172                 :          0 :     return -1;
         173                 :            : }
         174                 :            :
         175                 :            : /* Internal routine for writing a string of bytes to the buffer of a BytesIO
         176                 :            :    object. Returns the number of bytes written, or -1 on error.
         177                 :            :    Inlining is disabled because it's significantly decreases performance
         178                 :            :    of writelines() in PGO build. */
         179                 :            : Py_NO_INLINE static Py_ssize_t
         180                 :          0 : write_bytes(bytesio *self, PyObject *b)
         181                 :            : {
         182         [ #  # ]:          0 :     if (check_closed(self)) {
         183                 :          0 :         return -1;
         184                 :            :     }
         185         [ #  # ]:          0 :     if (check_exports(self)) {
         186                 :          0 :         return -1;
         187                 :            :     }
         188                 :            :
         189                 :            :     Py_buffer buf;
         190         [ #  # ]:          0 :     if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0) {
         191                 :          0 :         return -1;
         192                 :            :     }
         193                 :          0 :     Py_ssize_t len = buf.len;
         194         [ #  # ]:          0 :     if (len == 0) {
         195                 :          0 :         goto done;
         196                 :            :     }
         197                 :            :
         198                 :            :     assert(self->pos >= 0);
         199                 :          0 :     size_t endpos = (size_t)self->pos + len;
         200         [ #  # ]:          0 :     if (endpos > (size_t)PyBytes_GET_SIZE(self->buf)) {
         201         [ #  # ]:          0 :         if (resize_buffer(self, endpos) < 0) {
         202                 :          0 :             len = -1;
         203                 :          0 :             goto done;
         204                 :            :         }
         205                 :            :     }
         206         [ #  # ]:          0 :     else if (SHARED_BUF(self)) {
         207         [ #  # ]:          0 :         if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0) {
         208                 :          0 :             len = -1;
         209                 :          0 :             goto done;
         210                 :            :         }
         211                 :            :     }
         212                 :            :
         213         [ #  # ]:          0 :     if (self->pos > self->string_size) {
         214                 :            :         /* In case of overseek, pad with null bytes the buffer region between
         215                 :            :            the end of stream and the current position.
         216                 :            :
         217                 :            :           0   lo      string_size                           hi
         218                 :            :           |   |<---used--->|<----------available----------->|
         219                 :            :           |   |            <--to pad-->|<---to write--->    |
         220                 :            :           0   buf                   position
         221                 :            :         */
         222                 :          0 :         memset(PyBytes_AS_STRING(self->buf) + self->string_size, '\0',
         223                 :          0 :                (self->pos - self->string_size) * sizeof(char));
         224                 :            :     }
         225                 :            :
         226                 :            :     /* Copy the data to the internal buffer, overwriting some of the existing
         227                 :            :        data if self->pos < self->string_size. */
         228                 :          0 :     memcpy(PyBytes_AS_STRING(self->buf) + self->pos, buf.buf, len);
         229                 :          0 :     self->pos = endpos;
         230                 :            :
         231                 :            :     /* Set the new length of the internal string if it has changed. */
         232         [ #  # ]:          0 :     if ((size_t)self->string_size < endpos) {
         233                 :          0 :         self->string_size = endpos;
         234                 :            :     }
         235                 :            :
         236                 :          0 :   done:
         237                 :          0 :     PyBuffer_Release(&buf);
         238                 :          0 :     return len;
         239                 :            : }
         240                 :            :
         241                 :            : static PyObject *
         242                 :          0 : bytesio_get_closed(bytesio *self, void *Py_UNUSED(ignored))
         243                 :            : {
         244         [ #  # ]:          0 :     if (self->buf == NULL) {
         245                 :          0 :         Py_RETURN_TRUE;
         246                 :            :     }
         247                 :            :     else {
         248                 :          0 :         Py_RETURN_FALSE;
         249                 :            :     }
         250                 :            : }
         251                 :            :
         252                 :            : /*[clinic input]
         253                 :            : _io.BytesIO.readable
         254                 :            :
         255                 :            : Returns True if the IO object can be read.
         256                 :            : [clinic start generated code]*/
         257                 :            :
         258                 :            : static PyObject *
         259                 :          0 : _io_BytesIO_readable_impl(bytesio *self)
         260                 :            : /*[clinic end generated code: output=4e93822ad5b62263 input=96c5d0cccfb29f5c]*/
         261                 :            : {
         262         [ #  # ]:          0 :     CHECK_CLOSED(self);
         263                 :          0 :     Py_RETURN_TRUE;
         264                 :            : }
         265                 :            :
         266                 :            : /*[clinic input]
         267                 :            : _io.BytesIO.writable
         268                 :            :
         269                 :            : Returns True if the IO object can be written.
         270                 :            : [clinic start generated code]*/
         271                 :            :
         272                 :            : static PyObject *
         273                 :          0 : _io_BytesIO_writable_impl(bytesio *self)
         274                 :            : /*[clinic end generated code: output=64ff6a254b1150b8 input=700eed808277560a]*/
         275                 :            : {
         276         [ #  # ]:          0 :     CHECK_CLOSED(self);
         277                 :          0 :     Py_RETURN_TRUE;
         278                 :            : }
         279                 :            :
         280                 :            : /*[clinic input]
         281                 :            : _io.BytesIO.seekable
         282                 :            :
         283                 :            : Returns True if the IO object can be seeked.
         284                 :            : [clinic start generated code]*/
         285                 :            :
         286                 :            : static PyObject *
         287                 :          0 : _io_BytesIO_seekable_impl(bytesio *self)
         288                 :            : /*[clinic end generated code: output=6b417f46dcc09b56 input=9421f65627a344dd]*/
         289                 :            : {
         290         [ #  # ]:          0 :     CHECK_CLOSED(self);
         291                 :          0 :     Py_RETURN_TRUE;
         292                 :            : }
         293                 :            :
         294                 :            : /*[clinic input]
         295                 :            : _io.BytesIO.flush
         296                 :            :
         297                 :            : Does nothing.
         298                 :            : [clinic start generated code]*/
         299                 :            :
         300                 :            : static PyObject *
         301                 :          0 : _io_BytesIO_flush_impl(bytesio *self)
         302                 :            : /*[clinic end generated code: output=187e3d781ca134a0 input=561ea490be4581a7]*/
         303                 :            : {
         304         [ #  # ]:          0 :     CHECK_CLOSED(self);
         305                 :          0 :     Py_RETURN_NONE;
         306                 :            : }
         307                 :            :
         308                 :            : /*[clinic input]
         309                 :            : _io.BytesIO.getbuffer
         310                 :            :
         311                 :            : Get a read-write view over the contents of the BytesIO object.
         312                 :            : [clinic start generated code]*/
         313                 :            :
         314                 :            : static PyObject *
         315                 :          0 : _io_BytesIO_getbuffer_impl(bytesio *self)
         316                 :            : /*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/
         317                 :            : {
         318                 :          0 :     PyTypeObject *type = &_PyBytesIOBuffer_Type;
         319                 :            :     bytesiobuf *buf;
         320                 :            :     PyObject *view;
         321                 :            :
         322         [ #  # ]:          0 :     CHECK_CLOSED(self);
         323                 :            :
         324                 :          0 :     buf = (bytesiobuf *) type->tp_alloc(type, 0);
         325         [ #  # ]:          0 :     if (buf == NULL)
         326                 :          0 :         return NULL;
         327                 :          0 :     buf->source = (bytesio*)Py_NewRef(self);
         328                 :          0 :     view = PyMemoryView_FromObject((PyObject *) buf);
         329                 :          0 :     Py_DECREF(buf);
         330                 :          0 :     return view;
         331                 :            : }
         332                 :            :
         333                 :            : /*[clinic input]
         334                 :            : _io.BytesIO.getvalue
         335                 :            :
         336                 :            : Retrieve the entire contents of the BytesIO object.
         337                 :            : [clinic start generated code]*/
         338                 :            :
         339                 :            : static PyObject *
         340                 :          0 : _io_BytesIO_getvalue_impl(bytesio *self)
         341                 :            : /*[clinic end generated code: output=b3f6a3233c8fd628 input=4b403ac0af3973ed]*/
         342                 :            : {
         343         [ #  # ]:          0 :     CHECK_CLOSED(self);
         344   [ #  #  #  # ]:          0 :     if (self->string_size <= 1 || self->exports > 0)
         345                 :          0 :         return PyBytes_FromStringAndSize(PyBytes_AS_STRING(self->buf),
         346                 :            :                                          self->string_size);
         347                 :            :
         348         [ #  # ]:          0 :     if (self->string_size != PyBytes_GET_SIZE(self->buf)) {
         349         [ #  # ]:          0 :         if (SHARED_BUF(self)) {
         350         [ #  # ]:          0 :             if (unshare_buffer(self, self->string_size) < 0)
         351                 :          0 :                 return NULL;
         352                 :            :         }
         353                 :            :         else {
         354         [ #  # ]:          0 :             if (_PyBytes_Resize(&self->buf, self->string_size) < 0)
         355                 :          0 :                 return NULL;
         356                 :            :         }
         357                 :            :     }
         358                 :          0 :     return Py_NewRef(self->buf);
         359                 :            : }
         360                 :            :
         361                 :            : /*[clinic input]
         362                 :            : _io.BytesIO.isatty
         363                 :            :
         364                 :            : Always returns False.
         365                 :            :
         366                 :            : BytesIO objects are not connected to a TTY-like device.
         367                 :            : [clinic start generated code]*/
         368                 :            :
         369                 :            : static PyObject *
         370                 :          0 : _io_BytesIO_isatty_impl(bytesio *self)
         371                 :            : /*[clinic end generated code: output=df67712e669f6c8f input=6f97f0985d13f827]*/
         372                 :            : {
         373         [ #  # ]:          0 :     CHECK_CLOSED(self);
         374                 :          0 :     Py_RETURN_FALSE;
         375                 :            : }
         376                 :            :
         377                 :            : /*[clinic input]
         378                 :            : _io.BytesIO.tell
         379                 :            :
         380                 :            : Current file position, an integer.
         381                 :            : [clinic start generated code]*/
         382                 :            :
         383                 :            : static PyObject *
         384                 :          0 : _io_BytesIO_tell_impl(bytesio *self)
         385                 :            : /*[clinic end generated code: output=b54b0f93cd0e5e1d input=b106adf099cb3657]*/
         386                 :            : {
         387         [ #  # ]:          0 :     CHECK_CLOSED(self);
         388                 :          0 :     return PyLong_FromSsize_t(self->pos);
         389                 :            : }
         390                 :            :
         391                 :            : static PyObject *
         392                 :          0 : read_bytes(bytesio *self, Py_ssize_t size)
         393                 :            : {
         394                 :            :     const char *output;
         395                 :            :
         396                 :            :     assert(self->buf != NULL);
         397                 :            :     assert(size <= self->string_size);
         398         [ #  # ]:          0 :     if (size > 1 &&
         399   [ #  #  #  # ]:          0 :         self->pos == 0 && size == PyBytes_GET_SIZE(self->buf) &&
         400         [ #  # ]:          0 :         self->exports == 0) {
         401                 :          0 :         self->pos += size;
         402                 :          0 :         return Py_NewRef(self->buf);
         403                 :            :     }
         404                 :            :
         405                 :          0 :     output = PyBytes_AS_STRING(self->buf) + self->pos;
         406                 :          0 :     self->pos += size;
         407                 :          0 :     return PyBytes_FromStringAndSize(output, size);
         408                 :            : }
         409                 :            :
         410                 :            : /*[clinic input]
         411                 :            : _io.BytesIO.read
         412                 :            :     size: Py_ssize_t(accept={int, NoneType}) = -1
         413                 :            :     /
         414                 :            :
         415                 :            : Read at most size bytes, returned as a bytes object.
         416                 :            :
         417                 :            : If the size argument is negative, read until EOF is reached.
         418                 :            : Return an empty bytes object at EOF.
         419                 :            : [clinic start generated code]*/
         420                 :            :
         421                 :            : static PyObject *
         422                 :          0 : _io_BytesIO_read_impl(bytesio *self, Py_ssize_t size)
         423                 :            : /*[clinic end generated code: output=9cc025f21c75bdd2 input=74344a39f431c3d7]*/
         424                 :            : {
         425                 :            :     Py_ssize_t n;
         426                 :            :
         427         [ #  # ]:          0 :     CHECK_CLOSED(self);
         428                 :            :
         429                 :            :     /* adjust invalid sizes */
         430                 :          0 :     n = self->string_size - self->pos;
         431   [ #  #  #  # ]:          0 :     if (size < 0 || size > n) {
         432                 :          0 :         size = n;
         433         [ #  # ]:          0 :         if (size < 0)
         434                 :          0 :             size = 0;
         435                 :            :     }
         436                 :            :
         437                 :          0 :     return read_bytes(self, size);
         438                 :            : }
         439                 :            :
         440                 :            :
         441                 :            : /*[clinic input]
         442                 :            : _io.BytesIO.read1
         443                 :            :     size: Py_ssize_t(accept={int, NoneType}) = -1
         444                 :            :     /
         445                 :            :
         446                 :            : Read at most size bytes, returned as a bytes object.
         447                 :            :
         448                 :            : If the size argument is negative or omitted, read until EOF is reached.
         449                 :            : Return an empty bytes object at EOF.
         450                 :            : [clinic start generated code]*/
         451                 :            :
         452                 :            : static PyObject *
         453                 :          0 : _io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
         454                 :            : /*[clinic end generated code: output=d0f843285aa95f1c input=440a395bf9129ef5]*/
         455                 :            : {
         456                 :          0 :     return _io_BytesIO_read_impl(self, size);
         457                 :            : }
         458                 :            :
         459                 :            : /*[clinic input]
         460                 :            : _io.BytesIO.readline
         461                 :            :     size: Py_ssize_t(accept={int, NoneType}) = -1
         462                 :            :     /
         463                 :            :
         464                 :            : Next line from the file, as a bytes object.
         465                 :            :
         466                 :            : Retain newline.  A non-negative size argument limits the maximum
         467                 :            : number of bytes to return (an incomplete line may be returned then).
         468                 :            : Return an empty bytes object at EOF.
         469                 :            : [clinic start generated code]*/
         470                 :            :
         471                 :            : static PyObject *
         472                 :          0 : _io_BytesIO_readline_impl(bytesio *self, Py_ssize_t size)
         473                 :            : /*[clinic end generated code: output=4bff3c251df8ffcd input=e7c3fbd1744e2783]*/
         474                 :            : {
         475                 :            :     Py_ssize_t n;
         476                 :            :
         477         [ #  # ]:          0 :     CHECK_CLOSED(self);
         478                 :            :
         479                 :          0 :     n = scan_eol(self, size);
         480                 :            :
         481                 :          0 :     return read_bytes(self, n);
         482                 :            : }
         483                 :            :
         484                 :            : /*[clinic input]
         485                 :            : _io.BytesIO.readlines
         486                 :            :     size as arg: object = None
         487                 :            :     /
         488                 :            :
         489                 :            : List of bytes objects, each a line from the file.
         490                 :            :
         491                 :            : Call readline() repeatedly and return a list of the lines so read.
         492                 :            : The optional size argument, if given, is an approximate bound on the
         493                 :            : total number of bytes in the lines returned.
         494                 :            : [clinic start generated code]*/
         495                 :            :
         496                 :            : static PyObject *
         497                 :          0 : _io_BytesIO_readlines_impl(bytesio *self, PyObject *arg)
         498                 :            : /*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/
         499                 :            : {
         500                 :            :     Py_ssize_t maxsize, size, n;
         501                 :            :     PyObject *result, *line;
         502                 :            :     const char *output;
         503                 :            :
         504         [ #  # ]:          0 :     CHECK_CLOSED(self);
         505                 :            :
         506         [ #  # ]:          0 :     if (PyLong_Check(arg)) {
         507                 :          0 :         maxsize = PyLong_AsSsize_t(arg);
         508   [ #  #  #  # ]:          0 :         if (maxsize == -1 && PyErr_Occurred())
         509                 :          0 :             return NULL;
         510                 :            :     }
         511         [ #  # ]:          0 :     else if (arg == Py_None) {
         512                 :            :         /* No size limit, by default. */
         513                 :          0 :         maxsize = -1;
         514                 :            :     }
         515                 :            :     else {
         516                 :          0 :         PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
         517                 :          0 :                      Py_TYPE(arg)->tp_name);
         518                 :          0 :         return NULL;
         519                 :            :     }
         520                 :            :
         521                 :          0 :     size = 0;
         522                 :          0 :     result = PyList_New(0);
         523         [ #  # ]:          0 :     if (!result)
         524                 :          0 :         return NULL;
         525                 :            :
         526                 :          0 :     output = PyBytes_AS_STRING(self->buf) + self->pos;
         527         [ #  # ]:          0 :     while ((n = scan_eol(self, -1)) != 0) {
         528                 :          0 :         self->pos += n;
         529                 :          0 :         line = PyBytes_FromStringAndSize(output, n);
         530         [ #  # ]:          0 :         if (!line)
         531                 :          0 :             goto on_error;
         532         [ #  # ]:          0 :         if (PyList_Append(result, line) == -1) {
         533                 :          0 :             Py_DECREF(line);
         534                 :          0 :             goto on_error;
         535                 :            :         }
         536                 :          0 :         Py_DECREF(line);
         537                 :          0 :         size += n;
         538   [ #  #  #  # ]:          0 :         if (maxsize > 0 && size >= maxsize)
         539                 :          0 :             break;
         540                 :          0 :         output += n;
         541                 :            :     }
         542                 :          0 :     return result;
         543                 :            :
         544                 :          0 :   on_error:
         545                 :          0 :     Py_DECREF(result);
         546                 :          0 :     return NULL;
         547                 :            : }
         548                 :            :
         549                 :            : /*[clinic input]
         550                 :            : _io.BytesIO.readinto
         551                 :            :     buffer: Py_buffer(accept={rwbuffer})
         552                 :            :     /
         553                 :            :
         554                 :            : Read bytes into buffer.
         555                 :            :
         556                 :            : Returns number of bytes read (0 for EOF), or None if the object
         557                 :            : is set not to block and has no data to read.
         558                 :            : [clinic start generated code]*/
         559                 :            :
         560                 :            : static PyObject *
         561                 :          0 : _io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
         562                 :            : /*[clinic end generated code: output=a5d407217dcf0639 input=1424d0fdce857919]*/
         563                 :            : {
         564                 :            :     Py_ssize_t len, n;
         565                 :            :
         566         [ #  # ]:          0 :     CHECK_CLOSED(self);
         567                 :            :
         568                 :            :     /* adjust invalid sizes */
         569                 :          0 :     len = buffer->len;
         570                 :          0 :     n = self->string_size - self->pos;
         571         [ #  # ]:          0 :     if (len > n) {
         572                 :          0 :         len = n;
         573         [ #  # ]:          0 :         if (len < 0)
         574                 :          0 :             len = 0;
         575                 :            :     }
         576                 :            :
         577                 :          0 :     memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
         578                 :            :     assert(self->pos + len < PY_SSIZE_T_MAX);
         579                 :            :     assert(len >= 0);
         580                 :          0 :     self->pos += len;
         581                 :            :
         582                 :          0 :     return PyLong_FromSsize_t(len);
         583                 :            : }
         584                 :            :
         585                 :            : /*[clinic input]
         586                 :            : _io.BytesIO.truncate
         587                 :            :     size: Py_ssize_t(accept={int, NoneType}, c_default="self->pos") = None
         588                 :            :     /
         589                 :            :
         590                 :            : Truncate the file to at most size bytes.
         591                 :            :
         592                 :            : Size defaults to the current file position, as returned by tell().
         593                 :            : The current file position is unchanged.  Returns the new size.
         594                 :            : [clinic start generated code]*/
         595                 :            :
         596                 :            : static PyObject *
         597                 :          0 : _io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size)
         598                 :            : /*[clinic end generated code: output=9ad17650c15fa09b input=423759dd42d2f7c1]*/
         599                 :            : {
         600         [ #  # ]:          0 :     CHECK_CLOSED(self);
         601         [ #  # ]:          0 :     CHECK_EXPORTS(self);
         602                 :            :
         603         [ #  # ]:          0 :     if (size < 0) {
         604                 :          0 :         PyErr_Format(PyExc_ValueError,
         605                 :            :                      "negative size value %zd", size);
         606                 :          0 :         return NULL;
         607                 :            :     }
         608                 :            :
         609         [ #  # ]:          0 :     if (size < self->string_size) {
         610                 :          0 :         self->string_size = size;
         611         [ #  # ]:          0 :         if (resize_buffer(self, size) < 0)
         612                 :          0 :             return NULL;
         613                 :            :     }
         614                 :            :
         615                 :          0 :     return PyLong_FromSsize_t(size);
         616                 :            : }
         617                 :            :
         618                 :            : static PyObject *
         619                 :          0 : bytesio_iternext(bytesio *self)
         620                 :            : {
         621                 :            :     Py_ssize_t n;
         622                 :            :
         623         [ #  # ]:          0 :     CHECK_CLOSED(self);
         624                 :            :
         625                 :          0 :     n = scan_eol(self, -1);
         626                 :            :
         627         [ #  # ]:          0 :     if (n == 0)
         628                 :          0 :         return NULL;
         629                 :            :
         630                 :          0 :     return read_bytes(self, n);
         631                 :            : }
         632                 :            :
         633                 :            : /*[clinic input]
         634                 :            : _io.BytesIO.seek
         635                 :            :     pos: Py_ssize_t
         636                 :            :     whence: int = 0
         637                 :            :     /
         638                 :            :
         639                 :            : Change stream position.
         640                 :            :
         641                 :            : Seek to byte offset pos relative to position indicated by whence:
         642                 :            :      0  Start of stream (the default).  pos should be >= 0;
         643                 :            :      1  Current position - pos may be negative;
         644                 :            :      2  End of stream - pos usually negative.
         645                 :            : Returns the new absolute position.
         646                 :            : [clinic start generated code]*/
         647                 :            :
         648                 :            : static PyObject *
         649                 :          0 : _io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence)
         650                 :            : /*[clinic end generated code: output=c26204a68e9190e4 input=1e875e6ebc652948]*/
         651                 :            : {
         652         [ #  # ]:          0 :     CHECK_CLOSED(self);
         653                 :            :
         654   [ #  #  #  # ]:          0 :     if (pos < 0 && whence == 0) {
         655                 :          0 :         PyErr_Format(PyExc_ValueError,
         656                 :            :                      "negative seek value %zd", pos);
         657                 :          0 :         return NULL;
         658                 :            :     }
         659                 :            :
         660                 :            :     /* whence = 0: offset relative to beginning of the string.
         661                 :            :        whence = 1: offset relative to current position.
         662                 :            :        whence = 2: offset relative the end of the string. */
         663         [ #  # ]:          0 :     if (whence == 1) {
         664         [ #  # ]:          0 :         if (pos > PY_SSIZE_T_MAX - self->pos) {
         665                 :          0 :             PyErr_SetString(PyExc_OverflowError,
         666                 :            :                             "new position too large");
         667                 :          0 :             return NULL;
         668                 :            :         }
         669                 :          0 :         pos += self->pos;
         670                 :            :     }
         671         [ #  # ]:          0 :     else if (whence == 2) {
         672         [ #  # ]:          0 :         if (pos > PY_SSIZE_T_MAX - self->string_size) {
         673                 :          0 :             PyErr_SetString(PyExc_OverflowError,
         674                 :            :                             "new position too large");
         675                 :          0 :             return NULL;
         676                 :            :         }
         677                 :          0 :         pos += self->string_size;
         678                 :            :     }
         679         [ #  # ]:          0 :     else if (whence != 0) {
         680                 :          0 :         PyErr_Format(PyExc_ValueError,
         681                 :            :                      "invalid whence (%i, should be 0, 1 or 2)", whence);
         682                 :          0 :         return NULL;
         683                 :            :     }
         684                 :            :
         685         [ #  # ]:          0 :     if (pos < 0)
         686                 :          0 :         pos = 0;
         687                 :          0 :     self->pos = pos;
         688                 :            :
         689                 :          0 :     return PyLong_FromSsize_t(self->pos);
         690                 :            : }
         691                 :            :
         692                 :            : /*[clinic input]
         693                 :            : _io.BytesIO.write
         694                 :            :     b: object
         695                 :            :     /
         696                 :            :
         697                 :            : Write bytes to file.
         698                 :            :
         699                 :            : Return the number of bytes written.
         700                 :            : [clinic start generated code]*/
         701                 :            :
         702                 :            : static PyObject *
         703                 :          0 : _io_BytesIO_write(bytesio *self, PyObject *b)
         704                 :            : /*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/
         705                 :            : {
         706                 :          0 :     Py_ssize_t n = write_bytes(self, b);
         707         [ #  # ]:          0 :     return n >= 0 ? PyLong_FromSsize_t(n) : NULL;
         708                 :            : }
         709                 :            :
         710                 :            : /*[clinic input]
         711                 :            : _io.BytesIO.writelines
         712                 :            :     lines: object
         713                 :            :     /
         714                 :            :
         715                 :            : Write lines to the file.
         716                 :            :
         717                 :            : Note that newlines are not added.  lines can be any iterable object
         718                 :            : producing bytes-like objects. This is equivalent to calling write() for
         719                 :            : each element.
         720                 :            : [clinic start generated code]*/
         721                 :            :
         722                 :            : static PyObject *
         723                 :          0 : _io_BytesIO_writelines(bytesio *self, PyObject *lines)
         724                 :            : /*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/
         725                 :            : {
         726                 :            :     PyObject *it, *item;
         727                 :            :
         728         [ #  # ]:          0 :     CHECK_CLOSED(self);
         729                 :            :
         730                 :          0 :     it = PyObject_GetIter(lines);
         731         [ #  # ]:          0 :     if (it == NULL)
         732                 :          0 :         return NULL;
         733                 :            :
         734         [ #  # ]:          0 :     while ((item = PyIter_Next(it)) != NULL) {
         735                 :          0 :         Py_ssize_t ret = write_bytes(self, item);
         736                 :          0 :         Py_DECREF(item);
         737         [ #  # ]:          0 :         if (ret < 0) {
         738                 :          0 :             Py_DECREF(it);
         739                 :          0 :             return NULL;
         740                 :            :         }
         741                 :            :     }
         742                 :          0 :     Py_DECREF(it);
         743                 :            :
         744                 :            :     /* See if PyIter_Next failed */
         745         [ #  # ]:          0 :     if (PyErr_Occurred())
         746                 :          0 :         return NULL;
         747                 :            :
         748                 :          0 :     Py_RETURN_NONE;
         749                 :            : }
         750                 :            :
         751                 :            : /*[clinic input]
         752                 :            : _io.BytesIO.close
         753                 :            :
         754                 :            : Disable all I/O operations.
         755                 :            : [clinic start generated code]*/
         756                 :            :
         757                 :            : static PyObject *
         758                 :          0 : _io_BytesIO_close_impl(bytesio *self)
         759                 :            : /*[clinic end generated code: output=1471bb9411af84a0 input=37e1f55556e61f60]*/
         760                 :            : {
         761         [ #  # ]:          0 :     CHECK_EXPORTS(self);
         762         [ #  # ]:          0 :     Py_CLEAR(self->buf);
         763                 :          0 :     Py_RETURN_NONE;
         764                 :            : }
         765                 :            :
         766                 :            : /* Pickling support.
         767                 :            :
         768                 :            :    Note that only pickle protocol 2 and onward are supported since we use
         769                 :            :    extended __reduce__ API of PEP 307 to make BytesIO instances picklable.
         770                 :            :
         771                 :            :    Providing support for protocol < 2 would require the __reduce_ex__ method
         772                 :            :    which is notably long-winded when defined properly.
         773                 :            :
         774                 :            :    For BytesIO, the implementation would similar to one coded for
         775                 :            :    object.__reduce_ex__, but slightly less general. To be more specific, we
         776                 :            :    could call bytesio_getstate directly and avoid checking for the presence of
         777                 :            :    a fallback __reduce__ method. However, we would still need a __newobj__
         778                 :            :    function to use the efficient instance representation of PEP 307.
         779                 :            :  */
         780                 :            :
         781                 :            : static PyObject *
         782                 :          0 : bytesio_getstate(bytesio *self, PyObject *Py_UNUSED(ignored))
         783                 :            : {
         784                 :          0 :     PyObject *initvalue = _io_BytesIO_getvalue_impl(self);
         785                 :            :     PyObject *dict;
         786                 :            :     PyObject *state;
         787                 :            :
         788         [ #  # ]:          0 :     if (initvalue == NULL)
         789                 :          0 :         return NULL;
         790         [ #  # ]:          0 :     if (self->dict == NULL) {
         791                 :          0 :         dict = Py_NewRef(Py_None);
         792                 :            :     }
         793                 :            :     else {
         794                 :          0 :         dict = PyDict_Copy(self->dict);
         795         [ #  # ]:          0 :         if (dict == NULL) {
         796                 :          0 :             Py_DECREF(initvalue);
         797                 :          0 :             return NULL;
         798                 :            :         }
         799                 :            :     }
         800                 :            :
         801                 :          0 :     state = Py_BuildValue("(OnN)", initvalue, self->pos, dict);
         802                 :          0 :     Py_DECREF(initvalue);
         803                 :          0 :     return state;
         804                 :            : }
         805                 :            :
         806                 :            : static PyObject *
         807                 :          0 : bytesio_setstate(bytesio *self, PyObject *state)
         808                 :            : {
         809                 :            :     PyObject *result;
         810                 :            :     PyObject *position_obj;
         811                 :            :     PyObject *dict;
         812                 :            :     Py_ssize_t pos;
         813                 :            :
         814                 :            :     assert(state != NULL);
         815                 :            :
         816                 :            :     /* We allow the state tuple to be longer than 3, because we may need
         817                 :            :        someday to extend the object's state without breaking
         818                 :            :        backward-compatibility. */
         819   [ #  #  #  # ]:          0 :     if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) < 3) {
         820                 :          0 :         PyErr_Format(PyExc_TypeError,
         821                 :            :                      "%.200s.__setstate__ argument should be 3-tuple, got %.200s",
         822                 :          0 :                      Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
         823                 :          0 :         return NULL;
         824                 :            :     }
         825         [ #  # ]:          0 :     CHECK_EXPORTS(self);
         826                 :            :     /* Reset the object to its default state. This is only needed to handle
         827                 :            :        the case of repeated calls to __setstate__. */
         828                 :          0 :     self->string_size = 0;
         829                 :          0 :     self->pos = 0;
         830                 :            :
         831                 :            :     /* Set the value of the internal buffer. If state[0] does not support the
         832                 :            :        buffer protocol, bytesio_write will raise the appropriate TypeError. */
         833                 :          0 :     result = _io_BytesIO_write(self, PyTuple_GET_ITEM(state, 0));
         834         [ #  # ]:          0 :     if (result == NULL)
         835                 :          0 :         return NULL;
         836                 :          0 :     Py_DECREF(result);
         837                 :            :
         838                 :            :     /* Set carefully the position value. Alternatively, we could use the seek
         839                 :            :        method instead of modifying self->pos directly to better protect the
         840                 :            :        object internal state against erroneous (or malicious) inputs. */
         841                 :          0 :     position_obj = PyTuple_GET_ITEM(state, 1);
         842         [ #  # ]:          0 :     if (!PyLong_Check(position_obj)) {
         843                 :          0 :         PyErr_Format(PyExc_TypeError,
         844                 :            :                      "second item of state must be an integer, not %.200s",
         845                 :          0 :                      Py_TYPE(position_obj)->tp_name);
         846                 :          0 :         return NULL;
         847                 :            :     }
         848                 :          0 :     pos = PyLong_AsSsize_t(position_obj);
         849   [ #  #  #  # ]:          0 :     if (pos == -1 && PyErr_Occurred())
         850                 :          0 :         return NULL;
         851         [ #  # ]:          0 :     if (pos < 0) {
         852                 :          0 :         PyErr_SetString(PyExc_ValueError,
         853                 :            :                         "position value cannot be negative");
         854                 :          0 :         return NULL;
         855                 :            :     }
         856                 :          0 :     self->pos = pos;
         857                 :            :
         858                 :            :     /* Set the dictionary of the instance variables. */
         859                 :          0 :     dict = PyTuple_GET_ITEM(state, 2);
         860         [ #  # ]:          0 :     if (dict != Py_None) {
         861         [ #  # ]:          0 :         if (!PyDict_Check(dict)) {
         862                 :          0 :             PyErr_Format(PyExc_TypeError,
         863                 :            :                          "third item of state should be a dict, got a %.200s",
         864                 :          0 :                          Py_TYPE(dict)->tp_name);
         865                 :          0 :             return NULL;
         866                 :            :         }
         867         [ #  # ]:          0 :         if (self->dict) {
         868                 :            :             /* Alternatively, we could replace the internal dictionary
         869                 :            :                completely. However, it seems more practical to just update it. */
         870         [ #  # ]:          0 :             if (PyDict_Update(self->dict, dict) < 0)
         871                 :          0 :                 return NULL;
         872                 :            :         }
         873                 :            :         else {
         874                 :          0 :             self->dict = Py_NewRef(dict);
         875                 :            :         }
         876                 :            :     }
         877                 :            :
         878                 :          0 :     Py_RETURN_NONE;
         879                 :            : }
         880                 :            :
         881                 :            : static void
         882                 :          0 : bytesio_dealloc(bytesio *self)
         883                 :            : {
         884                 :          0 :     PyTypeObject *tp = Py_TYPE(self);
         885                 :          0 :     _PyObject_GC_UNTRACK(self);
         886         [ #  # ]:          0 :     if (self->exports > 0) {
         887                 :          0 :         PyErr_SetString(PyExc_SystemError,
         888                 :            :                         "deallocated BytesIO object has exported buffers");
         889                 :          0 :         PyErr_Print();
         890                 :            :     }
         891         [ #  # ]:          0 :     Py_CLEAR(self->buf);
         892         [ #  # ]:          0 :     Py_CLEAR(self->dict);
         893         [ #  # ]:          0 :     if (self->weakreflist != NULL)
         894                 :          0 :         PyObject_ClearWeakRefs((PyObject *) self);
         895                 :          0 :     tp->tp_free(self);
         896                 :          0 :     Py_DECREF(tp);
         897                 :          0 : }
         898                 :            :
         899                 :            : static PyObject *
         900                 :          0 : bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         901                 :            : {
         902                 :            :     bytesio *self;
         903                 :            :
         904                 :            :     assert(type != NULL && type->tp_alloc != NULL);
         905                 :          0 :     self = (bytesio *)type->tp_alloc(type, 0);
         906         [ #  # ]:          0 :     if (self == NULL)
         907                 :          0 :         return NULL;
         908                 :            :
         909                 :            :     /* tp_alloc initializes all the fields to zero. So we don't have to
         910                 :            :        initialize them here. */
         911                 :            :
         912                 :          0 :     self->buf = PyBytes_FromStringAndSize(NULL, 0);
         913         [ #  # ]:          0 :     if (self->buf == NULL) {
         914                 :          0 :         Py_DECREF(self);
         915                 :          0 :         return PyErr_NoMemory();
         916                 :            :     }
         917                 :            :
         918                 :          0 :     return (PyObject *)self;
         919                 :            : }
         920                 :            :
         921                 :            : /*[clinic input]
         922                 :            : _io.BytesIO.__init__
         923                 :            :     initial_bytes as initvalue: object(c_default="NULL") = b''
         924                 :            :
         925                 :            : Buffered I/O implementation using an in-memory bytes buffer.
         926                 :            : [clinic start generated code]*/
         927                 :            :
         928                 :            : static int
         929                 :          0 : _io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
         930                 :            : /*[clinic end generated code: output=65c0c51e24c5b621 input=aac7f31b67bf0fb6]*/
         931                 :            : {
         932                 :            :     /* In case, __init__ is called multiple times. */
         933                 :          0 :     self->string_size = 0;
         934                 :          0 :     self->pos = 0;
         935                 :            :
         936         [ #  # ]:          0 :     if (self->exports > 0) {
         937                 :          0 :         PyErr_SetString(PyExc_BufferError,
         938                 :            :                         "Existing exports of data: object cannot be re-sized");
         939                 :          0 :         return -1;
         940                 :            :     }
         941   [ #  #  #  # ]:          0 :     if (initvalue && initvalue != Py_None) {
         942         [ #  # ]:          0 :         if (PyBytes_CheckExact(initvalue)) {
         943                 :          0 :             Py_XSETREF(self->buf, Py_NewRef(initvalue));
         944                 :          0 :             self->string_size = PyBytes_GET_SIZE(initvalue);
         945                 :            :         }
         946                 :            :         else {
         947                 :            :             PyObject *res;
         948                 :          0 :             res = _io_BytesIO_write(self, initvalue);
         949         [ #  # ]:          0 :             if (res == NULL)
         950                 :          0 :                 return -1;
         951                 :          0 :             Py_DECREF(res);
         952                 :          0 :             self->pos = 0;
         953                 :            :         }
         954                 :            :     }
         955                 :            :
         956                 :          0 :     return 0;
         957                 :            : }
         958                 :            :
         959                 :            : static PyObject *
         960                 :          0 : bytesio_sizeof(bytesio *self, void *unused)
         961                 :            : {
         962                 :          0 :     size_t res = _PyObject_SIZE(Py_TYPE(self));
         963   [ #  #  #  # ]:          0 :     if (self->buf && !SHARED_BUF(self)) {
         964                 :          0 :         size_t s = _PySys_GetSizeOf(self->buf);
         965         [ #  # ]:          0 :         if (s == (size_t)-1) {
         966                 :          0 :             return NULL;
         967                 :            :         }
         968                 :          0 :         res += s;
         969                 :            :     }
         970                 :          0 :     return PyLong_FromSize_t(res);
         971                 :            : }
         972                 :            :
         973                 :            : static int
         974                 :          0 : bytesio_traverse(bytesio *self, visitproc visit, void *arg)
         975                 :            : {
         976   [ #  #  #  # ]:          0 :     Py_VISIT(Py_TYPE(self));
         977   [ #  #  #  # ]:          0 :     Py_VISIT(self->dict);
         978                 :          0 :     return 0;
         979                 :            : }
         980                 :            :
         981                 :            : static int
         982                 :          0 : bytesio_clear(bytesio *self)
         983                 :            : {
         984         [ #  # ]:          0 :     Py_CLEAR(self->dict);
         985                 :          0 :     return 0;
         986                 :            : }
         987                 :            :
         988                 :            :
         989                 :            : #define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
         990                 :            : #include "clinic/bytesio.c.h"
         991                 :            : #undef clinic_state
         992                 :            :
         993                 :            : static PyGetSetDef bytesio_getsetlist[] = {
         994                 :            :     {"closed",  (getter)bytesio_get_closed, NULL,
         995                 :            :      "True if the file is closed."},
         996                 :            :     {NULL},            /* sentinel */
         997                 :            : };
         998                 :            :
         999                 :            : static struct PyMethodDef bytesio_methods[] = {
        1000                 :            :     _IO_BYTESIO_READABLE_METHODDEF
        1001                 :            :     _IO_BYTESIO_SEEKABLE_METHODDEF
        1002                 :            :     _IO_BYTESIO_WRITABLE_METHODDEF
        1003                 :            :     _IO_BYTESIO_CLOSE_METHODDEF
        1004                 :            :     _IO_BYTESIO_FLUSH_METHODDEF
        1005                 :            :     _IO_BYTESIO_ISATTY_METHODDEF
        1006                 :            :     _IO_BYTESIO_TELL_METHODDEF
        1007                 :            :     _IO_BYTESIO_WRITE_METHODDEF
        1008                 :            :     _IO_BYTESIO_WRITELINES_METHODDEF
        1009                 :            :     _IO_BYTESIO_READ1_METHODDEF
        1010                 :            :     _IO_BYTESIO_READINTO_METHODDEF
        1011                 :            :     _IO_BYTESIO_READLINE_METHODDEF
        1012                 :            :     _IO_BYTESIO_READLINES_METHODDEF
        1013                 :            :     _IO_BYTESIO_READ_METHODDEF
        1014                 :            :     _IO_BYTESIO_GETBUFFER_METHODDEF
        1015                 :            :     _IO_BYTESIO_GETVALUE_METHODDEF
        1016                 :            :     _IO_BYTESIO_SEEK_METHODDEF
        1017                 :            :     _IO_BYTESIO_TRUNCATE_METHODDEF
        1018                 :            :     {"__getstate__",  (PyCFunction)bytesio_getstate,  METH_NOARGS, NULL},
        1019                 :            :     {"__setstate__",  (PyCFunction)bytesio_setstate,  METH_O, NULL},
        1020                 :            :     {"__sizeof__", (PyCFunction)bytesio_sizeof,     METH_NOARGS, NULL},
        1021                 :            :     {NULL, NULL}        /* sentinel */
        1022                 :            : };
        1023                 :            :
        1024                 :            : static PyMemberDef bytesio_members[] = {
        1025                 :            :     {"__weaklistoffset__", T_PYSSIZET, offsetof(bytesio, weakreflist), READONLY},
        1026                 :            :     {"__dictoffset__", T_PYSSIZET, offsetof(bytesio, dict), READONLY},
        1027                 :            :     {NULL}
        1028                 :            : };
        1029                 :            :
        1030                 :            : static PyType_Slot bytesio_slots[] = {
        1031                 :            :     {Py_tp_dealloc, bytesio_dealloc},
        1032                 :            :     {Py_tp_doc, (void *)_io_BytesIO___init____doc__},
        1033                 :            :     {Py_tp_traverse, bytesio_traverse},
        1034                 :            :     {Py_tp_clear, bytesio_clear},
        1035                 :            :     {Py_tp_iter, PyObject_SelfIter},
        1036                 :            :     {Py_tp_iternext, bytesio_iternext},
        1037                 :            :     {Py_tp_methods, bytesio_methods},
        1038                 :            :     {Py_tp_members, bytesio_members},
        1039                 :            :     {Py_tp_getset, bytesio_getsetlist},
        1040                 :            :     {Py_tp_init, _io_BytesIO___init__},
        1041                 :            :     {Py_tp_new, bytesio_new},
        1042                 :            :     {0, NULL},
        1043                 :            : };
        1044                 :            :
        1045                 :            : PyType_Spec bytesio_spec = {
        1046                 :            :     .name = "_io.BytesIO",
        1047                 :            :     .basicsize = sizeof(bytesio),
        1048                 :            :     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
        1049                 :            :               Py_TPFLAGS_IMMUTABLETYPE),
        1050                 :            :     .slots = bytesio_slots,
        1051                 :            : };
        1052                 :            :
        1053                 :            : /*
        1054                 :            :  * Implementation of the small intermediate object used by getbuffer().
        1055                 :            :  * getbuffer() returns a memoryview over this object, which should make it
        1056                 :            :  * invisible from Python code.
        1057                 :            :  */
        1058                 :            :
        1059                 :            : static int
        1060                 :          0 : bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
        1061                 :            : {
        1062                 :          0 :     bytesio *b = (bytesio *) obj->source;
        1063                 :            :
        1064         [ #  # ]:          0 :     if (view == NULL) {
        1065                 :          0 :         PyErr_SetString(PyExc_BufferError,
        1066                 :            :             "bytesiobuf_getbuffer: view==NULL argument is obsolete");
        1067                 :          0 :         return -1;
        1068                 :            :     }
        1069         [ #  # ]:          0 :     if (SHARED_BUF(b)) {
        1070         [ #  # ]:          0 :         if (unshare_buffer(b, b->string_size) < 0)
        1071                 :          0 :             return -1;
        1072                 :            :     }
        1073                 :            :
        1074                 :            :     /* cannot fail if view != NULL and readonly == 0 */
        1075                 :          0 :     (void)PyBuffer_FillInfo(view, (PyObject*)obj,
        1076                 :          0 :                             PyBytes_AS_STRING(b->buf), b->string_size,
        1077                 :            :                             0, flags);
        1078                 :          0 :     b->exports++;
        1079                 :          0 :     return 0;
        1080                 :            : }
        1081                 :            :
        1082                 :            : static void
        1083                 :          0 : bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view)
        1084                 :            : {
        1085                 :          0 :     bytesio *b = (bytesio *) obj->source;
        1086                 :          0 :     b->exports--;
        1087                 :          0 : }
        1088                 :            :
        1089                 :            : static int
        1090                 :          0 : bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg)
        1091                 :            : {
        1092   [ #  #  #  # ]:          0 :     Py_VISIT(self->source);
        1093                 :          0 :     return 0;
        1094                 :            : }
        1095                 :            :
        1096                 :            : static void
        1097                 :          0 : bytesiobuf_dealloc(bytesiobuf *self)
        1098                 :            : {
        1099                 :            :     /* bpo-31095: UnTrack is needed before calling any callbacks */
        1100                 :          0 :     PyObject_GC_UnTrack(self);
        1101         [ #  # ]:          0 :     Py_CLEAR(self->source);
        1102                 :          0 :     Py_TYPE(self)->tp_free(self);
        1103                 :          0 : }
        1104                 :            :
        1105                 :            : static PyBufferProcs bytesiobuf_as_buffer = {
        1106                 :            :     (getbufferproc) bytesiobuf_getbuffer,
        1107                 :            :     (releasebufferproc) bytesiobuf_releasebuffer,
        1108                 :            : };
        1109                 :            :
        1110                 :            : Py_EXPORTED_SYMBOL PyTypeObject _PyBytesIOBuffer_Type = {
        1111                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        1112                 :            :     "_io._BytesIOBuffer",                      /*tp_name*/
        1113                 :            :     sizeof(bytesiobuf),                        /*tp_basicsize*/
        1114                 :            :     0,                                         /*tp_itemsize*/
        1115                 :            :     (destructor)bytesiobuf_dealloc,            /*tp_dealloc*/
        1116                 :            :     0,                                         /*tp_vectorcall_offset*/
        1117                 :            :     0,                                         /*tp_getattr*/
        1118                 :            :     0,                                         /*tp_setattr*/
        1119                 :            :     0,                                         /*tp_as_async*/
        1120                 :            :     0,                                         /*tp_repr*/
        1121                 :            :     0,                                         /*tp_as_number*/
        1122                 :            :     0,                                         /*tp_as_sequence*/
        1123                 :            :     0,                                         /*tp_as_mapping*/
        1124                 :            :     0,                                         /*tp_hash*/
        1125                 :            :     0,                                         /*tp_call*/
        1126                 :            :     0,                                         /*tp_str*/
        1127                 :            :     0,                                         /*tp_getattro*/
        1128                 :            :     0,                                         /*tp_setattro*/
        1129                 :            :     &bytesiobuf_as_buffer,                     /*tp_as_buffer*/
        1130                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
        1131                 :            :     0,                                         /*tp_doc*/
        1132                 :            :     (traverseproc)bytesiobuf_traverse,         /*tp_traverse*/
        1133                 :            :     0,                                         /*tp_clear*/
        1134                 :            :     0,                                         /*tp_richcompare*/
        1135                 :            :     0,                                         /*tp_weaklistoffset*/
        1136                 :            :     0,                                         /*tp_iter*/
        1137                 :            :     0,                                         /*tp_iternext*/
        1138                 :            :     0,                                         /*tp_methods*/
        1139                 :            :     0,                                         /*tp_members*/
        1140                 :            :     0,                                         /*tp_getset*/
        1141                 :            :     0,                                         /*tp_base*/
        1142                 :            :     0,                                         /*tp_dict*/
        1143                 :            :     0,                                         /*tp_descr_get*/
        1144                 :            :     0,                                         /*tp_descr_set*/
        1145                 :            :     0,                                         /*tp_dictoffset*/
        1146                 :            :     0,                                         /*tp_init*/
        1147                 :            :     0,                                         /*tp_alloc*/
        1148                 :            :     0,                                         /*tp_new*/
        1149                 :            : };

Generated by: LCOV version 1.14