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 : };
|