1 #define PY_SSIZE_T_CLEAN
3 #include "structmember.h"
6 /* Implementation note: the buffer is always at least one character longer
7 than the enclosed string, for proper functioning of _PyIO_find_line_ending.
14 Py_ssize_t string_size
;
17 char ok
; /* initialized? */
26 PyObject
*weakreflist
;
29 #define CHECK_INITIALIZED(self) \
30 if (self->ok <= 0) { \
31 PyErr_SetString(PyExc_ValueError, \
32 "I/O operation on uninitialized object"); \
36 #define CHECK_CLOSED(self) \
38 PyErr_SetString(PyExc_ValueError, \
39 "I/O operation on closed file"); \
43 PyDoc_STRVAR(stringio_doc
,
44 "Text I/O implementation using an in-memory buffer.\n"
46 "The initial_value argument sets the value of object. The newline\n"
47 "argument is like the one of TextIOWrapper's constructor.");
50 /* Internal routine for changing the size, in terms of characters, of the
51 buffer of StringIO objects. The caller should ensure that the 'size'
52 argument is non-negative. Returns 0 on success, -1 otherwise. */
54 resize_buffer(stringio
*self
, size_t size
)
56 /* Here, unsigned types are used to avoid dealing with signed integer
57 overflow, which is undefined in C. */
58 size_t alloc
= self
->buf_size
;
59 Py_UNICODE
*new_buf
= NULL
;
61 assert(self
->buf
!= NULL
);
63 /* Reserve one more char for line ending detection. */
65 /* For simplicity, stay in the range of the signed type. Anyway, Python
66 doesn't allow strings to be longer than this. */
67 if (size
> PY_SSIZE_T_MAX
)
70 if (size
< alloc
/ 2) {
71 /* Major downsize; resize down to exact size. */
74 else if (size
< alloc
) {
75 /* Within allocated size; quick exit */
78 else if (size
<= alloc
* 1.125) {
79 /* Moderate upsize; overallocate similar to list_resize() */
80 alloc
= size
+ (size
>> 3) + (size
< 9 ? 3 : 6);
83 /* Major upsize; resize up to exact size */
87 if (alloc
> ((size_t)-1) / sizeof(Py_UNICODE
))
89 new_buf
= (Py_UNICODE
*)PyMem_Realloc(self
->buf
,
90 alloc
* sizeof(Py_UNICODE
));
91 if (new_buf
== NULL
) {
95 self
->buf_size
= alloc
;
101 PyErr_SetString(PyExc_OverflowError
,
102 "new buffer size too large");
106 /* Internal routine for writing a whole PyUnicode object to the buffer of a
107 StringIO object. Returns 0 on success, or -1 on error. */
109 write_str(stringio
*self
, PyObject
*obj
)
113 PyObject
*decoded
= NULL
;
114 assert(self
->buf
!= NULL
);
115 assert(self
->pos
>= 0);
117 if (self
->decoder
!= NULL
) {
118 decoded
= _PyIncrementalNewlineDecoder_decode(
119 self
->decoder
, obj
, 1 /* always final */);
126 PyObject
*translated
= PyUnicode_Replace(
127 decoded
, _PyIO_str_nl
, self
->writenl
, -1);
129 decoded
= translated
;
134 assert(PyUnicode_Check(decoded
));
135 str
= PyUnicode_AS_UNICODE(decoded
);
136 len
= PyUnicode_GET_SIZE(decoded
);
140 /* This overflow check is not strictly necessary. However, it avoids us to
141 deal with funky things like comparing an unsigned and a signed
143 if (self
->pos
> PY_SSIZE_T_MAX
- len
) {
144 PyErr_SetString(PyExc_OverflowError
,
145 "new position too large");
148 if (self
->pos
+ len
> self
->string_size
) {
149 if (resize_buffer(self
, self
->pos
+ len
) < 0)
153 if (self
->pos
> self
->string_size
) {
154 /* In case of overseek, pad with null bytes the buffer region between
155 the end of stream and the current position.
158 | |<---used--->|<----------available----------->|
159 | | <--to pad-->|<---to write---> |
163 memset(self
->buf
+ self
->string_size
, '\0',
164 (self
->pos
- self
->string_size
) * sizeof(Py_UNICODE
));
167 /* Copy the data to the internal buffer, overwriting some of the
168 existing data if self->pos < self->string_size. */
169 memcpy(self
->buf
+ self
->pos
, str
, len
* sizeof(Py_UNICODE
));
172 /* Set the new length of the internal string if it has changed. */
173 if (self
->string_size
< self
->pos
) {
174 self
->string_size
= self
->pos
;
185 PyDoc_STRVAR(stringio_getvalue_doc
,
186 "Retrieve the entire contents of the object.");
189 stringio_getvalue(stringio
*self
)
191 CHECK_INITIALIZED(self
);
193 return PyUnicode_FromUnicode(self
->buf
, self
->string_size
);
196 PyDoc_STRVAR(stringio_tell_doc
,
197 "Tell the current file position.");
200 stringio_tell(stringio
*self
)
202 CHECK_INITIALIZED(self
);
204 return PyLong_FromSsize_t(self
->pos
);
207 PyDoc_STRVAR(stringio_read_doc
,
208 "Read at most n characters, returned as a string.\n"
210 "If the argument is negative or omitted, read until EOF\n"
211 "is reached. Return an empty string at EOF.\n");
214 stringio_read(stringio
*self
, PyObject
*args
)
218 PyObject
*arg
= Py_None
;
220 CHECK_INITIALIZED(self
);
221 if (!PyArg_ParseTuple(args
, "|O:read", &arg
))
225 if (PyNumber_Check(arg
)) {
226 size
= PyNumber_AsSsize_t(arg
, PyExc_OverflowError
);
227 if (size
== -1 && PyErr_Occurred())
230 else if (arg
== Py_None
) {
231 /* Read until EOF is reached, by default. */
235 PyErr_Format(PyExc_TypeError
, "integer argument expected, got '%s'",
236 Py_TYPE(arg
)->tp_name
);
240 /* adjust invalid sizes */
241 n
= self
->string_size
- self
->pos
;
242 if (size
< 0 || size
> n
) {
248 output
= self
->buf
+ self
->pos
;
250 return PyUnicode_FromUnicode(output
, size
);
253 /* Internal helper, used by stringio_readline and stringio_iternext */
255 _stringio_readline(stringio
*self
, Py_ssize_t limit
)
257 Py_UNICODE
*start
, *end
, old_char
;
258 Py_ssize_t len
, consumed
;
260 /* In case of overseek, return the empty string */
261 if (self
->pos
>= self
->string_size
)
262 return PyUnicode_FromString("");
264 start
= self
->buf
+ self
->pos
;
265 if (limit
< 0 || limit
> self
->string_size
- self
->pos
)
266 limit
= self
->string_size
- self
->pos
;
271 len
= _PyIO_find_line_ending(
272 self
->readtranslate
, self
->readuniversal
, self
->readnl
,
273 start
, end
, &consumed
);
275 /* If we haven't found any line ending, we just return everything
276 (`consumed` is ignored). */
280 return PyUnicode_FromUnicode(start
, len
);
283 PyDoc_STRVAR(stringio_readline_doc
,
284 "Read until newline or EOF.\n"
286 "Returns an empty string if EOF is hit immediately.\n");
289 stringio_readline(stringio
*self
, PyObject
*args
)
291 PyObject
*arg
= Py_None
;
292 Py_ssize_t limit
= -1;
294 CHECK_INITIALIZED(self
);
295 if (!PyArg_ParseTuple(args
, "|O:readline", &arg
))
299 if (PyNumber_Check(arg
)) {
300 limit
= PyNumber_AsSsize_t(arg
, PyExc_OverflowError
);
301 if (limit
== -1 && PyErr_Occurred())
304 else if (arg
!= Py_None
) {
305 PyErr_Format(PyExc_TypeError
, "integer argument expected, got '%s'",
306 Py_TYPE(arg
)->tp_name
);
309 return _stringio_readline(self
, limit
);
313 stringio_iternext(stringio
*self
)
317 CHECK_INITIALIZED(self
);
320 if (Py_TYPE(self
) == &PyStringIO_Type
) {
321 /* Skip method call overhead for speed */
322 line
= _stringio_readline(self
, -1);
325 /* XXX is subclassing StringIO really supported? */
326 line
= PyObject_CallMethodObjArgs((PyObject
*)self
,
327 _PyIO_str_readline
, NULL
);
328 if (line
&& !PyUnicode_Check(line
)) {
329 PyErr_Format(PyExc_IOError
,
330 "readline() should have returned an str object, "
331 "not '%.200s'", Py_TYPE(line
)->tp_name
);
340 if (PyUnicode_GET_SIZE(line
) == 0) {
349 PyDoc_STRVAR(stringio_truncate_doc
,
350 "Truncate size to pos.\n"
352 "The pos argument defaults to the current file position, as\n"
353 "returned by tell(). Imply an absolute seek to pos.\n"
354 "Returns the new absolute position.\n");
357 stringio_truncate(stringio
*self
, PyObject
*args
)
360 PyObject
*arg
= Py_None
;
362 CHECK_INITIALIZED(self
);
363 if (!PyArg_ParseTuple(args
, "|O:truncate", &arg
))
367 if (PyNumber_Check(arg
)) {
368 size
= PyNumber_AsSsize_t(arg
, PyExc_OverflowError
);
369 if (size
== -1 && PyErr_Occurred())
372 else if (arg
== Py_None
) {
373 /* Truncate to current position if no argument is passed. */
377 PyErr_Format(PyExc_TypeError
, "integer argument expected, got '%s'",
378 Py_TYPE(arg
)->tp_name
);
383 PyErr_Format(PyExc_ValueError
,
384 "Negative size value %zd", size
);
388 if (size
< self
->string_size
) {
389 if (resize_buffer(self
, size
) < 0)
391 self
->string_size
= size
;
395 return PyLong_FromSsize_t(size
);
398 PyDoc_STRVAR(stringio_seek_doc
,
399 "Change stream position.\n"
401 "Seek to character offset pos relative to position indicated by whence:\n"
402 " 0 Start of stream (the default). pos should be >= 0;\n"
403 " 1 Current position - pos must be 0;\n"
404 " 2 End of stream - pos must be 0.\n"
405 "Returns the new absolute position.\n");
408 stringio_seek(stringio
*self
, PyObject
*args
)
414 CHECK_INITIALIZED(self
);
415 if (!PyArg_ParseTuple(args
, "O|i:seek", &posobj
, &mode
))
418 pos
= PyNumber_AsSsize_t(posobj
, PyExc_OverflowError
);
419 if (pos
== -1 && PyErr_Occurred())
424 if (mode
!= 0 && mode
!= 1 && mode
!= 2) {
425 PyErr_Format(PyExc_ValueError
,
426 "Invalid whence (%i, should be 0, 1 or 2)", mode
);
429 else if (pos
< 0 && mode
== 0) {
430 PyErr_Format(PyExc_ValueError
,
431 "Negative seek position %zd", pos
);
434 else if (mode
!= 0 && pos
!= 0) {
435 PyErr_SetString(PyExc_IOError
,
436 "Can't do nonzero cur-relative seeks");
440 /* mode 0: offset relative to beginning of the string.
441 mode 1: no change to current position.
442 mode 2: change position to end of file. */
446 else if (mode
== 2) {
447 pos
= self
->string_size
;
452 return PyLong_FromSsize_t(self
->pos
);
455 PyDoc_STRVAR(stringio_write_doc
,
456 "Write string to file.\n"
458 "Returns the number of characters written, which is always equal to\n"
459 "the length of the string.\n");
462 stringio_write(stringio
*self
, PyObject
*obj
)
466 CHECK_INITIALIZED(self
);
467 if (!PyUnicode_Check(obj
)) {
468 PyErr_Format(PyExc_TypeError
, "string argument expected, got '%s'",
469 Py_TYPE(obj
)->tp_name
);
473 size
= PyUnicode_GET_SIZE(obj
);
475 if (size
> 0 && write_str(self
, obj
) < 0)
478 return PyLong_FromSsize_t(size
);
481 PyDoc_STRVAR(stringio_close_doc
,
482 "Close the IO object. Attempting any further operation after the\n"
483 "object is closed will raise a ValueError.\n"
485 "This method has no effect if the file is already closed.\n");
488 stringio_close(stringio
*self
)
491 /* Free up some memory */
492 if (resize_buffer(self
, 0) < 0)
494 Py_CLEAR(self
->readnl
);
495 Py_CLEAR(self
->writenl
);
496 Py_CLEAR(self
->decoder
);
501 stringio_traverse(stringio
*self
, visitproc visit
, void *arg
)
503 Py_VISIT(self
->dict
);
508 stringio_clear(stringio
*self
)
510 Py_CLEAR(self
->dict
);
515 stringio_dealloc(stringio
*self
)
517 _PyObject_GC_UNTRACK(self
);
520 PyMem_Free(self
->buf
);
523 Py_CLEAR(self
->readnl
);
524 Py_CLEAR(self
->writenl
);
525 Py_CLEAR(self
->decoder
);
526 Py_CLEAR(self
->dict
);
527 if (self
->weakreflist
!= NULL
)
528 PyObject_ClearWeakRefs((PyObject
*) self
);
529 Py_TYPE(self
)->tp_free(self
);
533 stringio_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwds
)
537 assert(type
!= NULL
&& type
->tp_alloc
!= NULL
);
538 self
= (stringio
*)type
->tp_alloc(type
, 0);
542 /* tp_alloc initializes all the fields to zero. So we don't have to
543 initialize them here. */
545 self
->buf
= (Py_UNICODE
*)PyMem_Malloc(0);
546 if (self
->buf
== NULL
) {
548 return PyErr_NoMemory();
551 return (PyObject
*)self
;
555 stringio_init(stringio
*self
, PyObject
*args
, PyObject
*kwds
)
557 char *kwlist
[] = {"initial_value", "newline", NULL
};
558 PyObject
*value
= NULL
;
559 char *newline
= "\n";
561 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "|Oz:__init__", kwlist
,
565 if (newline
&& newline
[0] != '\0'
566 && !(newline
[0] == '\n' && newline
[1] == '\0')
567 && !(newline
[0] == '\r' && newline
[1] == '\0')
568 && !(newline
[0] == '\r' && newline
[1] == '\n' && newline
[2] == '\0')) {
569 PyErr_Format(PyExc_ValueError
,
570 "illegal newline value: %s", newline
);
573 if (value
&& value
!= Py_None
&& !PyUnicode_Check(value
)) {
574 PyErr_Format(PyExc_TypeError
,
575 "initial_value must be unicode or None, not %.200s",
576 Py_TYPE(value
)->tp_name
);
582 Py_CLEAR(self
->readnl
);
583 Py_CLEAR(self
->writenl
);
584 Py_CLEAR(self
->decoder
);
587 self
->readnl
= PyString_FromString(newline
);
588 if (self
->readnl
== NULL
)
591 self
->readuniversal
= (newline
== NULL
|| newline
[0] == '\0');
592 self
->readtranslate
= (newline
== NULL
);
593 /* If newline == "", we don't translate anything.
594 If newline == "\n" or newline == None, we translate to "\n", which is
596 (for newline == None, TextIOWrapper translates to os.sepline, but it
597 is pointless for StringIO)
599 if (newline
!= NULL
&& newline
[0] == '\r') {
600 self
->writenl
= PyUnicode_FromString(newline
);
603 if (self
->readuniversal
) {
604 self
->decoder
= PyObject_CallFunction(
605 (PyObject
*)&PyIncrementalNewlineDecoder_Type
,
606 "Oi", Py_None
, (int) self
->readtranslate
);
607 if (self
->decoder
== NULL
)
611 /* Now everything is set up, resize buffer to size of initial value,
613 self
->string_size
= 0;
614 if (value
&& value
!= Py_None
) {
615 Py_ssize_t len
= PyUnicode_GetSize(value
);
616 /* This is a heuristic, for newline translation might change
617 the string length. */
618 if (resize_buffer(self
, len
) < 0)
621 if (write_str(self
, value
) < 0)
625 if (resize_buffer(self
, 0) < 0)
635 /* Properties and pseudo-properties */
637 stringio_seekable(stringio
*self
, PyObject
*args
)
639 CHECK_INITIALIZED(self
);
644 stringio_readable(stringio
*self
, PyObject
*args
)
646 CHECK_INITIALIZED(self
);
651 stringio_writable(stringio
*self
, PyObject
*args
)
653 CHECK_INITIALIZED(self
);
659 The implementation of __getstate__ is similar to the one for BytesIO,
660 except that we also save the newline parameter. For __setstate__ and unlike
661 BytesIO, we call __init__ to restore the object's state. Doing so allows us
662 to avoid decoding the complex newline state while keeping the object
663 representation compact.
665 See comment in bytesio.c regarding why only pickle protocols and onward are
670 stringio_getstate(stringio
*self
)
672 PyObject
*initvalue
= stringio_getvalue(self
);
676 if (initvalue
== NULL
)
678 if (self
->dict
== NULL
) {
683 dict
= PyDict_Copy(self
->dict
);
688 state
= Py_BuildValue("(OOnN)", initvalue
,
689 self
->readnl
? self
->readnl
: Py_None
,
691 Py_DECREF(initvalue
);
696 stringio_setstate(stringio
*self
, PyObject
*state
)
699 PyObject
*position_obj
;
703 assert(state
!= NULL
);
706 /* We allow the state tuple to be longer than 4, because we may need
707 someday to extend the object's state without breaking
708 backward-compatibility. */
709 if (!PyTuple_Check(state
) || Py_SIZE(state
) < 4) {
710 PyErr_Format(PyExc_TypeError
,
711 "%.200s.__setstate__ argument should be 4-tuple, got %.200s",
712 Py_TYPE(self
)->tp_name
, Py_TYPE(state
)->tp_name
);
716 /* Initialize the object's state. */
717 initarg
= PyTuple_GetSlice(state
, 0, 2);
720 if (stringio_init(self
, initarg
, NULL
) < 0) {
726 /* Restore the buffer state. Even if __init__ did initialize the buffer,
727 we have to initialize it again since __init__ may translates the
728 newlines in the inital_value string. We clearly do not want that
729 because the string value in the state tuple has already been translated
730 once by __init__. So we do not take any chance and replace object's
731 buffer completely. */
733 Py_UNICODE
*buf
= PyUnicode_AS_UNICODE(PyTuple_GET_ITEM(state
, 0));
734 Py_ssize_t bufsize
= PyUnicode_GET_SIZE(PyTuple_GET_ITEM(state
, 0));
735 if (resize_buffer(self
, bufsize
) < 0)
737 memcpy(self
->buf
, buf
, bufsize
* sizeof(Py_UNICODE
));
738 self
->string_size
= bufsize
;
741 /* Set carefully the position value. Alternatively, we could use the seek
742 method instead of modifying self->pos directly to better protect the
743 object internal state against errneous (or malicious) inputs. */
744 position_obj
= PyTuple_GET_ITEM(state
, 2);
745 if (!PyIndex_Check(position_obj
)) {
746 PyErr_Format(PyExc_TypeError
,
747 "third item of state must be an integer, got %.200s",
748 Py_TYPE(position_obj
)->tp_name
);
751 pos
= PyNumber_AsSsize_t(position_obj
, PyExc_OverflowError
);
752 if (pos
== -1 && PyErr_Occurred())
755 PyErr_SetString(PyExc_ValueError
,
756 "position value cannot be negative");
761 /* Set the dictionary of the instance variables. */
762 dict
= PyTuple_GET_ITEM(state
, 3);
763 if (dict
!= Py_None
) {
764 if (!PyDict_Check(dict
)) {
765 PyErr_Format(PyExc_TypeError
,
766 "fourth item of state should be a dict, got a %.200s",
767 Py_TYPE(dict
)->tp_name
);
771 /* Alternatively, we could replace the internal dictionary
772 completely. However, it seems more practical to just update it. */
773 if (PyDict_Update(self
->dict
, dict
) < 0)
787 stringio_closed(stringio
*self
, void *context
)
789 CHECK_INITIALIZED(self
);
790 return PyBool_FromLong(self
->closed
);
794 stringio_line_buffering(stringio
*self
, void *context
)
796 CHECK_INITIALIZED(self
);
802 stringio_newlines(stringio
*self
, void *context
)
804 CHECK_INITIALIZED(self
);
806 if (self
->decoder
== NULL
)
808 return PyObject_GetAttr(self
->decoder
, _PyIO_str_newlines
);
811 static struct PyMethodDef stringio_methods
[] = {
812 {"close", (PyCFunction
)stringio_close
, METH_NOARGS
, stringio_close_doc
},
813 {"getvalue", (PyCFunction
)stringio_getvalue
, METH_VARARGS
, stringio_getvalue_doc
},
814 {"read", (PyCFunction
)stringio_read
, METH_VARARGS
, stringio_read_doc
},
815 {"readline", (PyCFunction
)stringio_readline
, METH_VARARGS
, stringio_readline_doc
},
816 {"tell", (PyCFunction
)stringio_tell
, METH_NOARGS
, stringio_tell_doc
},
817 {"truncate", (PyCFunction
)stringio_truncate
, METH_VARARGS
, stringio_truncate_doc
},
818 {"seek", (PyCFunction
)stringio_seek
, METH_VARARGS
, stringio_seek_doc
},
819 {"write", (PyCFunction
)stringio_write
, METH_O
, stringio_write_doc
},
821 {"seekable", (PyCFunction
)stringio_seekable
, METH_NOARGS
},
822 {"readable", (PyCFunction
)stringio_readable
, METH_NOARGS
},
823 {"writable", (PyCFunction
)stringio_writable
, METH_NOARGS
},
825 {"__getstate__", (PyCFunction
)stringio_getstate
, METH_NOARGS
},
826 {"__setstate__", (PyCFunction
)stringio_setstate
, METH_O
},
827 {NULL
, NULL
} /* sentinel */
830 static PyGetSetDef stringio_getset
[] = {
831 {"closed", (getter
)stringio_closed
, NULL
, NULL
},
832 {"newlines", (getter
)stringio_newlines
, NULL
, NULL
},
833 /* (following comments straight off of the original Python wrapper:)
834 XXX Cruft to support the TextIOWrapper API. This would only
835 be meaningful if StringIO supported the buffer attribute.
836 Hopefully, a better solution, than adding these pseudo-attributes,
839 {"line_buffering", (getter
)stringio_line_buffering
, NULL
, NULL
},
843 PyTypeObject PyStringIO_Type
= {
844 PyVarObject_HEAD_INIT(NULL
, 0)
845 "_io.StringIO", /*tp_name*/
846 sizeof(stringio
), /*tp_basicsize*/
848 (destructor
)stringio_dealloc
, /*tp_dealloc*/
855 0, /*tp_as_sequence*/
863 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
864 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
865 stringio_doc
, /*tp_doc*/
866 (traverseproc
)stringio_traverse
, /*tp_traverse*/
867 (inquiry
)stringio_clear
, /*tp_clear*/
868 0, /*tp_richcompare*/
869 offsetof(stringio
, weakreflist
), /*tp_weaklistoffset*/
871 (iternextfunc
)stringio_iternext
, /*tp_iternext*/
872 stringio_methods
, /*tp_methods*/
874 stringio_getset
, /*tp_getset*/
879 offsetof(stringio
, dict
), /*tp_dictoffset*/
880 (initproc
)stringio_init
, /*tp_init*/
882 stringio_new
, /*tp_new*/