LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules/_io - bytesio.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 370 0.0 %
Date: 2012-12-17 Functions: 0 33 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10