]>
Commit | Line | Data |
---|---|---|
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 | |
10 | typedef 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 | |
43 | PyDoc_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 | |
53 | static int\r | |
54 | resize_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 | |
108 | static Py_ssize_t\r | |
109 | write_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 | |
180 | fail:\r | |
181 | Py_XDECREF(decoded);\r | |
182 | return -1;\r | |
183 | }\r | |
184 | \r | |
185 | PyDoc_STRVAR(stringio_getvalue_doc,\r | |
186 | "Retrieve the entire contents of the object.");\r | |
187 | \r | |
188 | static PyObject *\r | |
189 | stringio_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 | |
196 | PyDoc_STRVAR(stringio_tell_doc,\r | |
197 | "Tell the current file position.");\r | |
198 | \r | |
199 | static PyObject *\r | |
200 | stringio_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 | |
207 | PyDoc_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 | |
213 | static PyObject *\r | |
214 | stringio_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 | |
254 | static 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 | |
283 | PyDoc_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 | |
288 | static PyObject *\r | |
289 | stringio_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 | |
312 | static PyObject *\r | |
313 | stringio_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 | |
349 | PyDoc_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 | |
356 | static PyObject *\r | |
357 | stringio_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 | |
397 | PyDoc_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 | |
406 | static PyObject *\r | |
407 | stringio_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 | |
454 | PyDoc_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 | |
460 | static PyObject *\r | |
461 | stringio_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 | |
480 | PyDoc_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 | |
486 | static PyObject *\r | |
487 | stringio_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 | |
499 | static int\r | |
500 | stringio_traverse(stringio *self, visitproc visit, void *arg)\r | |
501 | {\r | |
502 | Py_VISIT(self->dict);\r | |
503 | return 0;\r | |
504 | }\r | |
505 | \r | |
506 | static int\r | |
507 | stringio_clear(stringio *self)\r | |
508 | {\r | |
509 | Py_CLEAR(self->dict);\r | |
510 | return 0;\r | |
511 | }\r | |
512 | \r | |
513 | static void\r | |
514 | stringio_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 | |
531 | static PyObject *\r | |
532 | stringio_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 | |
553 | static int\r | |
554 | stringio_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 | |
636 | PyDoc_STRVAR(stringio_readable_doc,\r | |
637 | "readable() -> bool. Returns True if the IO object can be read.");\r | |
638 | \r | |
639 | PyDoc_STRVAR(stringio_writable_doc,\r | |
640 | "writable() -> bool. Returns True if the IO object can be written.");\r | |
641 | \r | |
642 | PyDoc_STRVAR(stringio_seekable_doc,\r | |
643 | "seekable() -> bool. Returns True if the IO object can be seeked.");\r | |
644 | \r | |
645 | static PyObject *\r | |
646 | stringio_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 | |
653 | static PyObject *\r | |
654 | stringio_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 | |
661 | static PyObject *\r | |
662 | stringio_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 | |
681 | static PyObject *\r | |
682 | stringio_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 | |
707 | static PyObject *\r | |
708 | stringio_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 | |
798 | static PyObject *\r | |
799 | stringio_closed(stringio *self, void *context)\r | |
800 | {\r | |
801 | CHECK_INITIALIZED(self);\r | |
802 | return PyBool_FromLong(self->closed);\r | |
803 | }\r | |
804 | \r | |
805 | static PyObject *\r | |
806 | stringio_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 | |
813 | static PyObject *\r | |
814 | stringio_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 | |
823 | static 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 | |
842 | static 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 | |
855 | PyTypeObject 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 |