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 : } 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
26 0 : 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 0 : str_end = self->buf + self->string_size;
36 0 : for (n = self->buf + self->pos;
37 0 : n < str_end && *n != '\n';
38 0 : n++);
39 :
40 : /* Skip the newline character */
41 0 : if (n < str_end)
42 0 : n++;
43 :
44 : /* Get the length from the current position to the end of the line. */
45 0 : len = n - (self->buf + self->pos);
46 0 : *output = self->buf + self->pos;
47 :
48 : assert(len >= 0);
49 : assert(self->pos < PY_SSIZE_T_MAX - len);
50 0 : self->pos += len;
51 :
52 0 : 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
59 0 : 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 0 : size_t alloc = self->buf_size;
64 0 : 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 0 : if (size > PY_SSIZE_T_MAX)
71 0 : goto overflow;
72 :
73 0 : if (size < alloc / 2) {
74 : /* Major downsize; resize down to exact size. */
75 0 : alloc = size + 1;
76 : }
77 0 : else if (size < alloc) {
78 : /* Within allocated size; quick exit */
79 0 : return 0;
80 : }
81 0 : else if (size <= alloc * 1.125) {
82 : /* Moderate upsize; overallocate similar to list_resize() */
83 0 : alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
84 : }
85 : else {
86 : /* Major upsize; resize up to exact size */
87 0 : alloc = size + 1;
88 : }
89 :
90 : if (alloc > ((size_t)-1) / sizeof(char))
91 : goto overflow;
92 0 : new_buf = (char *)PyMem_Realloc(self->buf, alloc * sizeof(char));
93 0 : if (new_buf == NULL) {
94 0 : PyErr_NoMemory();
95 0 : return -1;
96 : }
97 0 : self->buf_size = alloc;
98 0 : self->buf = new_buf;
99 :
100 0 : return 0;
101 :
102 : overflow:
103 0 : PyErr_SetString(PyExc_OverflowError,
104 : "new buffer size too large");
105 0 : 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
111 0 : 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 0 : if ((size_t)self->pos + len > self->buf_size) {
118 0 : if (resize_buffer(self, (size_t)self->pos + len) < 0)
119 0 : return -1;
120 : }
121 :
122 0 : 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 0 : memset(self->buf + self->string_size, '\0',
132 0 : (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 0 : memcpy(self->buf + self->pos, bytes, len);
138 0 : self->pos += len;
139 :
140 : /* Set the new length of the internal string if it has changed. */
141 0 : if (self->string_size < self->pos) {
142 0 : self->string_size = self->pos;
143 : }
144 :
145 0 : return len;
146 : }
147 :
148 : static PyObject *
149 0 : bytesio_get_closed(bytesio *self)
150 : {
151 0 : if (self->buf == NULL) {
152 0 : Py_RETURN_TRUE;
153 : }
154 : else {
155 0 : 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 *
170 0 : return_not_closed(bytesio *self)
171 : {
172 0 : CHECK_CLOSED(self);
173 0 : Py_RETURN_TRUE;
174 : }
175 :
176 : PyDoc_STRVAR(flush_doc,
177 : "flush() -> None. Does nothing.");
178 :
179 : static PyObject *
180 0 : bytesio_flush(bytesio *self)
181 : {
182 0 : CHECK_CLOSED(self);
183 0 : 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 *
192 0 : bytesio_getvalue(bytesio *self)
193 : {
194 0 : CHECK_CLOSED(self);
195 0 : 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 *
205 0 : bytesio_isatty(bytesio *self)
206 : {
207 0 : CHECK_CLOSED(self);
208 0 : Py_RETURN_FALSE;
209 : }
210 :
211 : PyDoc_STRVAR(tell_doc,
212 : "tell() -> current file position, an integer\n");
213 :
214 : static PyObject *
215 0 : bytesio_tell(bytesio *self)
216 : {
217 0 : CHECK_CLOSED(self);
218 0 : 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 *
228 0 : bytesio_read(bytesio *self, PyObject *args)
229 : {
230 : Py_ssize_t size, n;
231 : char *output;
232 0 : PyObject *arg = Py_None;
233 :
234 0 : CHECK_CLOSED(self);
235 :
236 0 : if (!PyArg_ParseTuple(args, "|O:read", &arg))
237 0 : return NULL;
238 :
239 0 : if (PyNumber_Check(arg)) {
240 0 : size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
241 0 : if (size == -1 && PyErr_Occurred())
242 0 : return NULL;
243 : }
244 0 : else if (arg == Py_None) {
245 : /* Read until EOF is reached, by default. */
246 0 : size = -1;
247 : }
248 : else {
249 0 : PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
250 0 : Py_TYPE(arg)->tp_name);
251 0 : return NULL;
252 : }
253 :
254 : /* adjust invalid sizes */
255 0 : n = self->string_size - self->pos;
256 0 : if (size < 0 || size > n) {
257 0 : size = n;
258 0 : if (size < 0)
259 0 : size = 0;
260 : }
261 :
262 : assert(self->buf != NULL);
263 0 : output = self->buf + self->pos;
264 0 : self->pos += size;
265 :
266 0 : 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 *
277 0 : bytesio_read1(bytesio *self, PyObject *n)
278 : {
279 : PyObject *arg, *res;
280 :
281 0 : arg = PyTuple_Pack(1, n);
282 0 : if (arg == NULL)
283 0 : return NULL;
284 0 : res = bytesio_read(self, arg);
285 0 : Py_DECREF(arg);
286 0 : 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 *
297 0 : bytesio_readline(bytesio *self, PyObject *args)
298 : {
299 : Py_ssize_t size, n;
300 : char *output;
301 0 : PyObject *arg = Py_None;
302 :
303 0 : CHECK_CLOSED(self);
304 :
305 0 : if (!PyArg_ParseTuple(args, "|O:readline", &arg))
306 0 : return NULL;
307 :
308 0 : if (PyNumber_Check(arg)) {
309 0 : size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
310 0 : if (size == -1 && PyErr_Occurred())
311 0 : return NULL;
312 : }
313 0 : else if (arg == Py_None) {
314 : /* No size limit, by default. */
315 0 : size = -1;
316 : }
317 : else {
318 0 : PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
319 0 : Py_TYPE(arg)->tp_name);
320 0 : return NULL;
321 : }
322 :
323 0 : n = get_line(self, &output);
324 :
325 0 : if (size >= 0 && size < n) {
326 0 : size = n - size;
327 0 : n -= size;
328 0 : self->pos -= size;
329 : }
330 :
331 0 : 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 *
342 0 : bytesio_readlines(bytesio *self, PyObject *args)
343 : {
344 : Py_ssize_t maxsize, size, n;
345 : PyObject *result, *line;
346 : char *output;
347 0 : PyObject *arg = Py_None;
348 :
349 0 : CHECK_CLOSED(self);
350 :
351 0 : if (!PyArg_ParseTuple(args, "|O:readlines", &arg))
352 0 : return NULL;
353 :
354 0 : if (PyNumber_Check(arg)) {
355 0 : maxsize = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
356 0 : if (maxsize == -1 && PyErr_Occurred())
357 0 : return NULL;
358 : }
359 0 : else if (arg == Py_None) {
360 : /* No size limit, by default. */
361 0 : maxsize = -1;
362 : }
363 : else {
364 0 : PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
365 0 : Py_TYPE(arg)->tp_name);
366 0 : return NULL;
367 : }
368 :
369 0 : size = 0;
370 0 : result = PyList_New(0);
371 0 : if (!result)
372 0 : return NULL;
373 :
374 0 : while ((n = get_line(self, &output)) != 0) {
375 0 : line = PyBytes_FromStringAndSize(output, n);
376 0 : if (!line)
377 0 : goto on_error;
378 0 : if (PyList_Append(result, line) == -1) {
379 0 : Py_DECREF(line);
380 0 : goto on_error;
381 : }
382 0 : Py_DECREF(line);
383 0 : size += n;
384 0 : if (maxsize > 0 && size >= maxsize)
385 0 : break;
386 : }
387 0 : return result;
388 :
389 : on_error:
390 0 : Py_DECREF(result);
391 0 : 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 *
401 0 : bytesio_readinto(bytesio *self, PyObject *args)
402 : {
403 : Py_buffer buf;
404 : Py_ssize_t len, n;
405 :
406 0 : CHECK_CLOSED(self);
407 :
408 0 : if (!PyArg_ParseTuple(args, "w*", &buf))
409 0 : return NULL;
410 :
411 0 : len = buf.len;
412 : /* adjust invalid sizes */
413 0 : n = self->string_size - self->pos;
414 0 : if (len > n) {
415 0 : len = n;
416 0 : if (len < 0)
417 0 : len = 0;
418 : }
419 :
420 0 : memcpy(buf.buf, self->buf + self->pos, len);
421 : assert(self->pos + len < PY_SSIZE_T_MAX);
422 : assert(len >= 0);
423 0 : self->pos += len;
424 :
425 0 : PyBuffer_Release(&buf);
426 0 : 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 *
436 0 : bytesio_truncate(bytesio *self, PyObject *args)
437 : {
438 : Py_ssize_t size;
439 0 : PyObject *arg = Py_None;
440 :
441 0 : CHECK_CLOSED(self);
442 :
443 0 : if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
444 0 : return NULL;
445 :
446 0 : if (PyNumber_Check(arg)) {
447 0 : size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
448 0 : if (size == -1 && PyErr_Occurred())
449 0 : return NULL;
450 : }
451 0 : else if (arg == Py_None) {
452 : /* Truncate to current position if no argument is passed. */
453 0 : size = self->pos;
454 : }
455 : else {
456 0 : PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
457 0 : Py_TYPE(arg)->tp_name);
458 0 : return NULL;
459 : }
460 :
461 0 : if (size < 0) {
462 0 : PyErr_Format(PyExc_ValueError,
463 : "negative size value %zd", size);
464 0 : return NULL;
465 : }
466 :
467 0 : if (size < self->string_size) {
468 0 : self->string_size = size;
469 0 : if (resize_buffer(self, size) < 0)
470 0 : return NULL;
471 : }
472 :
473 0 : return PyLong_FromSsize_t(size);
474 : }
475 :
476 : static PyObject *
477 0 : bytesio_iternext(bytesio *self)
478 : {
479 : char *next;
480 : Py_ssize_t n;
481 :
482 0 : CHECK_CLOSED(self);
483 :
484 0 : n = get_line(self, &next);
485 :
486 0 : if (!next || n == 0)
487 0 : return NULL;
488 :
489 0 : 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 *
502 0 : bytesio_seek(bytesio *self, PyObject *args)
503 : {
504 : PyObject *posobj;
505 : Py_ssize_t pos;
506 0 : int mode = 0;
507 :
508 0 : CHECK_CLOSED(self);
509 :
510 0 : if (!PyArg_ParseTuple(args, "O|i:seek", &posobj, &mode))
511 0 : return NULL;
512 :
513 0 : pos = PyNumber_AsSsize_t(posobj, PyExc_OverflowError);
514 0 : if (pos == -1 && PyErr_Occurred())
515 0 : return NULL;
516 :
517 0 : if (pos < 0 && mode == 0) {
518 0 : PyErr_Format(PyExc_ValueError,
519 : "negative seek value %zd", pos);
520 0 : 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 0 : if (mode == 1) {
527 0 : if (pos > PY_SSIZE_T_MAX - self->pos) {
528 0 : PyErr_SetString(PyExc_OverflowError,
529 : "new position too large");
530 0 : return NULL;
531 : }
532 0 : pos += self->pos;
533 : }
534 0 : else if (mode == 2) {
535 0 : if (pos > PY_SSIZE_T_MAX - self->string_size) {
536 0 : PyErr_SetString(PyExc_OverflowError,
537 : "new position too large");
538 0 : return NULL;
539 : }
540 0 : pos += self->string_size;
541 : }
542 0 : else if (mode != 0) {
543 0 : PyErr_Format(PyExc_ValueError,
544 : "invalid whence (%i, should be 0, 1 or 2)", mode);
545 0 : return NULL;
546 : }
547 :
548 0 : if (pos < 0)
549 0 : pos = 0;
550 0 : self->pos = pos;
551 :
552 0 : 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 *
561 0 : bytesio_write(bytesio *self, PyObject *obj)
562 : {
563 0 : Py_ssize_t n = 0;
564 : Py_buffer buf;
565 0 : PyObject *result = NULL;
566 :
567 0 : CHECK_CLOSED(self);
568 :
569 0 : if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0)
570 0 : return NULL;
571 :
572 0 : if (buf.len != 0)
573 0 : n = write_bytes(self, buf.buf, buf.len);
574 0 : if (n >= 0)
575 0 : result = PyLong_FromSsize_t(n);
576 :
577 0 : PyBuffer_Release(&buf);
578 0 : 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 *
589 0 : bytesio_writelines(bytesio *self, PyObject *v)
590 : {
591 : PyObject *it, *item;
592 : PyObject *ret;
593 :
594 0 : CHECK_CLOSED(self);
595 :
596 0 : it = PyObject_GetIter(v);
597 0 : if (it == NULL)
598 0 : return NULL;
599 :
600 0 : while ((item = PyIter_Next(it)) != NULL) {
601 0 : ret = bytesio_write(self, item);
602 0 : Py_DECREF(item);
603 0 : if (ret == NULL) {
604 0 : Py_DECREF(it);
605 0 : return NULL;
606 : }
607 0 : Py_DECREF(ret);
608 : }
609 0 : Py_DECREF(it);
610 :
611 : /* See if PyIter_Next failed */
612 0 : if (PyErr_Occurred())
613 0 : return NULL;
614 :
615 0 : Py_RETURN_NONE;
616 : }
617 :
618 : PyDoc_STRVAR(close_doc,
619 : "close() -> None. Disable all I/O operations.");
620 :
621 : static PyObject *
622 0 : bytesio_close(bytesio *self)
623 : {
624 0 : if (self->buf != NULL) {
625 0 : PyMem_Free(self->buf);
626 0 : self->buf = NULL;
627 : }
628 0 : 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 *
647 0 : bytesio_getstate(bytesio *self)
648 : {
649 0 : PyObject *initvalue = bytesio_getvalue(self);
650 : PyObject *dict;
651 : PyObject *state;
652 :
653 0 : if (initvalue == NULL)
654 0 : return NULL;
655 0 : if (self->dict == NULL) {
656 0 : Py_INCREF(Py_None);
657 0 : dict = Py_None;
658 : }
659 : else {
660 0 : dict = PyDict_Copy(self->dict);
661 0 : if (dict == NULL)
662 0 : return NULL;
663 : }
664 :
665 0 : state = Py_BuildValue("(OnN)", initvalue, self->pos, dict);
666 0 : Py_DECREF(initvalue);
667 0 : return state;
668 : }
669 :
670 : static PyObject *
671 0 : 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 0 : if (!PyTuple_Check(state) || Py_SIZE(state) < 3) {
684 0 : PyErr_Format(PyExc_TypeError,
685 : "%.200s.__setstate__ argument should be 3-tuple, got %.200s",
686 0 : Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
687 0 : 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 0 : self->string_size = 0;
692 0 : 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 0 : result = bytesio_write(self, PyTuple_GET_ITEM(state, 0));
697 0 : if (result == NULL)
698 0 : return NULL;
699 0 : 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 0 : position_obj = PyTuple_GET_ITEM(state, 1);
705 0 : if (!PyIndex_Check(position_obj)) {
706 0 : PyErr_Format(PyExc_TypeError,
707 : "second item of state must be an integer, not %.200s",
708 0 : Py_TYPE(position_obj)->tp_name);
709 0 : return NULL;
710 : }
711 0 : pos = PyNumber_AsSsize_t(position_obj, PyExc_OverflowError);
712 0 : if (pos == -1 && PyErr_Occurred())
713 0 : return NULL;
714 0 : if (pos < 0) {
715 0 : PyErr_SetString(PyExc_ValueError,
716 : "position value cannot be negative");
717 0 : return NULL;
718 : }
719 0 : self->pos = pos;
720 :
721 : /* Set the dictionary of the instance variables. */
722 0 : dict = PyTuple_GET_ITEM(state, 2);
723 0 : if (dict != Py_None) {
724 0 : if (!PyDict_Check(dict)) {
725 0 : PyErr_Format(PyExc_TypeError,
726 : "third item of state should be a dict, got a %.200s",
727 0 : Py_TYPE(dict)->tp_name);
728 0 : return NULL;
729 : }
730 0 : if (self->dict) {
731 : /* Alternatively, we could replace the internal dictionary
732 : completely. However, it seems more practical to just update it. */
733 0 : if (PyDict_Update(self->dict, dict) < 0)
734 0 : return NULL;
735 : }
736 : else {
737 0 : Py_INCREF(dict);
738 0 : self->dict = dict;
739 : }
740 : }
741 :
742 0 : Py_RETURN_NONE;
743 : }
744 :
745 : static void
746 0 : bytesio_dealloc(bytesio *self)
747 : {
748 0 : _PyObject_GC_UNTRACK(self);
749 0 : if (self->buf != NULL) {
750 0 : PyMem_Free(self->buf);
751 0 : self->buf = NULL;
752 : }
753 0 : Py_CLEAR(self->dict);
754 0 : if (self->weakreflist != NULL)
755 0 : PyObject_ClearWeakRefs((PyObject *) self);
756 0 : Py_TYPE(self)->tp_free(self);
757 0 : }
758 :
759 : static PyObject *
760 0 : bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
761 : {
762 : bytesio *self;
763 :
764 : assert(type != NULL && type->tp_alloc != NULL);
765 0 : self = (bytesio *)type->tp_alloc(type, 0);
766 0 : if (self == NULL)
767 0 : return NULL;
768 :
769 : /* tp_alloc initializes all the fields to zero. So we don't have to
770 : initialize them here. */
771 :
772 0 : self->buf = (char *)PyMem_Malloc(0);
773 0 : if (self->buf == NULL) {
774 0 : Py_DECREF(self);
775 0 : return PyErr_NoMemory();
776 : }
777 :
778 0 : return (PyObject *)self;
779 : }
780 :
781 : static int
782 0 : bytesio_init(bytesio *self, PyObject *args, PyObject *kwds)
783 : {
784 0 : char *kwlist[] = {"initial_bytes", NULL};
785 0 : PyObject *initvalue = NULL;
786 :
787 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:BytesIO", kwlist,
788 : &initvalue))
789 0 : return -1;
790 :
791 : /* In case, __init__ is called multiple times. */
792 0 : self->string_size = 0;
793 0 : self->pos = 0;
794 :
795 0 : if (initvalue && initvalue != Py_None) {
796 : PyObject *res;
797 0 : res = bytesio_write(self, initvalue);
798 0 : if (res == NULL)
799 0 : return -1;
800 0 : Py_DECREF(res);
801 0 : self->pos = 0;
802 : }
803 :
804 0 : return 0;
805 : }
806 :
807 : static PyObject *
808 0 : bytesio_sizeof(bytesio *self, void *unused)
809 : {
810 : Py_ssize_t res;
811 :
812 0 : res = _PyObject_SIZE(Py_TYPE(self));
813 0 : if (self->buf)
814 0 : res += self->buf_size;
815 0 : return PyLong_FromSsize_t(res);
816 : }
817 :
818 : static int
819 0 : bytesio_traverse(bytesio *self, visitproc visit, void *arg)
820 : {
821 0 : Py_VISIT(self->dict);
822 0 : return 0;
823 : }
824 :
825 : static int
826 0 : bytesio_clear(bytesio *self)
827 : {
828 0 : Py_CLEAR(self->dict);
829 0 : 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 : };
|