ยปCore Development>Code coverage>Modules/_io/stringio.c

Python code coverage for Modules/_io/stringio.c

#countcontent
1n/a#define PY_SSIZE_T_CLEAN
2n/a#include "Python.h"
3n/a#include "structmember.h"
4n/a#include "accu.h"
5n/a#include "_iomodule.h"
6n/a
7n/a/* Implementation note: the buffer is always at least one character longer
8n/a than the enclosed string, for proper functioning of _PyIO_find_line_ending.
9n/a*/
10n/a
11n/a#define STATE_REALIZED 1
12n/a#define STATE_ACCUMULATING 2
13n/a
14n/a/*[clinic input]
15n/amodule _io
16n/aclass _io.StringIO "stringio *" "&PyStringIO_Type"
17n/a[clinic start generated code]*/
18n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c17bc0f42165cd7d]*/
19n/a
20n/atypedef struct {
21n/a PyObject_HEAD
22n/a Py_UCS4 *buf;
23n/a Py_ssize_t pos;
24n/a Py_ssize_t string_size;
25n/a size_t buf_size;
26n/a
27n/a /* The stringio object can be in two states: accumulating or realized.
28n/a In accumulating state, the internal buffer contains nothing and
29n/a the contents are given by the embedded _PyAccu structure.
30n/a In realized state, the internal buffer is meaningful and the
31n/a _PyAccu is destroyed.
32n/a */
33n/a int state;
34n/a _PyAccu accu;
35n/a
36n/a char ok; /* initialized? */
37n/a char closed;
38n/a char readuniversal;
39n/a char readtranslate;
40n/a PyObject *decoder;
41n/a PyObject *readnl;
42n/a PyObject *writenl;
43n/a
44n/a PyObject *dict;
45n/a PyObject *weakreflist;
46n/a} stringio;
47n/a
48n/astatic int _io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs);
49n/a
50n/a#define CHECK_INITIALIZED(self) \
51n/a if (self->ok <= 0) { \
52n/a PyErr_SetString(PyExc_ValueError, \
53n/a "I/O operation on uninitialized object"); \
54n/a return NULL; \
55n/a }
56n/a
57n/a#define CHECK_CLOSED(self) \
58n/a if (self->closed) { \
59n/a PyErr_SetString(PyExc_ValueError, \
60n/a "I/O operation on closed file"); \
61n/a return NULL; \
62n/a }
63n/a
64n/a#define ENSURE_REALIZED(self) \
65n/a if (realize(self) < 0) { \
66n/a return NULL; \
67n/a }
68n/a
69n/a
70n/a/* Internal routine for changing the size, in terms of characters, of the
71n/a buffer of StringIO objects. The caller should ensure that the 'size'
72n/a argument is non-negative. Returns 0 on success, -1 otherwise. */
73n/astatic int
74n/aresize_buffer(stringio *self, size_t size)
75n/a{
76n/a /* Here, unsigned types are used to avoid dealing with signed integer
77n/a overflow, which is undefined in C. */
78n/a size_t alloc = self->buf_size;
79n/a Py_UCS4 *new_buf = NULL;
80n/a
81n/a assert(self->buf != NULL);
82n/a
83n/a /* Reserve one more char for line ending detection. */
84n/a size = size + 1;
85n/a /* For simplicity, stay in the range of the signed type. Anyway, Python
86n/a doesn't allow strings to be longer than this. */
87n/a if (size > PY_SSIZE_T_MAX)
88n/a goto overflow;
89n/a
90n/a if (size < alloc / 2) {
91n/a /* Major downsize; resize down to exact size. */
92n/a alloc = size + 1;
93n/a }
94n/a else if (size < alloc) {
95n/a /* Within allocated size; quick exit */
96n/a return 0;
97n/a }
98n/a else if (size <= alloc * 1.125) {
99n/a /* Moderate upsize; overallocate similar to list_resize() */
100n/a alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
101n/a }
102n/a else {
103n/a /* Major upsize; resize up to exact size */
104n/a alloc = size + 1;
105n/a }
106n/a
107n/a if (alloc > PY_SIZE_MAX / sizeof(Py_UCS4))
108n/a goto overflow;
109n/a new_buf = (Py_UCS4 *)PyMem_Realloc(self->buf, alloc * sizeof(Py_UCS4));
110n/a if (new_buf == NULL) {
111n/a PyErr_NoMemory();
112n/a return -1;
113n/a }
114n/a self->buf_size = alloc;
115n/a self->buf = new_buf;
116n/a
117n/a return 0;
118n/a
119n/a overflow:
120n/a PyErr_SetString(PyExc_OverflowError,
121n/a "new buffer size too large");
122n/a return -1;
123n/a}
124n/a
125n/astatic PyObject *
126n/amake_intermediate(stringio *self)
127n/a{
128n/a PyObject *intermediate = _PyAccu_Finish(&self->accu);
129n/a self->state = STATE_REALIZED;
130n/a if (intermediate == NULL)
131n/a return NULL;
132n/a if (_PyAccu_Init(&self->accu) ||
133n/a _PyAccu_Accumulate(&self->accu, intermediate)) {
134n/a Py_DECREF(intermediate);
135n/a return NULL;
136n/a }
137n/a self->state = STATE_ACCUMULATING;
138n/a return intermediate;
139n/a}
140n/a
141n/astatic int
142n/arealize(stringio *self)
143n/a{
144n/a Py_ssize_t len;
145n/a PyObject *intermediate;
146n/a
147n/a if (self->state == STATE_REALIZED)
148n/a return 0;
149n/a assert(self->state == STATE_ACCUMULATING);
150n/a self->state = STATE_REALIZED;
151n/a
152n/a intermediate = _PyAccu_Finish(&self->accu);
153n/a if (intermediate == NULL)
154n/a return -1;
155n/a
156n/a /* Append the intermediate string to the internal buffer.
157n/a The length should be equal to the current cursor position.
158n/a */
159n/a len = PyUnicode_GET_LENGTH(intermediate);
160n/a if (resize_buffer(self, len) < 0) {
161n/a Py_DECREF(intermediate);
162n/a return -1;
163n/a }
164n/a if (!PyUnicode_AsUCS4(intermediate, self->buf, len, 0)) {
165n/a Py_DECREF(intermediate);
166n/a return -1;
167n/a }
168n/a
169n/a Py_DECREF(intermediate);
170n/a return 0;
171n/a}
172n/a
173n/a/* Internal routine for writing a whole PyUnicode object to the buffer of a
174n/a StringIO object. Returns 0 on success, or -1 on error. */
175n/astatic Py_ssize_t
176n/awrite_str(stringio *self, PyObject *obj)
177n/a{
178n/a Py_ssize_t len;
179n/a PyObject *decoded = NULL;
180n/a
181n/a assert(self->buf != NULL);
182n/a assert(self->pos >= 0);
183n/a
184n/a if (self->decoder != NULL) {
185n/a decoded = _PyIncrementalNewlineDecoder_decode(
186n/a self->decoder, obj, 1 /* always final */);
187n/a }
188n/a else {
189n/a decoded = obj;
190n/a Py_INCREF(decoded);
191n/a }
192n/a if (self->writenl) {
193n/a PyObject *translated = PyUnicode_Replace(
194n/a decoded, _PyIO_str_nl, self->writenl, -1);
195n/a Py_DECREF(decoded);
196n/a decoded = translated;
197n/a }
198n/a if (decoded == NULL)
199n/a return -1;
200n/a
201n/a assert(PyUnicode_Check(decoded));
202n/a if (PyUnicode_READY(decoded)) {
203n/a Py_DECREF(decoded);
204n/a return -1;
205n/a }
206n/a len = PyUnicode_GET_LENGTH(decoded);
207n/a assert(len >= 0);
208n/a
209n/a /* This overflow check is not strictly necessary. However, it avoids us to
210n/a deal with funky things like comparing an unsigned and a signed
211n/a integer. */
212n/a if (self->pos > PY_SSIZE_T_MAX - len) {
213n/a PyErr_SetString(PyExc_OverflowError,
214n/a "new position too large");
215n/a goto fail;
216n/a }
217n/a
218n/a if (self->state == STATE_ACCUMULATING) {
219n/a if (self->string_size == self->pos) {
220n/a if (_PyAccu_Accumulate(&self->accu, decoded))
221n/a goto fail;
222n/a goto success;
223n/a }
224n/a if (realize(self))
225n/a goto fail;
226n/a }
227n/a
228n/a if (self->pos + len > self->string_size) {
229n/a if (resize_buffer(self, self->pos + len) < 0)
230n/a goto fail;
231n/a }
232n/a
233n/a if (self->pos > self->string_size) {
234n/a /* In case of overseek, pad with null bytes the buffer region between
235n/a the end of stream and the current position.
236n/a
237n/a 0 lo string_size hi
238n/a | |<---used--->|<----------available----------->|
239n/a | | <--to pad-->|<---to write---> |
240n/a 0 buf position
241n/a
242n/a */
243n/a memset(self->buf + self->string_size, '\0',
244n/a (self->pos - self->string_size) * sizeof(Py_UCS4));
245n/a }
246n/a
247n/a /* Copy the data to the internal buffer, overwriting some of the
248n/a existing data if self->pos < self->string_size. */
249n/a if (!PyUnicode_AsUCS4(decoded,
250n/a self->buf + self->pos,
251n/a self->buf_size - self->pos,
252n/a 0))
253n/a goto fail;
254n/a
255n/asuccess:
256n/a /* Set the new length of the internal string if it has changed. */
257n/a self->pos += len;
258n/a if (self->string_size < self->pos)
259n/a self->string_size = self->pos;
260n/a
261n/a Py_DECREF(decoded);
262n/a return 0;
263n/a
264n/afail:
265n/a Py_XDECREF(decoded);
266n/a return -1;
267n/a}
268n/a
269n/a/*[clinic input]
270n/a_io.StringIO.getvalue
271n/a
272n/aRetrieve the entire contents of the object.
273n/a[clinic start generated code]*/
274n/a
275n/astatic PyObject *
276n/a_io_StringIO_getvalue_impl(stringio *self)
277n/a/*[clinic end generated code: output=27b6a7bfeaebce01 input=d23cb81d6791cf88]*/
278n/a{
279n/a CHECK_INITIALIZED(self);
280n/a CHECK_CLOSED(self);
281n/a if (self->state == STATE_ACCUMULATING)
282n/a return make_intermediate(self);
283n/a return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, self->buf,
284n/a self->string_size);
285n/a}
286n/a
287n/a/*[clinic input]
288n/a_io.StringIO.tell
289n/a
290n/aTell the current file position.
291n/a[clinic start generated code]*/
292n/a
293n/astatic PyObject *
294n/a_io_StringIO_tell_impl(stringio *self)
295n/a/*[clinic end generated code: output=2e87ac67b116c77b input=ec866ebaff02f405]*/
296n/a{
297n/a CHECK_INITIALIZED(self);
298n/a CHECK_CLOSED(self);
299n/a return PyLong_FromSsize_t(self->pos);
300n/a}
301n/a
302n/a/*[clinic input]
303n/a_io.StringIO.read
304n/a size as arg: object = None
305n/a /
306n/a
307n/aRead at most size characters, returned as a string.
308n/a
309n/aIf the argument is negative or omitted, read until EOF
310n/ais reached. Return an empty string at EOF.
311n/a[clinic start generated code]*/
312n/a
313n/astatic PyObject *
314n/a_io_StringIO_read_impl(stringio *self, PyObject *arg)
315n/a/*[clinic end generated code: output=3676864773746f68 input=9a319015f6f3965c]*/
316n/a{
317n/a Py_ssize_t size, n;
318n/a Py_UCS4 *output;
319n/a
320n/a CHECK_INITIALIZED(self);
321n/a CHECK_CLOSED(self);
322n/a
323n/a if (PyNumber_Check(arg)) {
324n/a size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
325n/a if (size == -1 && PyErr_Occurred())
326n/a return NULL;
327n/a }
328n/a else if (arg == Py_None) {
329n/a /* Read until EOF is reached, by default. */
330n/a size = -1;
331n/a }
332n/a else {
333n/a PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
334n/a Py_TYPE(arg)->tp_name);
335n/a return NULL;
336n/a }
337n/a
338n/a /* adjust invalid sizes */
339n/a n = self->string_size - self->pos;
340n/a if (size < 0 || size > n) {
341n/a size = n;
342n/a if (size < 0)
343n/a size = 0;
344n/a }
345n/a
346n/a /* Optimization for seek(0); read() */
347n/a if (self->state == STATE_ACCUMULATING && self->pos == 0 && size == n) {
348n/a PyObject *result = make_intermediate(self);
349n/a self->pos = self->string_size;
350n/a return result;
351n/a }
352n/a
353n/a ENSURE_REALIZED(self);
354n/a output = self->buf + self->pos;
355n/a self->pos += size;
356n/a return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, output, size);
357n/a}
358n/a
359n/a/* Internal helper, used by stringio_readline and stringio_iternext */
360n/astatic PyObject *
361n/a_stringio_readline(stringio *self, Py_ssize_t limit)
362n/a{
363n/a Py_UCS4 *start, *end, old_char;
364n/a Py_ssize_t len, consumed;
365n/a
366n/a /* In case of overseek, return the empty string */
367n/a if (self->pos >= self->string_size)
368n/a return PyUnicode_New(0, 0);
369n/a
370n/a start = self->buf + self->pos;
371n/a if (limit < 0 || limit > self->string_size - self->pos)
372n/a limit = self->string_size - self->pos;
373n/a
374n/a end = start + limit;
375n/a old_char = *end;
376n/a *end = '\0';
377n/a len = _PyIO_find_line_ending(
378n/a self->readtranslate, self->readuniversal, self->readnl,
379n/a PyUnicode_4BYTE_KIND, (char*)start, (char*)end, &consumed);
380n/a *end = old_char;
381n/a /* If we haven't found any line ending, we just return everything
382n/a (`consumed` is ignored). */
383n/a if (len < 0)
384n/a len = limit;
385n/a self->pos += len;
386n/a return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, start, len);
387n/a}
388n/a
389n/a/*[clinic input]
390n/a_io.StringIO.readline
391n/a size as arg: object = None
392n/a /
393n/a
394n/aRead until newline or EOF.
395n/a
396n/aReturns an empty string if EOF is hit immediately.
397n/a[clinic start generated code]*/
398n/a
399n/astatic PyObject *
400n/a_io_StringIO_readline_impl(stringio *self, PyObject *arg)
401n/a/*[clinic end generated code: output=99fdcac03a3dee81 input=e0e0ed4042040176]*/
402n/a{
403n/a Py_ssize_t limit = -1;
404n/a
405n/a CHECK_INITIALIZED(self);
406n/a CHECK_CLOSED(self);
407n/a ENSURE_REALIZED(self);
408n/a
409n/a if (PyNumber_Check(arg)) {
410n/a limit = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
411n/a if (limit == -1 && PyErr_Occurred())
412n/a return NULL;
413n/a }
414n/a else if (arg != Py_None) {
415n/a PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
416n/a Py_TYPE(arg)->tp_name);
417n/a return NULL;
418n/a }
419n/a return _stringio_readline(self, limit);
420n/a}
421n/a
422n/astatic PyObject *
423n/astringio_iternext(stringio *self)
424n/a{
425n/a PyObject *line;
426n/a
427n/a CHECK_INITIALIZED(self);
428n/a CHECK_CLOSED(self);
429n/a ENSURE_REALIZED(self);
430n/a
431n/a if (Py_TYPE(self) == &PyStringIO_Type) {
432n/a /* Skip method call overhead for speed */
433n/a line = _stringio_readline(self, -1);
434n/a }
435n/a else {
436n/a /* XXX is subclassing StringIO really supported? */
437n/a line = PyObject_CallMethodObjArgs((PyObject *)self,
438n/a _PyIO_str_readline, NULL);
439n/a if (line && !PyUnicode_Check(line)) {
440n/a PyErr_Format(PyExc_IOError,
441n/a "readline() should have returned a str object, "
442n/a "not '%.200s'", Py_TYPE(line)->tp_name);
443n/a Py_DECREF(line);
444n/a return NULL;
445n/a }
446n/a }
447n/a
448n/a if (line == NULL)
449n/a return NULL;
450n/a
451n/a if (PyUnicode_GET_LENGTH(line) == 0) {
452n/a /* Reached EOF */
453n/a Py_DECREF(line);
454n/a return NULL;
455n/a }
456n/a
457n/a return line;
458n/a}
459n/a
460n/a/*[clinic input]
461n/a_io.StringIO.truncate
462n/a pos as arg: object = None
463n/a /
464n/a
465n/aTruncate size to pos.
466n/a
467n/aThe pos argument defaults to the current file position, as
468n/areturned by tell(). The current file position is unchanged.
469n/aReturns the new absolute position.
470n/a[clinic start generated code]*/
471n/a
472n/astatic PyObject *
473n/a_io_StringIO_truncate_impl(stringio *self, PyObject *arg)
474n/a/*[clinic end generated code: output=6072439c2b01d306 input=748619a494ba53ad]*/
475n/a{
476n/a Py_ssize_t size;
477n/a
478n/a CHECK_INITIALIZED(self);
479n/a CHECK_CLOSED(self);
480n/a
481n/a if (PyNumber_Check(arg)) {
482n/a size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
483n/a if (size == -1 && PyErr_Occurred())
484n/a return NULL;
485n/a }
486n/a else if (arg == Py_None) {
487n/a /* Truncate to current position if no argument is passed. */
488n/a size = self->pos;
489n/a }
490n/a else {
491n/a PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
492n/a Py_TYPE(arg)->tp_name);
493n/a return NULL;
494n/a }
495n/a
496n/a if (size < 0) {
497n/a PyErr_Format(PyExc_ValueError,
498n/a "Negative size value %zd", size);
499n/a return NULL;
500n/a }
501n/a
502n/a if (size < self->string_size) {
503n/a ENSURE_REALIZED(self);
504n/a if (resize_buffer(self, size) < 0)
505n/a return NULL;
506n/a self->string_size = size;
507n/a }
508n/a
509n/a return PyLong_FromSsize_t(size);
510n/a}
511n/a
512n/a/*[clinic input]
513n/a_io.StringIO.seek
514n/a pos: Py_ssize_t
515n/a whence: int = 0
516n/a /
517n/a
518n/aChange stream position.
519n/a
520n/aSeek to character offset pos relative to position indicated by whence:
521n/a 0 Start of stream (the default). pos should be >= 0;
522n/a 1 Current position - pos must be 0;
523n/a 2 End of stream - pos must be 0.
524n/aReturns the new absolute position.
525n/a[clinic start generated code]*/
526n/a
527n/astatic PyObject *
528n/a_io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence)
529n/a/*[clinic end generated code: output=e9e0ac9a8ae71c25 input=e3855b24e7cae06a]*/
530n/a{
531n/a CHECK_INITIALIZED(self);
532n/a CHECK_CLOSED(self);
533n/a
534n/a if (whence != 0 && whence != 1 && whence != 2) {
535n/a PyErr_Format(PyExc_ValueError,
536n/a "Invalid whence (%i, should be 0, 1 or 2)", whence);
537n/a return NULL;
538n/a }
539n/a else if (pos < 0 && whence == 0) {
540n/a PyErr_Format(PyExc_ValueError,
541n/a "Negative seek position %zd", pos);
542n/a return NULL;
543n/a }
544n/a else if (whence != 0 && pos != 0) {
545n/a PyErr_SetString(PyExc_IOError,
546n/a "Can't do nonzero cur-relative seeks");
547n/a return NULL;
548n/a }
549n/a
550n/a /* whence = 0: offset relative to beginning of the string.
551n/a whence = 1: no change to current position.
552n/a whence = 2: change position to end of file. */
553n/a if (whence == 1) {
554n/a pos = self->pos;
555n/a }
556n/a else if (whence == 2) {
557n/a pos = self->string_size;
558n/a }
559n/a
560n/a self->pos = pos;
561n/a
562n/a return PyLong_FromSsize_t(self->pos);
563n/a}
564n/a
565n/a/*[clinic input]
566n/a_io.StringIO.write
567n/a s as obj: object
568n/a /
569n/a
570n/aWrite string to file.
571n/a
572n/aReturns the number of characters written, which is always equal to
573n/athe length of the string.
574n/a[clinic start generated code]*/
575n/a
576n/astatic PyObject *
577n/a_io_StringIO_write(stringio *self, PyObject *obj)
578n/a/*[clinic end generated code: output=0deaba91a15b94da input=cf96f3b16586e669]*/
579n/a{
580n/a Py_ssize_t size;
581n/a
582n/a CHECK_INITIALIZED(self);
583n/a if (!PyUnicode_Check(obj)) {
584n/a PyErr_Format(PyExc_TypeError, "string argument expected, got '%s'",
585n/a Py_TYPE(obj)->tp_name);
586n/a return NULL;
587n/a }
588n/a if (PyUnicode_READY(obj))
589n/a return NULL;
590n/a CHECK_CLOSED(self);
591n/a size = PyUnicode_GET_LENGTH(obj);
592n/a
593n/a if (size > 0 && write_str(self, obj) < 0)
594n/a return NULL;
595n/a
596n/a return PyLong_FromSsize_t(size);
597n/a}
598n/a
599n/a/*[clinic input]
600n/a_io.StringIO.close
601n/a
602n/aClose the IO object.
603n/a
604n/aAttempting any further operation after the object is closed
605n/awill raise a ValueError.
606n/a
607n/aThis method has no effect if the file is already closed.
608n/a[clinic start generated code]*/
609n/a
610n/astatic PyObject *
611n/a_io_StringIO_close_impl(stringio *self)
612n/a/*[clinic end generated code: output=04399355cbe518f1 input=cbc10b45f35d6d46]*/
613n/a{
614n/a self->closed = 1;
615n/a /* Free up some memory */
616n/a if (resize_buffer(self, 0) < 0)
617n/a return NULL;
618n/a _PyAccu_Destroy(&self->accu);
619n/a Py_CLEAR(self->readnl);
620n/a Py_CLEAR(self->writenl);
621n/a Py_CLEAR(self->decoder);
622n/a Py_RETURN_NONE;
623n/a}
624n/a
625n/astatic int
626n/astringio_traverse(stringio *self, visitproc visit, void *arg)
627n/a{
628n/a Py_VISIT(self->dict);
629n/a return 0;
630n/a}
631n/a
632n/astatic int
633n/astringio_clear(stringio *self)
634n/a{
635n/a Py_CLEAR(self->dict);
636n/a return 0;
637n/a}
638n/a
639n/astatic void
640n/astringio_dealloc(stringio *self)
641n/a{
642n/a _PyObject_GC_UNTRACK(self);
643n/a self->ok = 0;
644n/a if (self->buf) {
645n/a PyMem_Free(self->buf);
646n/a self->buf = NULL;
647n/a }
648n/a _PyAccu_Destroy(&self->accu);
649n/a Py_CLEAR(self->readnl);
650n/a Py_CLEAR(self->writenl);
651n/a Py_CLEAR(self->decoder);
652n/a Py_CLEAR(self->dict);
653n/a if (self->weakreflist != NULL)
654n/a PyObject_ClearWeakRefs((PyObject *) self);
655n/a Py_TYPE(self)->tp_free(self);
656n/a}
657n/a
658n/astatic PyObject *
659n/astringio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
660n/a{
661n/a stringio *self;
662n/a
663n/a assert(type != NULL && type->tp_alloc != NULL);
664n/a self = (stringio *)type->tp_alloc(type, 0);
665n/a if (self == NULL)
666n/a return NULL;
667n/a
668n/a /* tp_alloc initializes all the fields to zero. So we don't have to
669n/a initialize them here. */
670n/a
671n/a self->buf = (Py_UCS4 *)PyMem_Malloc(0);
672n/a if (self->buf == NULL) {
673n/a Py_DECREF(self);
674n/a return PyErr_NoMemory();
675n/a }
676n/a
677n/a return (PyObject *)self;
678n/a}
679n/a
680n/a/*[clinic input]
681n/a_io.StringIO.__init__
682n/a initial_value as value: object(c_default="NULL") = ''
683n/a newline as newline_obj: object(c_default="NULL") = '\n'
684n/a
685n/aText I/O implementation using an in-memory buffer.
686n/a
687n/aThe initial_value argument sets the value of object. The newline
688n/aargument is like the one of TextIOWrapper's constructor.
689n/a[clinic start generated code]*/
690n/a
691n/astatic int
692n/a_io_StringIO___init___impl(stringio *self, PyObject *value,
693n/a PyObject *newline_obj)
694n/a/*[clinic end generated code: output=a421ea023b22ef4e input=cee2d9181b2577a3]*/
695n/a{
696n/a const char *newline = "\n";
697n/a Py_ssize_t value_len;
698n/a
699n/a /* Parse the newline argument. We only want to allow unicode objects or
700n/a None. */
701n/a if (newline_obj == Py_None) {
702n/a newline = NULL;
703n/a }
704n/a else if (newline_obj) {
705n/a if (!PyUnicode_Check(newline_obj)) {
706n/a PyErr_Format(PyExc_TypeError,
707n/a "newline must be str or None, not %.200s",
708n/a Py_TYPE(newline_obj)->tp_name);
709n/a return -1;
710n/a }
711n/a newline = PyUnicode_AsUTF8(newline_obj);
712n/a if (newline == NULL)
713n/a return -1;
714n/a }
715n/a
716n/a if (newline && newline[0] != '\0'
717n/a && !(newline[0] == '\n' && newline[1] == '\0')
718n/a && !(newline[0] == '\r' && newline[1] == '\0')
719n/a && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
720n/a PyErr_Format(PyExc_ValueError,
721n/a "illegal newline value: %R", newline_obj);
722n/a return -1;
723n/a }
724n/a if (value && value != Py_None && !PyUnicode_Check(value)) {
725n/a PyErr_Format(PyExc_TypeError,
726n/a "initial_value must be str or None, not %.200s",
727n/a Py_TYPE(value)->tp_name);
728n/a return -1;
729n/a }
730n/a
731n/a self->ok = 0;
732n/a
733n/a _PyAccu_Destroy(&self->accu);
734n/a Py_CLEAR(self->readnl);
735n/a Py_CLEAR(self->writenl);
736n/a Py_CLEAR(self->decoder);
737n/a
738n/a assert((newline != NULL && newline_obj != Py_None) ||
739n/a (newline == NULL && newline_obj == Py_None));
740n/a
741n/a if (newline) {
742n/a self->readnl = PyUnicode_FromString(newline);
743n/a if (self->readnl == NULL)
744n/a return -1;
745n/a }
746n/a self->readuniversal = (newline == NULL || newline[0] == '\0');
747n/a self->readtranslate = (newline == NULL);
748n/a /* If newline == "", we don't translate anything.
749n/a If newline == "\n" or newline == None, we translate to "\n", which is
750n/a a no-op.
751n/a (for newline == None, TextIOWrapper translates to os.linesep, but it
752n/a is pointless for StringIO)
753n/a */
754n/a if (newline != NULL && newline[0] == '\r') {
755n/a self->writenl = self->readnl;
756n/a Py_INCREF(self->writenl);
757n/a }
758n/a
759n/a if (self->readuniversal) {
760n/a self->decoder = PyObject_CallFunction(
761n/a (PyObject *)&PyIncrementalNewlineDecoder_Type,
762n/a "Oi", Py_None, (int) self->readtranslate);
763n/a if (self->decoder == NULL)
764n/a return -1;
765n/a }
766n/a
767n/a /* Now everything is set up, resize buffer to size of initial value,
768n/a and copy it */
769n/a self->string_size = 0;
770n/a if (value && value != Py_None)
771n/a value_len = PyUnicode_GetLength(value);
772n/a else
773n/a value_len = 0;
774n/a if (value_len > 0) {
775n/a /* This is a heuristic, for newline translation might change
776n/a the string length. */
777n/a if (resize_buffer(self, 0) < 0)
778n/a return -1;
779n/a self->state = STATE_REALIZED;
780n/a self->pos = 0;
781n/a if (write_str(self, value) < 0)
782n/a return -1;
783n/a }
784n/a else {
785n/a /* Empty stringio object, we can start by accumulating */
786n/a if (resize_buffer(self, 0) < 0)
787n/a return -1;
788n/a if (_PyAccu_Init(&self->accu))
789n/a return -1;
790n/a self->state = STATE_ACCUMULATING;
791n/a }
792n/a self->pos = 0;
793n/a
794n/a self->closed = 0;
795n/a self->ok = 1;
796n/a return 0;
797n/a}
798n/a
799n/a/* Properties and pseudo-properties */
800n/a
801n/a/*[clinic input]
802n/a_io.StringIO.readable
803n/a
804n/aReturns True if the IO object can be read.
805n/a[clinic start generated code]*/
806n/a
807n/astatic PyObject *
808n/a_io_StringIO_readable_impl(stringio *self)
809n/a/*[clinic end generated code: output=b19d44dd8b1ceb99 input=39ce068b224c21ad]*/
810n/a{
811n/a CHECK_INITIALIZED(self);
812n/a CHECK_CLOSED(self);
813n/a Py_RETURN_TRUE;
814n/a}
815n/a
816n/a/*[clinic input]
817n/a_io.StringIO.writable
818n/a
819n/aReturns True if the IO object can be written.
820n/a[clinic start generated code]*/
821n/a
822n/astatic PyObject *
823n/a_io_StringIO_writable_impl(stringio *self)
824n/a/*[clinic end generated code: output=13e4dd77187074ca input=7a691353aac38835]*/
825n/a{
826n/a CHECK_INITIALIZED(self);
827n/a CHECK_CLOSED(self);
828n/a Py_RETURN_TRUE;
829n/a}
830n/a
831n/a/*[clinic input]
832n/a_io.StringIO.seekable
833n/a
834n/aReturns True if the IO object can be seeked.
835n/a[clinic start generated code]*/
836n/a
837n/astatic PyObject *
838n/a_io_StringIO_seekable_impl(stringio *self)
839n/a/*[clinic end generated code: output=4d20b4641c756879 input=4c606d05b32952e6]*/
840n/a{
841n/a CHECK_INITIALIZED(self);
842n/a CHECK_CLOSED(self);
843n/a Py_RETURN_TRUE;
844n/a}
845n/a
846n/a/* Pickling support.
847n/a
848n/a The implementation of __getstate__ is similar to the one for BytesIO,
849n/a except that we also save the newline parameter. For __setstate__ and unlike
850n/a BytesIO, we call __init__ to restore the object's state. Doing so allows us
851n/a to avoid decoding the complex newline state while keeping the object
852n/a representation compact.
853n/a
854n/a See comment in bytesio.c regarding why only pickle protocols and onward are
855n/a supported.
856n/a*/
857n/a
858n/astatic PyObject *
859n/astringio_getstate(stringio *self)
860n/a{
861n/a PyObject *initvalue = _io_StringIO_getvalue_impl(self);
862n/a PyObject *dict;
863n/a PyObject *state;
864n/a
865n/a if (initvalue == NULL)
866n/a return NULL;
867n/a if (self->dict == NULL) {
868n/a Py_INCREF(Py_None);
869n/a dict = Py_None;
870n/a }
871n/a else {
872n/a dict = PyDict_Copy(self->dict);
873n/a if (dict == NULL)
874n/a return NULL;
875n/a }
876n/a
877n/a state = Py_BuildValue("(OOnN)", initvalue,
878n/a self->readnl ? self->readnl : Py_None,
879n/a self->pos, dict);
880n/a Py_DECREF(initvalue);
881n/a return state;
882n/a}
883n/a
884n/astatic PyObject *
885n/astringio_setstate(stringio *self, PyObject *state)
886n/a{
887n/a PyObject *initarg;
888n/a PyObject *position_obj;
889n/a PyObject *dict;
890n/a Py_ssize_t pos;
891n/a
892n/a assert(state != NULL);
893n/a CHECK_CLOSED(self);
894n/a
895n/a /* We allow the state tuple to be longer than 4, because we may need
896n/a someday to extend the object's state without breaking
897n/a backward-compatibility. */
898n/a if (!PyTuple_Check(state) || Py_SIZE(state) < 4) {
899n/a PyErr_Format(PyExc_TypeError,
900n/a "%.200s.__setstate__ argument should be 4-tuple, got %.200s",
901n/a Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
902n/a return NULL;
903n/a }
904n/a
905n/a /* Initialize the object's state. */
906n/a initarg = PyTuple_GetSlice(state, 0, 2);
907n/a if (initarg == NULL)
908n/a return NULL;
909n/a if (_io_StringIO___init__((PyObject *)self, initarg, NULL) < 0) {
910n/a Py_DECREF(initarg);
911n/a return NULL;
912n/a }
913n/a Py_DECREF(initarg);
914n/a
915n/a /* Restore the buffer state. Even if __init__ did initialize the buffer,
916n/a we have to initialize it again since __init__ may translate the
917n/a newlines in the initial_value string. We clearly do not want that
918n/a because the string value in the state tuple has already been translated
919n/a once by __init__. So we do not take any chance and replace object's
920n/a buffer completely. */
921n/a {
922n/a PyObject *item;
923n/a Py_UCS4 *buf;
924n/a Py_ssize_t bufsize;
925n/a
926n/a item = PyTuple_GET_ITEM(state, 0);
927n/a buf = PyUnicode_AsUCS4Copy(item);
928n/a if (buf == NULL)
929n/a return NULL;
930n/a bufsize = PyUnicode_GET_LENGTH(item);
931n/a
932n/a if (resize_buffer(self, bufsize) < 0) {
933n/a PyMem_Free(buf);
934n/a return NULL;
935n/a }
936n/a memcpy(self->buf, buf, bufsize * sizeof(Py_UCS4));
937n/a PyMem_Free(buf);
938n/a self->string_size = bufsize;
939n/a }
940n/a
941n/a /* Set carefully the position value. Alternatively, we could use the seek
942n/a method instead of modifying self->pos directly to better protect the
943n/a object internal state against errneous (or malicious) inputs. */
944n/a position_obj = PyTuple_GET_ITEM(state, 2);
945n/a if (!PyLong_Check(position_obj)) {
946n/a PyErr_Format(PyExc_TypeError,
947n/a "third item of state must be an integer, got %.200s",
948n/a Py_TYPE(position_obj)->tp_name);
949n/a return NULL;
950n/a }
951n/a pos = PyLong_AsSsize_t(position_obj);
952n/a if (pos == -1 && PyErr_Occurred())
953n/a return NULL;
954n/a if (pos < 0) {
955n/a PyErr_SetString(PyExc_ValueError,
956n/a "position value cannot be negative");
957n/a return NULL;
958n/a }
959n/a self->pos = pos;
960n/a
961n/a /* Set the dictionary of the instance variables. */
962n/a dict = PyTuple_GET_ITEM(state, 3);
963n/a if (dict != Py_None) {
964n/a if (!PyDict_Check(dict)) {
965n/a PyErr_Format(PyExc_TypeError,
966n/a "fourth item of state should be a dict, got a %.200s",
967n/a Py_TYPE(dict)->tp_name);
968n/a return NULL;
969n/a }
970n/a if (self->dict) {
971n/a /* Alternatively, we could replace the internal dictionary
972n/a completely. However, it seems more practical to just update it. */
973n/a if (PyDict_Update(self->dict, dict) < 0)
974n/a return NULL;
975n/a }
976n/a else {
977n/a Py_INCREF(dict);
978n/a self->dict = dict;
979n/a }
980n/a }
981n/a
982n/a Py_RETURN_NONE;
983n/a}
984n/a
985n/a
986n/astatic PyObject *
987n/astringio_closed(stringio *self, void *context)
988n/a{
989n/a CHECK_INITIALIZED(self);
990n/a return PyBool_FromLong(self->closed);
991n/a}
992n/a
993n/astatic PyObject *
994n/astringio_line_buffering(stringio *self, void *context)
995n/a{
996n/a CHECK_INITIALIZED(self);
997n/a CHECK_CLOSED(self);
998n/a Py_RETURN_FALSE;
999n/a}
1000n/a
1001n/astatic PyObject *
1002n/astringio_newlines(stringio *self, void *context)
1003n/a{
1004n/a CHECK_INITIALIZED(self);
1005n/a CHECK_CLOSED(self);
1006n/a if (self->decoder == NULL)
1007n/a Py_RETURN_NONE;
1008n/a return PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
1009n/a}
1010n/a
1011n/a#include "clinic/stringio.c.h"
1012n/a
1013n/astatic struct PyMethodDef stringio_methods[] = {
1014n/a _IO_STRINGIO_CLOSE_METHODDEF
1015n/a _IO_STRINGIO_GETVALUE_METHODDEF
1016n/a _IO_STRINGIO_READ_METHODDEF
1017n/a _IO_STRINGIO_READLINE_METHODDEF
1018n/a _IO_STRINGIO_TELL_METHODDEF
1019n/a _IO_STRINGIO_TRUNCATE_METHODDEF
1020n/a _IO_STRINGIO_SEEK_METHODDEF
1021n/a _IO_STRINGIO_WRITE_METHODDEF
1022n/a
1023n/a _IO_STRINGIO_SEEKABLE_METHODDEF
1024n/a _IO_STRINGIO_READABLE_METHODDEF
1025n/a _IO_STRINGIO_WRITABLE_METHODDEF
1026n/a
1027n/a {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
1028n/a {"__setstate__", (PyCFunction)stringio_setstate, METH_O},
1029n/a {NULL, NULL} /* sentinel */
1030n/a};
1031n/a
1032n/astatic PyGetSetDef stringio_getset[] = {
1033n/a {"closed", (getter)stringio_closed, NULL, NULL},
1034n/a {"newlines", (getter)stringio_newlines, NULL, NULL},
1035n/a /* (following comments straight off of the original Python wrapper:)
1036n/a XXX Cruft to support the TextIOWrapper API. This would only
1037n/a be meaningful if StringIO supported the buffer attribute.
1038n/a Hopefully, a better solution, than adding these pseudo-attributes,
1039n/a will be found.
1040n/a */
1041n/a {"line_buffering", (getter)stringio_line_buffering, NULL, NULL},
1042n/a {NULL}
1043n/a};
1044n/a
1045n/aPyTypeObject PyStringIO_Type = {
1046n/a PyVarObject_HEAD_INIT(NULL, 0)
1047n/a "_io.StringIO", /*tp_name*/
1048n/a sizeof(stringio), /*tp_basicsize*/
1049n/a 0, /*tp_itemsize*/
1050n/a (destructor)stringio_dealloc, /*tp_dealloc*/
1051n/a 0, /*tp_print*/
1052n/a 0, /*tp_getattr*/
1053n/a 0, /*tp_setattr*/
1054n/a 0, /*tp_reserved*/
1055n/a 0, /*tp_repr*/
1056n/a 0, /*tp_as_number*/
1057n/a 0, /*tp_as_sequence*/
1058n/a 0, /*tp_as_mapping*/
1059n/a 0, /*tp_hash*/
1060n/a 0, /*tp_call*/
1061n/a 0, /*tp_str*/
1062n/a 0, /*tp_getattro*/
1063n/a 0, /*tp_setattro*/
1064n/a 0, /*tp_as_buffer*/
1065n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1066n/a | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1067n/a _io_StringIO___init____doc__, /*tp_doc*/
1068n/a (traverseproc)stringio_traverse, /*tp_traverse*/
1069n/a (inquiry)stringio_clear, /*tp_clear*/
1070n/a 0, /*tp_richcompare*/
1071n/a offsetof(stringio, weakreflist), /*tp_weaklistoffset*/
1072n/a 0, /*tp_iter*/
1073n/a (iternextfunc)stringio_iternext, /*tp_iternext*/
1074n/a stringio_methods, /*tp_methods*/
1075n/a 0, /*tp_members*/
1076n/a stringio_getset, /*tp_getset*/
1077n/a 0, /*tp_base*/
1078n/a 0, /*tp_dict*/
1079n/a 0, /*tp_descr_get*/
1080n/a 0, /*tp_descr_set*/
1081n/a offsetof(stringio, dict), /*tp_dictoffset*/
1082n/a _io_StringIO___init__, /*tp_init*/
1083n/a 0, /*tp_alloc*/
1084n/a stringio_new, /*tp_new*/
1085n/a};