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