Python-2.7.3/Modules/_io/stringio.c

No issues found

  1 #define PY_SSIZE_T_CLEAN
  2 #include "Python.h"
  3 #include "structmember.h"
  4 #include "_iomodule.h"
  5 
  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.
  8 */
  9 
 10 typedef struct {
 11     PyObject_HEAD
 12     Py_UNICODE *buf;
 13     Py_ssize_t pos;
 14     Py_ssize_t string_size;
 15     size_t buf_size;
 16 
 17     char ok; /* initialized? */
 18     char closed;
 19     char readuniversal;
 20     char readtranslate;
 21     PyObject *decoder;
 22     PyObject *readnl;
 23     PyObject *writenl;
 24     
 25     PyObject *dict;
 26     PyObject *weakreflist;
 27 } stringio;
 28 
 29 #define CHECK_INITIALIZED(self) \
 30     if (self->ok <= 0) { \
 31         PyErr_SetString(PyExc_ValueError, \
 32             "I/O operation on uninitialized object"); \
 33         return NULL; \
 34     }
 35 
 36 #define CHECK_CLOSED(self) \
 37     if (self->closed) { \
 38         PyErr_SetString(PyExc_ValueError, \
 39             "I/O operation on closed file"); \
 40         return NULL; \
 41     }
 42 
 43 PyDoc_STRVAR(stringio_doc,
 44     "Text I/O implementation using an in-memory buffer.\n"
 45     "\n"
 46     "The initial_value argument sets the value of object.  The newline\n"
 47     "argument is like the one of TextIOWrapper's constructor.");
 48 
 49 
 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. */
 53 static int
 54 resize_buffer(stringio *self, size_t size)
 55 {
 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;
 60 
 61     assert(self->buf != NULL);
 62 
 63     /* Reserve one more char for line ending detection. */
 64     size = size + 1;
 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)
 68         goto overflow;
 69 
 70     if (size < alloc / 2) {
 71         /* Major downsize; resize down to exact size. */
 72         alloc = size + 1;
 73     }
 74     else if (size < alloc) {
 75         /* Within allocated size; quick exit */
 76         return 0;
 77     }
 78     else if (size <= alloc * 1.125) {
 79         /* Moderate upsize; overallocate similar to list_resize() */
 80         alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
 81     }
 82     else {
 83         /* Major upsize; resize up to exact size */
 84         alloc = size + 1;
 85     }
 86 
 87     if (alloc > ((size_t)-1) / sizeof(Py_UNICODE))
 88         goto overflow;
 89     new_buf = (Py_UNICODE *)PyMem_Realloc(self->buf,
 90                                           alloc * sizeof(Py_UNICODE));
 91     if (new_buf == NULL) {
 92         PyErr_NoMemory();
 93         return -1;
 94     }
 95     self->buf_size = alloc;
 96     self->buf = new_buf;
 97 
 98     return 0;
 99 
