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