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