100   overflow:
101     PyErr_SetString(PyExc_OverflowError,
102                     "new buffer size too large");
103     return -1;
104 }
105 
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. */
108 static Py_ssize_t
109 write_str(stringio *self, PyObject *obj)
110 {
111     Py_UNICODE *str;
112     Py_ssize_t len;
113     PyObject *decoded = NULL;
114     assert(self->buf != NULL);
115     assert(self->pos >= 0);
116 
117     if (self->decoder != NULL) {
118         decoded = _PyIncrementalNewlineDecoder_decode(
119             self->decoder, obj, 1 /* always final */);
120     }
121     else {
122         decoded = obj;
123         Py_INCREF(decoded);
124     }
125     if (self->writenl) {
126         PyObject *translated = PyUnicode_Replace(
127             decoded, _PyIO_str_nl, self->writenl, -1);
128         Py_DECREF(decoded);
129         decoded = translated;
130     }
131     if (decoded == NULL)
132         return -1;
133 
134     assert(PyUnicode_Check(decoded));
135     str = PyUnicode_AS_UNICODE(decoded);
136     len = PyUnicode_GET_SIZE(decoded);
137 
138     assert(len >= 0);
139 
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
142        integer. */
143     if (self->pos > PY_SSIZE_T_MAX - len) {
144         PyErr_SetString(PyExc_OverflowError,
145                         "new position too large");
146         goto fail;
147     }
148     if (self->pos + len > self->string_size) {
149         if (resize_buffer(self, self->pos + len) < 0)
150             goto fail;
151     }
152 
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.
156 
157           0   lo      string_size                           hi
158           |   |<---used--->|<----------available----------->|
159           |   |            <--to pad-->|<---to write--->    |
160           0   buf                   position
161 
162         */
163         memset(self->buf + self->string_size, '\0',
164                (self->pos - self->string_size) * sizeof(Py_UNICODE));
165     }
166 
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));
170     self->pos += len;
171 
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;
175     }
176 
177     Py_DECREF(decoded);
178     return 0;
179 
180 fail:
181     Py_XDECREF(decoded);
182     return -1;
183 }
184 
185 PyDoc_STRVAR(stringio_getvalue_doc,
186     "Retrieve the entire contents of the object.");
187 
188 static PyObject *
189 stringio_getvalue(stringio *self)
190 {
191     CHECK_INITIALIZED(self);
192     CHECK_CLOSED(self);
193     return PyUnicode_FromUnicode(self->buf, self->string_size);
194 }
195 
196 PyDoc_STRVAR(stringio_tell_doc,
197     "Tell the current file position.");
198 
199 static PyObject *
200 stringio_tell(stringio *self)
201 {
202     CHECK_INITIALIZED(self);
203     CHECK_CLOSED(self);
204     return PyLong_FromSsize_t(self->pos);
205 }
206 
207 PyDoc_STRVAR(stringio_read_doc,
208     "Read at most n characters, returned as a string.\n"
209     "\n"
210     "If the argument is negative or omitted, read until EOF\n"
211     "is reached. Return an empty string at EOF.\n");
212 
213 static PyObject *
214 stringio_read(stringio *self, PyObject *args)
215 {
216     Py_ssize_t size, n;
217     Py_UNICODE *output;
218     PyObject *arg = Py_None;
219 
220     CHECK_INITIALIZED(self);
221     if (!PyArg_ParseTuple(args, "|O:read", &arg))
222         return NULL;
223     CHECK_CLOSED(self);
224 
225     if (PyNumber_Check(arg)) {
226         size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
227         if (size == -1 && PyErr_Occurred())
228             return NULL;
229     }
230     else if (arg == Py_None) {
231         /* Read until EOF is reached, by default. */
232         size = -1;
233     }
234     else {
235         PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
236                      Py_TYPE(arg)->tp_name);
237         return NULL;
238     }
239 
240     /* adjust invalid sizes */
241     n = self->string_size - self->pos;
242     if (size < 0 || size > n) {
243         size = n;
244         if (size < 0)
245             size = 0;
246     }
247 
248     output = self->buf + self->pos;
249     self->pos += size;
250     return PyUnicode_FromUnicode(output, size);
251 }
252 
253 /* Internal helper, used by stringio_readline and stringio_iternext */
254 static PyObject *
255 _stringio_readline(stringio *self, Py_ssize_t limit)
256 {
257     Py_UNICODE *start, *end, old_char;
258     Py_ssize_t len, consumed;
259 
260     /* In case of overseek, return the empty string */
261     if (self->pos >= self->string_size)
262         return PyUnicode_FromString("");
263 
264     start = self->buf + self->pos;
265     if (limit < 0 || limit > self->string_size - self->pos)
266         limit = self->string_size - self->pos;
267 
268     end = start + limit;
269     old_char = *end;
270     *end = '\0';
271     len = _PyIO_find_line_ending(
272         self->readtranslate, self->readuniversal, self->readnl,
273         start, end, &consumed);
274     *end = old_char;
275     /* If we haven't found any line ending, we just return everything
276        (`consumed` is ignored). */
277     if (len < 0)
278         len = limit;
279     self->pos += len;
280     return PyUnicode_FromUnicode(start, len);
281 }
282 
283 PyDoc_STRVAR(stringio_readline_doc,
284     "Read until newline or EOF.\n"
285     "\n"
286     "Returns an empty string if EOF is hit immediately.\n");
287 
288 static PyObject *
289 stringio_readline(stringio *self, PyObject *args)
290 {
291     PyObject *arg = Py_None;
292     Py_ssize_t limit = -1;
293 
294     CHECK_INITIALIZED(self);
295     if (!PyArg_ParseTuple(args, "|O:readline", &arg))
296         return NULL;
297     CHECK_CLOSED(self);
298 
299     if (PyNumber_Check(arg)) {
300         limit = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
301         if (limit == -1 && PyErr_Occurred())
302             return NULL;
303     }
304     else if (arg != Py_None) {
305         PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
306                      Py_TYPE(arg)->tp_name);
307         return NULL;
308     }
309     return _stringio_readline(self, limit);
310 }
311 
312 static PyObject *
313 stringio_iternext(stringio *self)
314 {
315     PyObject *line;
316 
317     CHECK_INITIALIZED(self);
318     CHECK_CLOSED(self);
319 
320     if (Py_TYPE(self) == &PyStringIO_Type) {
321         /* Skip method call overhead for speed */
322         line = _stringio_readline(self, -1);
323     }
324     else {
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);
332             Py_DECREF(line);
333             return NULL;
334         }
335     }
336 
337     if (line == NULL)
338         return NULL;
339 
340     if (PyUnicode_GET_SIZE(line) == 0) {
341         /* Reached EOF */
342         Py_DECREF(line);
343         return NULL;
344     }
345 
346     return line;
347 }
348 
349 PyDoc_STRVAR(stringio_truncate_doc,
350     "Truncate size to pos.\n"
351     "\n"
352     "The pos argument defaults to the current file position, as\n"
353     "returned by tell().  The current file position is unchanged.\n"
354     "Returns the new absolute position.\n");
355 
356 static PyObject *
357 stringio_truncate(stringio *self, PyObject *args)
358 {
359     Py_ssize_t size;
360     PyObject *arg = Py_None;
361 
362     CHECK_INITIALIZED(self);
363     if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
364         return NULL;
365     CHECK_CLOSED(self);
366 
367     if (PyNumber_Check(arg)) {
368         size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
369         if (size == -1 && PyErr_Occurred())
370             return NULL;
371     }
372     else if (arg == Py_None) {
373         /* Truncate to current position if no argument is passed. */
374         size = self->pos;
375     }
376     else {
377         PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
378                      Py_TYPE(arg)->tp_name);
379         return NULL;
380     }
381 
382     if (size < 0) {
383         PyErr_Format(PyExc_ValueError,
384                      "Negative size value %zd", size);
385         return NULL;
386     }
387 
388     if (size < self->string_size) {
389         if (resize_buffer(self, size) < 0)
390             return NULL;
391         self->string_size = size;
392     }
393 
394     return PyLong_FromSsize_t(size);
395 }
396 
397 PyDoc_STRVAR(stringio_seek_doc,
398     "Change stream position.\n"
399     "\n"
400     "Seek to character offset pos relative to position indicated by whence:\n"
401     "    0  Start of stream (the default).  pos should be >= 0;\n"
402     "    1  Current position - pos must be 0;\n"
403     "    2  End of stream - pos must be 0.\n"
404     "Returns the new absolute position.\n");
405 
406 static PyObject *
407 stringio_seek(stringio *self, PyObject *args)
408 {
409     PyObject *posobj;
410     Py_ssize_t pos;
411     int mode = 0;
412 
413     CHECK_INITIALIZED(self);
414     if (!PyArg_ParseTuple(args, "O|i:seek", &posobj, &mode))
415         return NULL;
416 
417     pos = PyNumber_AsSsize_t(posobj, PyExc_OverflowError);
418     if (pos == -1 && PyErr_Occurred())
419         return NULL;
420     
421     CHECK_CLOSED(self);
422 
423     if (mode != 0 && mode != 1 && mode != 2) {
424         PyErr_Format(PyExc_ValueError,
425                      "Invalid whence (%i, should be 0, 1 or 2)", mode);
426         return NULL;
427     }
428     else if (pos < 0 && mode == 0) {
429         PyErr_Format(PyExc_ValueError,
430                      "Negative seek position %zd", pos);
431         return NULL;
432     }
433     else if (mode != 0 && pos != 0) {
434         PyErr_SetString(PyExc_IOError,
435                         "Can't do nonzero cur-relative seeks");
436         return NULL;
437     }
438 
439     /* mode 0: offset relative to beginning of the string.
440        mode 1: no change to current position.
441        mode 2: change position to end of file. */
442     if (mode == 1) {
443         pos = self->pos;
444     }
445     else if (mode == 2) {
446         pos = self->string_size;
447     }
448 
449     self->pos = pos;
450 
451     return PyLong_FromSsize_t(self->pos);
452 }
453 
454 PyDoc_STRVAR(stringio_write_doc,
455     "Write string to file.\n"
456     "\n"
457     "Returns the number of characters written, which is always equal to\n"
458     "the length of the string.\n");
459 
460 static PyObject *
461 stringio_write(stringio *self, PyObject *obj)
462 {
463     Py_ssize_t size;
464 
465     CHECK_INITIALIZED(self);
466     if (!PyUnicode_Check(obj)) {
467         PyErr_Format(PyExc_TypeError, "unicode argument expected, got '%s'",
468                      Py_TYPE(obj)->tp_name);
469         return NULL;
470     }
471     CHECK_CLOSED(self);
472     size = PyUnicode_GET_SIZE(obj);
473 
474     if (size > 0 && write_str(self, obj) < 0)
475         return NULL;
476 
477     return PyLong_FromSsize_t(size);
478 }
479 
480 PyDoc_STRVAR(stringio_close_doc,
481     "Close the IO object. Attempting any further operation after the\n"
482     "object is closed will raise a ValueError.\n"
483     "\n"
484     "This method has no effect if the file is already closed.\n");
485 
486 static PyObject *
487 stringio_close(stringio *self)
488 {
489     self->closed = 1;
490     /* Free up some memory */
491     if (resize_buffer(self, 0) < 0)
492         return NULL;
493     Py_CLEAR(self->readnl);
494     Py_CLEAR(self->writenl);
495     Py_CLEAR(self->decoder);
496     Py_RETURN_NONE;
497 }
498 
499 static int
500 stringio_traverse(stringio *self, visitproc visit, void *arg)
501 {
502     Py_VISIT(self->dict);
503     return 0;
504 }
505 
506 static int
507 stringio_clear(stringio *self)
508 {
509     Py_CLEAR(self->dict);
510     return 0;
511 }
512 
513 static void
514 stringio_dealloc(stringio *self)
515 {
516     _PyObject_GC_UNTRACK(self);
517     self->ok = 0;
518     if (self->buf) {
519         PyMem_Free(self->buf);
520         self->buf = NULL;
521     }
522     Py_CLEAR(self->readnl);
523     Py_CLEAR(self->writenl);
524     Py_CLEAR(self->decoder);
525     Py_CLEAR(self->dict);
526     if (self->weakreflist != NULL)
527         PyObject_ClearWeakRefs((PyObject *) self);
528     Py_TYPE(self)->tp_free(self);
529 }
530 
531 static PyObject *
532 stringio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
533 {
534     stringio *self;
535 
536     assert(type != NULL && type->tp_alloc != NULL);
537     self = (stringio *)type->tp_alloc(type, 0);
538     if (self == NULL)
539         return NULL;
540 
541     /* tp_alloc initializes all the fields to zero. So we don't have to
542        initialize them here. */
543 
544     self->buf = (Py_UNICODE *)PyMem_Malloc(0);
545     if (self->buf == NULL) {
546         Py_DECREF(self);
547         return PyErr_NoMemory();
548     }
549 
550     return (PyObject *)self;
551 }
552 
553 static int
554 stringio_init(stringio *self, PyObject *args, PyObject *kwds)
555 {
556     char *kwlist[] = {"initial_value", "newline", NULL};
557     PyObject *value = NULL;
558     char *newline = "\n";
559 
560     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oz:__init__", kwlist,
561                                      &value, &newline))
562         return -1;
563 
564     if (newline && newline[0] != '\0'
565         && !(newline[0] == '\n' && newline[1] == '\0')
566         && !(newline[0] == '\r' && newline[1] == '\0')
567         && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
568         PyErr_Format(PyExc_ValueError,
569                      "illegal newline value: %s", newline);
570         return -1;
571     }
572     if (value && value != Py_None && !PyUnicode_Check(value)) {
573         PyErr_Format(PyExc_TypeError,
574                      "initial_value must be unicode or None, not %.200s",
575                      Py_TYPE(value)->tp_name);
576         return -1;
577     }
578 
579     self->ok = 0;
580 
581     Py_CLEAR(self->readnl);
582     Py_CLEAR(self->writenl);
583     Py_CLEAR(self->decoder);
584 
585     if (newline) {
586         self->readnl = PyString_FromString(newline);
587         if (self->readnl == NULL)
588             return -1;
589     }
590     self->readuniversal = (newline == NULL || newline[0] == '\0');
591     self->readtranslate = (newline == NULL);
592     /* If newline == "", we don't translate anything.
593        If newline == "\n" or newline == None, we translate to "\n", which is
594        a no-op.
595        (for newline == None, TextIOWrapper translates to os.sepline, but it
596        is pointless for StringIO)
597     */
598     if (newline != NULL && newline[0] == '\r') {
599         self->writenl = PyUnicode_FromString(newline);
600     }
601 
602     if (self->readuniversal) {
603         self->decoder = PyObject_CallFunction(
604             (PyObject *)&PyIncrementalNewlineDecoder_Type,
605             "Oi", Py_None, (int) self->readtranslate);
606         if (self->decoder == NULL)
607             return -1;
608     }
609 
610     /* Now everything is set up, resize buffer to size of initial value,
611        and copy it */
612     self->string_size = 0;
613     if (value && value != Py_None) {
614         Py_ssize_t len = PyUnicode_GetSize(value);
615         /* This is a heuristic, for newline translation might change
616            the string length. */
617         if (resize_buffer(self, len) < 0)
618             return -1;
619         self->pos = 0;
620         if (write_str(self, value) < 0)
621             return -1;
622     }
623     else {
624         if (resize_buffer(self, 0) < 0)
625             return -1;
626     }
627     self->pos = 0;
628 
629     self->closed = 0;
630     self->ok = 1;
631     return 0;
632 }
633 
634 /* Properties and pseudo-properties */
635 static PyObject *
636 stringio_seekable(stringio *self, PyObject *args)
637 {
638     CHECK_INITIALIZED(self);
639     Py_RETURN_TRUE;
640 }
641 
642 static PyObject *
643 stringio_readable(stringio *self, PyObject *args)
644 {
645     CHECK_INITIALIZED(self);
646     Py_RETURN_TRUE;
647 }
648 
649 static PyObject *
650 stringio_writable(stringio *self, PyObject *args)
651 {
652     CHECK_INITIALIZED(self);
653     Py_RETURN_TRUE;
654 }
655 
656 /* Pickling support.
657 
658    The implementation of __getstate__ is similar to the one for BytesIO,
659    except that we also save the newline parameter. For __setstate__ and unlike
660    BytesIO, we call __init__ to restore the object's state. Doing so allows us
661    to avoid decoding the complex newline state while keeping the object
662    representation compact.
663 
664    See comment in bytesio.c regarding why only pickle protocols and onward are
665    supported.
666 */
667 
668 static PyObject *
669 stringio_getstate(stringio *self)
670 {
671     PyObject *initvalue = stringio_getvalue(self);
672     PyObject *dict;
673     PyObject *state;
674 
675     if (initvalue == NULL)
676         return NULL;
677     if (self->dict == NULL) {
678         Py_INCREF(Py_None);
679         dict = Py_None;
680     }
681     else {
682         dict = PyDict_Copy(self->dict);
683         if (dict == NULL)
684             return NULL;
685     }
686 
687     state = Py_BuildValue("(OOnN)", initvalue,
688                           self->readnl ? self->readnl : Py_None,
689                           self->pos, dict);
690     Py_DECREF(initvalue);
691     return state;
692 }
693 
694 static PyObject *
695 stringio_setstate(stringio *self, PyObject *state)
696 {
697     PyObject *initarg;
698     PyObject *position_obj;
699     PyObject *dict;
700     Py_ssize_t pos;
701 
702     assert(state != NULL);
703     CHECK_CLOSED(self);
704 
705     /* We allow the state tuple to be longer than 4, because we may need
706        someday to extend the object's state without breaking
707        backward-compatibility. */
708     if (!PyTuple_Check(state) || Py_SIZE(state) < 4) {
709         PyErr_Format(PyExc_TypeError,
710                      "%.200s.__setstate__ argument should be 4-tuple, got %.200s",
711                      Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
712         return NULL;
713     }
714 
715     /* Initialize the object's state. */
716     initarg = PyTuple_GetSlice(state, 0, 2);
717     if (initarg == NULL)
718         return NULL;
719     if (stringio_init(self, initarg, NULL) < 0) {
720         Py_DECREF(initarg);
721         return NULL;
722     }
723     Py_DECREF(initarg);
724 
725     /* Restore the buffer state. Even if __init__ did initialize the buffer,
726        we have to initialize it again since __init__ may translates the
727        newlines in the inital_value string. We clearly do not want that
728        because the string value in the state tuple has already been translated
729        once by __init__. So we do not take any chance and replace object's
730        buffer completely. */
731     {
732         Py_UNICODE *buf = PyUnicode_AS_UNICODE(PyTuple_GET_ITEM(state, 0));
733         Py_ssize_t bufsize = PyUnicode_GET_SIZE(PyTuple_GET_ITEM(state, 0));
734         if (resize_buffer(self, bufsize) < 0)
735             return NULL;
736         memcpy(self->buf, buf, bufsize * sizeof(Py_UNICODE));
737         self->string_size = bufsize;
738     }
739 
740     /* Set carefully the position value. Alternatively, we could use the seek
741        method instead of modifying self->pos directly to better protect the
742        object internal state against errneous (or malicious) inputs. */
743     position_obj = PyTuple_GET_ITEM(state, 2);
744     if (!PyIndex_Check(position_obj)) {
745         PyErr_Format(PyExc_TypeError,
746                      "third item of state must be an integer, got %.200s",
747                      Py_TYPE(position_obj)->tp_name);
748         return NULL;
749     }
750     pos = PyNumber_AsSsize_t(position_obj, PyExc_OverflowError);
751     if (pos == -1 && PyErr_Occurred())
752         return NULL;
753     if (pos < 0) {
754         PyErr_SetString(PyExc_ValueError,
755                         "position value cannot be negative");
756         return NULL;
757     }
758     self->pos = pos;
759 
760     /* Set the dictionary of the instance variables. */
761     dict = PyTuple_GET_ITEM(state, 3);
762     if (dict != Py_None) {
763         if (!PyDict_Check(dict)) {
764             PyErr_Format(PyExc_TypeError,
765                          "fourth item of state should be a dict, got a %.200s",
766                          Py_TYPE(dict)->tp_name);
767             return NULL;
768         }
769         if (self->dict) {
770             /* Alternatively, we could replace the internal dictionary
771                completely. However, it seems more practical to just update it. */
772             if (PyDict_Update(self->dict, dict) < 0)
773                 return NULL;
774         }
775         else {
776             Py_INCREF(dict);
777             self->dict = dict;
778         }
779     }
780 
781     Py_RETURN_NONE;
782 }
783 
784 
785 static PyObject *
786 stringio_closed(stringio *self, void *context)
787 {
788     CHECK_INITIALIZED(self);
789     return PyBool_FromLong(self->closed);
790 }
791 
792 static PyObject *
793 stringio_line_buffering(stringio *self, void *context)
794 {
795     CHECK_INITIALIZED(self);
796     CHECK_CLOSED(self);
797     Py_RETURN_FALSE;
798 }
799 
800 static PyObject *
801 stringio_newlines(stringio *self, void *context)
802 {
803     CHECK_INITIALIZED(self);
804     CHECK_CLOSED(self);
805     if (self->decoder == NULL)
806         Py_RETURN_NONE;
807     return PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
808 }
809 
810 static struct PyMethodDef stringio_methods[] = {
811     {"close",    (PyCFunction)stringio_close,    METH_NOARGS,  stringio_close_doc},
812     {"getvalue", (PyCFunction)stringio_getvalue, METH_NOARGS,  stringio_getvalue_doc},
813     {"read",     (PyCFunction)stringio_read,     METH_VARARGS, stringio_read_doc},
814     {"readline", (PyCFunction)stringio_readline, METH_VARARGS, stringio_readline_doc},
815     {"tell",     (PyCFunction)stringio_tell,     METH_NOARGS,  stringio_tell_doc},
816     {"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, stringio_truncate_doc},
817     {"seek",     (PyCFunction)stringio_seek,     METH_VARARGS, stringio_seek_doc},
818     {"write",    (PyCFunction)stringio_write,    METH_O,       stringio_write_doc},
819 
820     {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS},
821     {"readable", (PyCFunction)stringio_readable, METH_NOARGS},
822     {"writable", (PyCFunction)stringio_writable, METH_NOARGS},
823 
824     {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
825     {"__setstate__", (PyCFunction)stringio_setstate, METH_O},
826     {NULL, NULL}        /* sentinel */
827 };
828 
829 static PyGetSetDef stringio_getset[] = {
830     {"closed",         (getter)stringio_closed,         NULL, NULL},
831     {"newlines",       (getter)stringio_newlines,       NULL, NULL},
832     /*  (following comments straight off of the original Python wrapper:)
833         XXX Cruft to support the TextIOWrapper API. This would only
834         be meaningful if StringIO supported the buffer attribute.
835         Hopefully, a better solution, than adding these pseudo-attributes,
836         will be found.
837     */
838     {"line_buffering", (getter)stringio_line_buffering, NULL, NULL},
839     {NULL}
840 };
841 
842 PyTypeObject PyStringIO_Type = {
843     PyVarObject_HEAD_INIT(NULL, 0)
844     "_io.StringIO",                            /*tp_name*/
845     sizeof(stringio),                    /*tp_basicsize*/
846     0,                                         /*tp_itemsize*/
847     (destructor)stringio_dealloc,              /*tp_dealloc*/
848     0,                                         /*tp_print*/
849     0,                                         /*tp_getattr*/
850     0,                                         /*tp_setattr*/
851     0,                                         /*tp_reserved*/
852     0,                                         /*tp_repr*/
853     0,                                         /*tp_as_number*/
854     0,                                         /*tp_as_sequence*/
855     0,                                         /*tp_as_mapping*/
856     0,                                         /*tp_hash*/
857     0,                                         /*tp_call*/
858     0,                                         /*tp_str*/
859     0,                                         /*tp_getattro*/
860     0,                                         /*tp_setattro*/
861     0,                                         /*tp_as_buffer*/
862     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
863                        | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
864     stringio_doc,                              /*tp_doc*/
865     (traverseproc)stringio_traverse,           /*tp_traverse*/
866     (inquiry)stringio_clear,                   /*tp_clear*/
867     0,                                         /*tp_richcompare*/
868     offsetof(stringio, weakreflist),            /*tp_weaklistoffset*/
869     0,                                         /*tp_iter*/
870     (iternextfunc)stringio_iternext,           /*tp_iternext*/
871     stringio_methods,                          /*tp_methods*/
872     0,                                         /*tp_members*/
873     stringio_getset,                           /*tp_getset*/
874     0,                                         /*tp_base*/
875     0,                                         /*tp_dict*/
876     0,                                         /*tp_descr_get*/
877     0,                                         /*tp_descr_set*/
878     offsetof(stringio, dict),                  /*tp_dictoffset*/
879     (initproc)stringio_init,                   /*tp_init*/
880     0,                                         /*tp_alloc*/
881     stringio_new,                              /*tp_new*/
882 };