]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.10/Modules/_io/textio.c
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / Modules / _io / textio.c
CommitLineData
7eb75bcc
DM
1/*\r
2 An implementation of Text I/O as defined by PEP 3116 - "New I/O"\r
3\r
4 Classes defined here: TextIOBase, IncrementalNewlineDecoder, TextIOWrapper.\r
5\r
6 Written by Amaury Forgeot d'Arc and Antoine Pitrou\r
7*/\r
8\r
9#define PY_SSIZE_T_CLEAN\r
10#include "Python.h"\r
11#include "structmember.h"\r
12#include "_iomodule.h"\r
13\r
14/* TextIOBase */\r
15\r
16PyDoc_STRVAR(textiobase_doc,\r
17 "Base class for text I/O.\n"\r
18 "\n"\r
19 "This class provides a character and line based interface to stream\n"\r
20 "I/O. There is no readinto method because Python's character strings\n"\r
21 "are immutable. There is no public constructor.\n"\r
22 );\r
23\r
24static PyObject *\r
25_unsupported(const char *message)\r
26{\r
27 PyErr_SetString(_PyIO_unsupported_operation, message);\r
28 return NULL;\r
29}\r
30\r
31PyDoc_STRVAR(textiobase_detach_doc,\r
32 "Separate the underlying buffer from the TextIOBase and return it.\n"\r
33 "\n"\r
34 "After the underlying buffer has been detached, the TextIO is in an\n"\r
35 "unusable state.\n"\r
36 );\r
37\r
38static PyObject *\r
39textiobase_detach(PyObject *self)\r
40{\r
41 return _unsupported("detach");\r
42}\r
43\r
44PyDoc_STRVAR(textiobase_read_doc,\r
45 "Read at most n characters from stream.\n"\r
46 "\n"\r
47 "Read from underlying buffer until we have n characters or we hit EOF.\n"\r
48 "If n is negative or omitted, read until EOF.\n"\r
49 );\r
50\r
51static PyObject *\r
52textiobase_read(PyObject *self, PyObject *args)\r
53{\r
54 return _unsupported("read");\r
55}\r
56\r
57PyDoc_STRVAR(textiobase_readline_doc,\r
58 "Read until newline or EOF.\n"\r
59 "\n"\r
60 "Returns an empty string if EOF is hit immediately.\n"\r
61 );\r
62\r
63static PyObject *\r
64textiobase_readline(PyObject *self, PyObject *args)\r
65{\r
66 return _unsupported("readline");\r
67}\r
68\r
69PyDoc_STRVAR(textiobase_write_doc,\r
70 "Write string to stream.\n"\r
71 "Returns the number of characters written (which is always equal to\n"\r
72 "the length of the string).\n"\r
73 );\r
74\r
75static PyObject *\r
76textiobase_write(PyObject *self, PyObject *args)\r
77{\r
78 return _unsupported("write");\r
79}\r
80\r
81PyDoc_STRVAR(textiobase_encoding_doc,\r
82 "Encoding of the text stream.\n"\r
83 "\n"\r
84 "Subclasses should override.\n"\r
85 );\r
86\r
87static PyObject *\r
88textiobase_encoding_get(PyObject *self, void *context)\r
89{\r
90 Py_RETURN_NONE;\r
91}\r
92\r
93PyDoc_STRVAR(textiobase_newlines_doc,\r
94 "Line endings translated so far.\n"\r
95 "\n"\r
96 "Only line endings translated during reading are considered.\n"\r
97 "\n"\r
98 "Subclasses should override.\n"\r
99 );\r
100\r
101static PyObject *\r
102textiobase_newlines_get(PyObject *self, void *context)\r
103{\r
104 Py_RETURN_NONE;\r
105}\r
106\r
107PyDoc_STRVAR(textiobase_errors_doc,\r
108 "The error setting of the decoder or encoder.\n"\r
109 "\n"\r
110 "Subclasses should override.\n"\r
111 );\r
112\r
113static PyObject *\r
114textiobase_errors_get(PyObject *self, void *context)\r
115{\r
116 Py_RETURN_NONE;\r
117}\r
118\r
119\r
120static PyMethodDef textiobase_methods[] = {\r
121 {"detach", (PyCFunction)textiobase_detach, METH_NOARGS, textiobase_detach_doc},\r
122 {"read", textiobase_read, METH_VARARGS, textiobase_read_doc},\r
123 {"readline", textiobase_readline, METH_VARARGS, textiobase_readline_doc},\r
124 {"write", textiobase_write, METH_VARARGS, textiobase_write_doc},\r
125 {NULL, NULL}\r
126};\r
127\r
128static PyGetSetDef textiobase_getset[] = {\r
129 {"encoding", (getter)textiobase_encoding_get, NULL, textiobase_encoding_doc},\r
130 {"newlines", (getter)textiobase_newlines_get, NULL, textiobase_newlines_doc},\r
131 {"errors", (getter)textiobase_errors_get, NULL, textiobase_errors_doc},\r
132 {NULL}\r
133};\r
134\r
135PyTypeObject PyTextIOBase_Type = {\r
136 PyVarObject_HEAD_INIT(NULL, 0)\r
137 "_io._TextIOBase", /*tp_name*/\r
138 0, /*tp_basicsize*/\r
139 0, /*tp_itemsize*/\r
140 0, /*tp_dealloc*/\r
141 0, /*tp_print*/\r
142 0, /*tp_getattr*/\r
143 0, /*tp_setattr*/\r
144 0, /*tp_compare */\r
145 0, /*tp_repr*/\r
146 0, /*tp_as_number*/\r
147 0, /*tp_as_sequence*/\r
148 0, /*tp_as_mapping*/\r
149 0, /*tp_hash */\r
150 0, /*tp_call*/\r
151 0, /*tp_str*/\r
152 0, /*tp_getattro*/\r
153 0, /*tp_setattro*/\r
154 0, /*tp_as_buffer*/\r
155 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\r
156 textiobase_doc, /* tp_doc */\r
157 0, /* tp_traverse */\r
158 0, /* tp_clear */\r
159 0, /* tp_richcompare */\r
160 0, /* tp_weaklistoffset */\r
161 0, /* tp_iter */\r
162 0, /* tp_iternext */\r
163 textiobase_methods, /* tp_methods */\r
164 0, /* tp_members */\r
165 textiobase_getset, /* tp_getset */\r
166 &PyIOBase_Type, /* tp_base */\r
167 0, /* tp_dict */\r
168 0, /* tp_descr_get */\r
169 0, /* tp_descr_set */\r
170 0, /* tp_dictoffset */\r
171 0, /* tp_init */\r
172 0, /* tp_alloc */\r
173 0, /* tp_new */\r
174};\r
175\r
176\r
177/* IncrementalNewlineDecoder */\r
178\r
179PyDoc_STRVAR(incrementalnewlinedecoder_doc,\r
180 "Codec used when reading a file in universal newlines mode. It wraps\n"\r
181 "another incremental decoder, translating \\r\\n and \\r into \\n. It also\n"\r
182 "records the types of newlines encountered. When used with\n"\r
183 "translate=False, it ensures that the newline sequence is returned in\n"\r
184 "one piece. When used with decoder=None, it expects unicode strings as\n"\r
185 "decode input and translates newlines without first invoking an external\n"\r
186 "decoder.\n"\r
187 );\r
188\r
189typedef struct {\r
190 PyObject_HEAD\r
191 PyObject *decoder;\r
192 PyObject *errors;\r
193 signed int pendingcr: 1;\r
194 signed int translate: 1;\r
195 unsigned int seennl: 3;\r
196} nldecoder_object;\r
197\r
198static int\r
199incrementalnewlinedecoder_init(nldecoder_object *self,\r
200 PyObject *args, PyObject *kwds)\r
201{\r
202 PyObject *decoder;\r
203 int translate;\r
204 PyObject *errors = NULL;\r
205 char *kwlist[] = {"decoder", "translate", "errors", NULL};\r
206\r
207 if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi|O:IncrementalNewlineDecoder",\r
208 kwlist, &decoder, &translate, &errors))\r
209 return -1;\r
210\r
211 self->decoder = decoder;\r
212 Py_INCREF(decoder);\r
213\r
214 if (errors == NULL) {\r
215 self->errors = PyUnicode_FromString("strict");\r
216 if (self->errors == NULL)\r
217 return -1;\r
218 }\r
219 else {\r
220 Py_INCREF(errors);\r
221 self->errors = errors;\r
222 }\r
223\r
224 self->translate = translate;\r
225 self->seennl = 0;\r
226 self->pendingcr = 0;\r
227\r
228 return 0;\r
229}\r
230\r
231static void\r
232incrementalnewlinedecoder_dealloc(nldecoder_object *self)\r
233{\r
234 Py_CLEAR(self->decoder);\r
235 Py_CLEAR(self->errors);\r
236 Py_TYPE(self)->tp_free((PyObject *)self);\r
237}\r
238\r
239static int\r
240check_decoded(PyObject *decoded)\r
241{\r
242 if (decoded == NULL)\r
243 return -1;\r
244 if (!PyUnicode_Check(decoded)) {\r
245 PyErr_Format(PyExc_TypeError,\r
246 "decoder should return a string result, not '%.200s'",\r
247 Py_TYPE(decoded)->tp_name);\r
248 Py_DECREF(decoded);\r
249 return -1;\r
250 }\r
251 return 0;\r
252}\r
253\r
254#define SEEN_CR 1\r
255#define SEEN_LF 2\r
256#define SEEN_CRLF 4\r
257#define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF)\r
258\r
259PyObject *\r
260_PyIncrementalNewlineDecoder_decode(PyObject *_self,\r
261 PyObject *input, int final)\r
262{\r
263 PyObject *output;\r
264 Py_ssize_t output_len;\r
265 nldecoder_object *self = (nldecoder_object *) _self;\r
266\r
267 if (self->decoder == NULL) {\r
268 PyErr_SetString(PyExc_ValueError,\r
269 "IncrementalNewlineDecoder.__init__ not called");\r
270 return NULL;\r
271 }\r
272\r
273 /* decode input (with the eventual \r from a previous pass) */\r
274 if (self->decoder != Py_None) {\r
275 output = PyObject_CallMethodObjArgs(self->decoder,\r
276 _PyIO_str_decode, input, final ? Py_True : Py_False, NULL);\r
277 }\r
278 else {\r
279 output = input;\r
280 Py_INCREF(output);\r
281 }\r
282\r
283 if (check_decoded(output) < 0)\r
284 return NULL;\r
285\r
286 output_len = PyUnicode_GET_SIZE(output);\r
287 if (self->pendingcr && (final || output_len > 0)) {\r
288 Py_UNICODE *out;\r
289 PyObject *modified = PyUnicode_FromUnicode(NULL, output_len + 1);\r
290 if (modified == NULL)\r
291 goto error;\r
292 out = PyUnicode_AS_UNICODE(modified);\r
293 out[0] = '\r';\r
294 memcpy(out + 1, PyUnicode_AS_UNICODE(output),\r
295 output_len * sizeof(Py_UNICODE));\r
296 Py_DECREF(output);\r
297 output = modified;\r
298 self->pendingcr = 0;\r
299 output_len++;\r
300 }\r
301\r
302 /* retain last \r even when not translating data:\r
303 * then readline() is sure to get \r\n in one pass\r
304 */\r
305 if (!final) {\r
306 if (output_len > 0\r
307 && PyUnicode_AS_UNICODE(output)[output_len - 1] == '\r') {\r
308\r
309 if (Py_REFCNT(output) == 1) {\r
310 if (PyUnicode_Resize(&output, output_len - 1) < 0)\r
311 goto error;\r
312 }\r
313 else {\r
314 PyObject *modified = PyUnicode_FromUnicode(\r
315 PyUnicode_AS_UNICODE(output),\r
316 output_len - 1);\r
317 if (modified == NULL)\r
318 goto error;\r
319 Py_DECREF(output);\r
320 output = modified;\r
321 }\r
322 self->pendingcr = 1;\r
323 }\r
324 }\r
325\r
326 /* Record which newlines are read and do newline translation if desired,\r
327 all in one pass. */\r
328 {\r
329 Py_UNICODE *in_str;\r
330 Py_ssize_t len;\r
331 int seennl = self->seennl;\r
332 int only_lf = 0;\r
333\r
334 in_str = PyUnicode_AS_UNICODE(output);\r
335 len = PyUnicode_GET_SIZE(output);\r
336\r
337 if (len == 0)\r
338 return output;\r
339\r
340 /* If, up to now, newlines are consistently \n, do a quick check\r
341 for the \r *byte* with the libc's optimized memchr.\r
342 */\r
343 if (seennl == SEEN_LF || seennl == 0) {\r
344 only_lf = (memchr(in_str, '\r', len * sizeof(Py_UNICODE)) == NULL);\r
345 }\r
346\r
347 if (only_lf) {\r
348 /* If not already seen, quick scan for a possible "\n" character.\r
349 (there's nothing else to be done, even when in translation mode)\r
350 */\r
351 if (seennl == 0 &&\r
352 memchr(in_str, '\n', len * sizeof(Py_UNICODE)) != NULL) {\r
353 Py_UNICODE *s, *end;\r
354 s = in_str;\r
355 end = in_str + len;\r
356 for (;;) {\r
357 Py_UNICODE c;\r
358 /* Fast loop for non-control characters */\r
359 while (*s > '\n')\r
360 s++;\r
361 c = *s++;\r
362 if (c == '\n') {\r
363 seennl |= SEEN_LF;\r
364 break;\r
365 }\r
366 if (s > end)\r
367 break;\r
368 }\r
369 }\r
370 /* Finished: we have scanned for newlines, and none of them\r
371 need translating */\r
372 }\r
373 else if (!self->translate) {\r
374 Py_UNICODE *s, *end;\r
375 /* We have already seen all newline types, no need to scan again */\r
376 if (seennl == SEEN_ALL)\r
377 goto endscan;\r
378 s = in_str;\r
379 end = in_str + len;\r
380 for (;;) {\r
381 Py_UNICODE c;\r
382 /* Fast loop for non-control characters */\r
383 while (*s > '\r')\r
384 s++;\r
385 c = *s++;\r
386 if (c == '\n')\r
387 seennl |= SEEN_LF;\r
388 else if (c == '\r') {\r
389 if (*s == '\n') {\r
390 seennl |= SEEN_CRLF;\r
391 s++;\r
392 }\r
393 else\r
394 seennl |= SEEN_CR;\r
395 }\r
396 if (s > end)\r
397 break;\r
398 if (seennl == SEEN_ALL)\r
399 break;\r
400 }\r
401 endscan:\r
402 ;\r
403 }\r
404 else {\r
405 PyObject *translated = NULL;\r
406 Py_UNICODE *out_str;\r
407 Py_UNICODE *in, *out, *end;\r
408 if (Py_REFCNT(output) != 1) {\r
409 /* We could try to optimize this so that we only do a copy\r
410 when there is something to translate. On the other hand,\r
411 most decoders should only output non-shared strings, i.e.\r
412 translation is done in place. */\r
413 translated = PyUnicode_FromUnicode(NULL, len);\r
414 if (translated == NULL)\r
415 goto error;\r
416 assert(Py_REFCNT(translated) == 1);\r
417 memcpy(PyUnicode_AS_UNICODE(translated),\r
418 PyUnicode_AS_UNICODE(output),\r
419 len * sizeof(Py_UNICODE));\r
420 }\r
421 else {\r
422 translated = output;\r
423 }\r
424 out_str = PyUnicode_AS_UNICODE(translated);\r
425 in = in_str;\r
426 out = out_str;\r
427 end = in_str + len;\r
428 for (;;) {\r
429 Py_UNICODE c;\r
430 /* Fast loop for non-control characters */\r
431 while ((c = *in++) > '\r')\r
432 *out++ = c;\r
433 if (c == '\n') {\r
434 *out++ = c;\r
435 seennl |= SEEN_LF;\r
436 continue;\r
437 }\r
438 if (c == '\r') {\r
439 if (*in == '\n') {\r
440 in++;\r
441 seennl |= SEEN_CRLF;\r
442 }\r
443 else\r
444 seennl |= SEEN_CR;\r
445 *out++ = '\n';\r
446 continue;\r
447 }\r
448 if (in > end)\r
449 break;\r
450 *out++ = c;\r
451 }\r
452 if (translated != output) {\r
453 Py_DECREF(output);\r
454 output = translated;\r
455 }\r
456 if (out - out_str != len) {\r
457 if (PyUnicode_Resize(&output, out - out_str) < 0)\r
458 goto error;\r
459 }\r
460 }\r
461 self->seennl |= seennl;\r
462 }\r
463\r
464 return output;\r
465\r
466 error:\r
467 Py_DECREF(output);\r
468 return NULL;\r
469}\r
470\r
471static PyObject *\r
472incrementalnewlinedecoder_decode(nldecoder_object *self,\r
473 PyObject *args, PyObject *kwds)\r
474{\r
475 char *kwlist[] = {"input", "final", NULL};\r
476 PyObject *input;\r
477 int final = 0;\r
478\r
479 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder",\r
480 kwlist, &input, &final))\r
481 return NULL;\r
482 return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final);\r
483}\r
484\r
485static PyObject *\r
486incrementalnewlinedecoder_getstate(nldecoder_object *self, PyObject *args)\r
487{\r
488 PyObject *buffer;\r
489 unsigned PY_LONG_LONG flag;\r
490\r
491 if (self->decoder != Py_None) {\r
492 PyObject *state = PyObject_CallMethodObjArgs(self->decoder,\r
493 _PyIO_str_getstate, NULL);\r
494 if (state == NULL)\r
495 return NULL;\r
496 if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) {\r
497 Py_DECREF(state);\r
498 return NULL;\r
499 }\r
500 Py_INCREF(buffer);\r
501 Py_DECREF(state);\r
502 }\r
503 else {\r
504 buffer = PyBytes_FromString("");\r
505 flag = 0;\r
506 }\r
507 flag <<= 1;\r
508 if (self->pendingcr)\r
509 flag |= 1;\r
510 return Py_BuildValue("NK", buffer, flag);\r
511}\r
512\r
513static PyObject *\r
514incrementalnewlinedecoder_setstate(nldecoder_object *self, PyObject *state)\r
515{\r
516 PyObject *buffer;\r
517 unsigned PY_LONG_LONG flag;\r
518\r
519 if (!PyArg_Parse(state, "(OK)", &buffer, &flag))\r
520 return NULL;\r
521\r
522 self->pendingcr = (int) flag & 1;\r
523 flag >>= 1;\r
524\r
525 if (self->decoder != Py_None)\r
526 return PyObject_CallMethod(self->decoder,\r
527 "setstate", "((OK))", buffer, flag);\r
528 else\r
529 Py_RETURN_NONE;\r
530}\r
531\r
532static PyObject *\r
533incrementalnewlinedecoder_reset(nldecoder_object *self, PyObject *args)\r
534{\r
535 self->seennl = 0;\r
536 self->pendingcr = 0;\r
537 if (self->decoder != Py_None)\r
538 return PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL);\r
539 else\r
540 Py_RETURN_NONE;\r
541}\r
542\r
543static PyObject *\r
544incrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context)\r
545{\r
546 switch (self->seennl) {\r
547 case SEEN_CR:\r
548 return PyUnicode_FromString("\r");\r
549 case SEEN_LF:\r
550 return PyUnicode_FromString("\n");\r
551 case SEEN_CRLF:\r
552 return PyUnicode_FromString("\r\n");\r
553 case SEEN_CR | SEEN_LF:\r
554 return Py_BuildValue("ss", "\r", "\n");\r
555 case SEEN_CR | SEEN_CRLF:\r
556 return Py_BuildValue("ss", "\r", "\r\n");\r
557 case SEEN_LF | SEEN_CRLF:\r
558 return Py_BuildValue("ss", "\n", "\r\n");\r
559 case SEEN_CR | SEEN_LF | SEEN_CRLF:\r
560 return Py_BuildValue("sss", "\r", "\n", "\r\n");\r
561 default:\r
562 Py_RETURN_NONE;\r
563 }\r
564\r
565}\r
566\r
567\r
568static PyMethodDef incrementalnewlinedecoder_methods[] = {\r
569 {"decode", (PyCFunction)incrementalnewlinedecoder_decode, METH_VARARGS|METH_KEYWORDS},\r
570 {"getstate", (PyCFunction)incrementalnewlinedecoder_getstate, METH_NOARGS},\r
571 {"setstate", (PyCFunction)incrementalnewlinedecoder_setstate, METH_O},\r
572 {"reset", (PyCFunction)incrementalnewlinedecoder_reset, METH_NOARGS},\r
573 {NULL}\r
574};\r
575\r
576static PyGetSetDef incrementalnewlinedecoder_getset[] = {\r
577 {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL},\r
578 {NULL}\r
579};\r
580\r
581PyTypeObject PyIncrementalNewlineDecoder_Type = {\r
582 PyVarObject_HEAD_INIT(NULL, 0)\r
583 "_io.IncrementalNewlineDecoder", /*tp_name*/\r
584 sizeof(nldecoder_object), /*tp_basicsize*/\r
585 0, /*tp_itemsize*/\r
586 (destructor)incrementalnewlinedecoder_dealloc, /*tp_dealloc*/\r
587 0, /*tp_print*/\r
588 0, /*tp_getattr*/\r
589 0, /*tp_setattr*/\r
590 0, /*tp_compare */\r
591 0, /*tp_repr*/\r
592 0, /*tp_as_number*/\r
593 0, /*tp_as_sequence*/\r
594 0, /*tp_as_mapping*/\r
595 0, /*tp_hash */\r
596 0, /*tp_call*/\r
597 0, /*tp_str*/\r
598 0, /*tp_getattro*/\r
599 0, /*tp_setattro*/\r
600 0, /*tp_as_buffer*/\r
601 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\r
602 incrementalnewlinedecoder_doc, /* tp_doc */\r
603 0, /* tp_traverse */\r
604 0, /* tp_clear */\r
605 0, /* tp_richcompare */\r
606 0, /*tp_weaklistoffset*/\r
607 0, /* tp_iter */\r
608 0, /* tp_iternext */\r
609 incrementalnewlinedecoder_methods, /* tp_methods */\r
610 0, /* tp_members */\r
611 incrementalnewlinedecoder_getset, /* tp_getset */\r
612 0, /* tp_base */\r
613 0, /* tp_dict */\r
614 0, /* tp_descr_get */\r
615 0, /* tp_descr_set */\r
616 0, /* tp_dictoffset */\r
617 (initproc)incrementalnewlinedecoder_init, /* tp_init */\r
618 0, /* tp_alloc */\r
619 PyType_GenericNew, /* tp_new */\r
620};\r
621\r
622\r
623/* TextIOWrapper */\r
624\r
625PyDoc_STRVAR(textiowrapper_doc,\r
626 "Character and line based layer over a BufferedIOBase object, buffer.\n"\r
627 "\n"\r
628 "encoding gives the name of the encoding that the stream will be\n"\r
629 "decoded or encoded with. It defaults to locale.getpreferredencoding.\n"\r
630 "\n"\r
631 "errors determines the strictness of encoding and decoding (see the\n"\r
632 "codecs.register) and defaults to \"strict\".\n"\r
633 "\n"\r
634 "newline controls how line endings are handled. It can be None, '',\n"\r
635 "'\\n', '\\r', and '\\r\\n'. It works as follows:\n"\r
636 "\n"\r
637 "* On input, if newline is None, universal newlines mode is\n"\r
638 " enabled. Lines in the input can end in '\\n', '\\r', or '\\r\\n', and\n"\r
639 " these are translated into '\\n' before being returned to the\n"\r
640 " caller. If it is '', universal newline mode is enabled, but line\n"\r
641 " endings are returned to the caller untranslated. If it has any of\n"\r
642 " the other legal values, input lines are only terminated by the given\n"\r
643 " string, and the line ending is returned to the caller untranslated.\n"\r
644 "\n"\r
645 "* On output, if newline is None, any '\\n' characters written are\n"\r
646 " translated to the system default line separator, os.linesep. If\n"\r
647 " newline is '', no translation takes place. If newline is any of the\n"\r
648 " other legal values, any '\\n' characters written are translated to\n"\r
649 " the given string.\n"\r
650 "\n"\r
651 "If line_buffering is True, a call to flush is implied when a call to\n"\r
652 "write contains a newline character."\r
653 );\r
654\r
655typedef PyObject *\r
656 (*encodefunc_t)(PyObject *, PyObject *);\r
657\r
658typedef struct\r
659{\r
660 PyObject_HEAD\r
661 int ok; /* initialized? */\r
662 int detached;\r
663 Py_ssize_t chunk_size;\r
664 PyObject *buffer;\r
665 PyObject *encoding;\r
666 PyObject *encoder;\r
667 PyObject *decoder;\r
668 PyObject *readnl;\r
669 PyObject *errors;\r
670 const char *writenl; /* utf-8 encoded, NULL stands for \n */\r
671 char line_buffering;\r
672 char readuniversal;\r
673 char readtranslate;\r
674 char writetranslate;\r
675 char seekable;\r
676 char telling;\r
677 /* Specialized encoding func (see below) */\r
678 encodefunc_t encodefunc;\r
679 /* Whether or not it's the start of the stream */\r
680 char encoding_start_of_stream;\r
681\r
682 /* Reads and writes are internally buffered in order to speed things up.\r
683 However, any read will first flush the write buffer if itsn't empty.\r
684\r
685 Please also note that text to be written is first encoded before being\r
686 buffered. This is necessary so that encoding errors are immediately\r
687 reported to the caller, but it unfortunately means that the\r
688 IncrementalEncoder (whose encode() method is always written in Python)\r
689 becomes a bottleneck for small writes.\r
690 */\r
691 PyObject *decoded_chars; /* buffer for text returned from decoder */\r
692 Py_ssize_t decoded_chars_used; /* offset into _decoded_chars for read() */\r
693 PyObject *pending_bytes; /* list of bytes objects waiting to be\r
694 written, or NULL */\r
695 Py_ssize_t pending_bytes_count;\r
696 PyObject *snapshot;\r
697 /* snapshot is either None, or a tuple (dec_flags, next_input) where\r
698 * dec_flags is the second (integer) item of the decoder state and\r
699 * next_input is the chunk of input bytes that comes next after the\r
700 * snapshot point. We use this to reconstruct decoder states in tell().\r
701 */\r
702\r
703 /* Cache raw object if it's a FileIO object */\r
704 PyObject *raw;\r
705\r
706 PyObject *weakreflist;\r
707 PyObject *dict;\r
708} textio;\r
709\r
710\r
711/* A couple of specialized cases in order to bypass the slow incremental\r
712 encoding methods for the most popular encodings. */\r
713\r
714static PyObject *\r
715ascii_encode(textio *self, PyObject *text)\r
716{\r
717 return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(text),\r
718 PyUnicode_GET_SIZE(text),\r
719 PyBytes_AS_STRING(self->errors));\r
720}\r
721\r
722static PyObject *\r
723utf16be_encode(textio *self, PyObject *text)\r
724{\r
725 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),\r
726 PyUnicode_GET_SIZE(text),\r
727 PyBytes_AS_STRING(self->errors), 1);\r
728}\r
729\r
730static PyObject *\r
731utf16le_encode(textio *self, PyObject *text)\r
732{\r
733 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),\r
734 PyUnicode_GET_SIZE(text),\r
735 PyBytes_AS_STRING(self->errors), -1);\r
736}\r
737\r
738static PyObject *\r
739utf16_encode(textio *self, PyObject *text)\r
740{\r
741 if (!self->encoding_start_of_stream) {\r
742 /* Skip the BOM and use native byte ordering */\r
743#if defined(WORDS_BIGENDIAN)\r
744 return utf16be_encode(self, text);\r
745#else\r
746 return utf16le_encode(self, text);\r
747#endif\r
748 }\r
749 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),\r
750 PyUnicode_GET_SIZE(text),\r
751 PyBytes_AS_STRING(self->errors), 0);\r
752}\r
753\r
754static PyObject *\r
755utf32be_encode(textio *self, PyObject *text)\r
756{\r
757 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),\r
758 PyUnicode_GET_SIZE(text),\r
759 PyBytes_AS_STRING(self->errors), 1);\r
760}\r
761\r
762static PyObject *\r
763utf32le_encode(textio *self, PyObject *text)\r
764{\r
765 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),\r
766 PyUnicode_GET_SIZE(text),\r
767 PyBytes_AS_STRING(self->errors), -1);\r
768}\r
769\r
770static PyObject *\r
771utf32_encode(textio *self, PyObject *text)\r
772{\r
773 if (!self->encoding_start_of_stream) {\r
774 /* Skip the BOM and use native byte ordering */\r
775#if defined(WORDS_BIGENDIAN)\r
776 return utf32be_encode(self, text);\r
777#else\r
778 return utf32le_encode(self, text);\r
779#endif\r
780 }\r
781 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),\r
782 PyUnicode_GET_SIZE(text),\r
783 PyBytes_AS_STRING(self->errors), 0);\r
784}\r
785\r
786static PyObject *\r
787utf8_encode(textio *self, PyObject *text)\r
788{\r
789 return PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(text),\r
790 PyUnicode_GET_SIZE(text),\r
791 PyBytes_AS_STRING(self->errors));\r
792}\r
793\r
794static PyObject *\r
795latin1_encode(textio *self, PyObject *text)\r
796{\r
797 return PyUnicode_EncodeLatin1(PyUnicode_AS_UNICODE(text),\r
798 PyUnicode_GET_SIZE(text),\r
799 PyBytes_AS_STRING(self->errors));\r
800}\r
801\r
802/* Map normalized encoding names onto the specialized encoding funcs */\r
803\r
804typedef struct {\r
805 const char *name;\r
806 encodefunc_t encodefunc;\r
807} encodefuncentry;\r
808\r
809static encodefuncentry encodefuncs[] = {\r
810 {"ascii", (encodefunc_t) ascii_encode},\r
811 {"iso8859-1", (encodefunc_t) latin1_encode},\r
812 {"utf-8", (encodefunc_t) utf8_encode},\r
813 {"utf-16-be", (encodefunc_t) utf16be_encode},\r
814 {"utf-16-le", (encodefunc_t) utf16le_encode},\r
815 {"utf-16", (encodefunc_t) utf16_encode},\r
816 {"utf-32-be", (encodefunc_t) utf32be_encode},\r
817 {"utf-32-le", (encodefunc_t) utf32le_encode},\r
818 {"utf-32", (encodefunc_t) utf32_encode},\r
819 {NULL, NULL}\r
820};\r
821\r
822\r
823static int\r
824textiowrapper_init(textio *self, PyObject *args, PyObject *kwds)\r
825{\r
826 char *kwlist[] = {"buffer", "encoding", "errors",\r
827 "newline", "line_buffering",\r
828 NULL};\r
829 PyObject *buffer, *raw;\r
830 char *encoding = NULL;\r
831 char *errors = NULL;\r
832 char *newline = NULL;\r
833 int line_buffering = 0;\r
834\r
835 PyObject *res;\r
836 int r;\r
837\r
838 self->ok = 0;\r
839 self->detached = 0;\r
840 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzi:fileio",\r
841 kwlist, &buffer, &encoding, &errors,\r
842 &newline, &line_buffering))\r
843 return -1;\r
844\r
845 if (newline && newline[0] != '\0'\r
846 && !(newline[0] == '\n' && newline[1] == '\0')\r
847 && !(newline[0] == '\r' && newline[1] == '\0')\r
848 && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {\r
849 PyErr_Format(PyExc_ValueError,\r
850 "illegal newline value: %s", newline);\r
851 return -1;\r
852 }\r
853\r
854 Py_CLEAR(self->buffer);\r
855 Py_CLEAR(self->encoding);\r
856 Py_CLEAR(self->encoder);\r
857 Py_CLEAR(self->decoder);\r
858 Py_CLEAR(self->readnl);\r
859 Py_CLEAR(self->decoded_chars);\r
860 Py_CLEAR(self->pending_bytes);\r
861 Py_CLEAR(self->snapshot);\r
862 Py_CLEAR(self->errors);\r
863 Py_CLEAR(self->raw);\r
864 self->decoded_chars_used = 0;\r
865 self->pending_bytes_count = 0;\r
866 self->encodefunc = NULL;\r
867 self->writenl = NULL;\r
868\r
869 if (encoding == NULL && self->encoding == NULL) {\r
870 if (_PyIO_locale_module == NULL) {\r
871 _PyIO_locale_module = PyImport_ImportModule("locale");\r
872 if (_PyIO_locale_module == NULL)\r
873 goto catch_ImportError;\r
874 else\r
875 goto use_locale;\r
876 }\r
877 else {\r
878 use_locale:\r
879 self->encoding = PyObject_CallMethod(\r
880 _PyIO_locale_module, "getpreferredencoding", NULL);\r
881 if (self->encoding == NULL) {\r
882 catch_ImportError:\r
883 /*\r
884 Importing locale can raise a ImportError because of\r
885 _functools, and locale.getpreferredencoding can raise a\r
886 ImportError if _locale is not available. These will happen\r
887 during module building.\r
888 */\r
889 if (PyErr_ExceptionMatches(PyExc_ImportError)) {\r
890 PyErr_Clear();\r
891 self->encoding = PyString_FromString("ascii");\r
892 }\r
893 else\r
894 goto error;\r
895 }\r
896 else if (!PyString_Check(self->encoding))\r
897 Py_CLEAR(self->encoding);\r
898 }\r
899 }\r
900 if (self->encoding != NULL)\r
901 encoding = PyString_AsString(self->encoding);\r
902 else if (encoding != NULL) {\r
903 self->encoding = PyString_FromString(encoding);\r
904 if (self->encoding == NULL)\r
905 goto error;\r
906 }\r
907 else {\r
908 PyErr_SetString(PyExc_IOError,\r
909 "could not determine default encoding");\r
910 }\r
911\r
912 if (errors == NULL)\r
913 errors = "strict";\r
914 self->errors = PyBytes_FromString(errors);\r
915 if (self->errors == NULL)\r
916 goto error;\r
917\r
918 self->chunk_size = 8192;\r
919 self->readuniversal = (newline == NULL || newline[0] == '\0');\r
920 self->line_buffering = line_buffering;\r
921 self->readtranslate = (newline == NULL);\r
922 if (newline) {\r
923 self->readnl = PyString_FromString(newline);\r
924 if (self->readnl == NULL)\r
925 return -1;\r
926 }\r
927 self->writetranslate = (newline == NULL || newline[0] != '\0');\r
928 if (!self->readuniversal && self->writetranslate) {\r
929 self->writenl = PyString_AsString(self->readnl);\r
930 if (!strcmp(self->writenl, "\n"))\r
931 self->writenl = NULL;\r
932 }\r
933#ifdef MS_WINDOWS\r
934 else\r
935 self->writenl = "\r\n";\r
936#endif\r
937\r
938 /* Build the decoder object */\r
939 res = PyObject_CallMethod(buffer, "readable", NULL);\r
940 if (res == NULL)\r
941 goto error;\r
942 r = PyObject_IsTrue(res);\r
943 Py_DECREF(res);\r
944 if (r == -1)\r
945 goto error;\r
946 if (r == 1) {\r
947 self->decoder = PyCodec_IncrementalDecoder(\r
948 encoding, errors);\r
949 if (self->decoder == NULL)\r
950 goto error;\r
951\r
952 if (self->readuniversal) {\r
953 PyObject *incrementalDecoder = PyObject_CallFunction(\r
954 (PyObject *)&PyIncrementalNewlineDecoder_Type,\r
955 "Oi", self->decoder, (int)self->readtranslate);\r
956 if (incrementalDecoder == NULL)\r
957 goto error;\r
958 Py_CLEAR(self->decoder);\r
959 self->decoder = incrementalDecoder;\r
960 }\r
961 }\r
962\r
963 /* Build the encoder object */\r
964 res = PyObject_CallMethod(buffer, "writable", NULL);\r
965 if (res == NULL)\r
966 goto error;\r
967 r = PyObject_IsTrue(res);\r
968 Py_DECREF(res);\r
969 if (r == -1)\r
970 goto error;\r
971 if (r == 1) {\r
972 PyObject *ci;\r
973 self->encoder = PyCodec_IncrementalEncoder(\r
974 encoding, errors);\r
975 if (self->encoder == NULL)\r
976 goto error;\r
977 /* Get the normalized named of the codec */\r
978 ci = _PyCodec_Lookup(encoding);\r
979 if (ci == NULL)\r
980 goto error;\r
981 res = PyObject_GetAttrString(ci, "name");\r
982 Py_DECREF(ci);\r
983 if (res == NULL) {\r
984 if (PyErr_ExceptionMatches(PyExc_AttributeError))\r
985 PyErr_Clear();\r
986 else\r
987 goto error;\r
988 }\r
989 else if (PyString_Check(res)) {\r
990 encodefuncentry *e = encodefuncs;\r
991 while (e->name != NULL) {\r
992 if (!strcmp(PyString_AS_STRING(res), e->name)) {\r
993 self->encodefunc = e->encodefunc;\r
994 break;\r
995 }\r
996 e++;\r
997 }\r
998 }\r
999 Py_XDECREF(res);\r
1000 }\r
1001\r
1002 self->buffer = buffer;\r
1003 Py_INCREF(buffer);\r
1004\r
1005 if (Py_TYPE(buffer) == &PyBufferedReader_Type ||\r
1006 Py_TYPE(buffer) == &PyBufferedWriter_Type ||\r
1007 Py_TYPE(buffer) == &PyBufferedRandom_Type) {\r
1008 raw = PyObject_GetAttrString(buffer, "raw");\r
1009 /* Cache the raw FileIO object to speed up 'closed' checks */\r
1010 if (raw == NULL) {\r
1011 if (PyErr_ExceptionMatches(PyExc_AttributeError))\r
1012 PyErr_Clear();\r
1013 else\r
1014 goto error;\r
1015 }\r
1016 else if (Py_TYPE(raw) == &PyFileIO_Type)\r
1017 self->raw = raw;\r
1018 else\r
1019 Py_DECREF(raw);\r
1020 }\r
1021\r
1022 res = PyObject_CallMethod(buffer, "seekable", NULL);\r
1023 if (res == NULL)\r
1024 goto error;\r
1025 r = PyObject_IsTrue(res);\r
1026 Py_DECREF(res);\r
1027 if (r < 0)\r
1028 goto error;\r
1029 self->seekable = self->telling = r;\r
1030\r
1031 self->encoding_start_of_stream = 0;\r
1032 if (self->seekable && self->encoder) {\r
1033 PyObject *cookieObj;\r
1034 int cmp;\r
1035\r
1036 self->encoding_start_of_stream = 1;\r
1037\r
1038 cookieObj = PyObject_CallMethodObjArgs(buffer, _PyIO_str_tell, NULL);\r
1039 if (cookieObj == NULL)\r
1040 goto error;\r
1041\r
1042 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);\r
1043 Py_DECREF(cookieObj);\r
1044 if (cmp < 0) {\r
1045 goto error;\r
1046 }\r
1047\r
1048 if (cmp == 0) {\r
1049 self->encoding_start_of_stream = 0;\r
1050 res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,\r
1051 _PyIO_zero, NULL);\r
1052 if (res == NULL)\r
1053 goto error;\r
1054 Py_DECREF(res);\r
1055 }\r
1056 }\r
1057\r
1058 self->ok = 1;\r
1059 return 0;\r
1060\r
1061 error:\r
1062 return -1;\r
1063}\r
1064\r
1065static int\r
1066_textiowrapper_clear(textio *self)\r
1067{\r
1068 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)\r
1069 return -1;\r
1070 self->ok = 0;\r
1071 Py_CLEAR(self->buffer);\r
1072 Py_CLEAR(self->encoding);\r
1073 Py_CLEAR(self->encoder);\r
1074 Py_CLEAR(self->decoder);\r
1075 Py_CLEAR(self->readnl);\r
1076 Py_CLEAR(self->decoded_chars);\r
1077 Py_CLEAR(self->pending_bytes);\r
1078 Py_CLEAR(self->snapshot);\r
1079 Py_CLEAR(self->errors);\r
1080 Py_CLEAR(self->raw);\r
1081 return 0;\r
1082}\r
1083\r
1084static void\r
1085textiowrapper_dealloc(textio *self)\r
1086{\r
1087 if (_textiowrapper_clear(self) < 0)\r
1088 return;\r
1089 _PyObject_GC_UNTRACK(self);\r
1090 if (self->weakreflist != NULL)\r
1091 PyObject_ClearWeakRefs((PyObject *)self);\r
1092 Py_CLEAR(self->dict);\r
1093 Py_TYPE(self)->tp_free((PyObject *)self);\r
1094}\r
1095\r
1096static int\r
1097textiowrapper_traverse(textio *self, visitproc visit, void *arg)\r
1098{\r
1099 Py_VISIT(self->buffer);\r
1100 Py_VISIT(self->encoding);\r
1101 Py_VISIT(self->encoder);\r
1102 Py_VISIT(self->decoder);\r
1103 Py_VISIT(self->readnl);\r
1104 Py_VISIT(self->decoded_chars);\r
1105 Py_VISIT(self->pending_bytes);\r
1106 Py_VISIT(self->snapshot);\r
1107 Py_VISIT(self->errors);\r
1108 Py_VISIT(self->raw);\r
1109\r
1110 Py_VISIT(self->dict);\r
1111 return 0;\r
1112}\r
1113\r
1114static int\r
1115textiowrapper_clear(textio *self)\r
1116{\r
1117 if (_textiowrapper_clear(self) < 0)\r
1118 return -1;\r
1119 Py_CLEAR(self->dict);\r
1120 return 0;\r
1121}\r
1122\r
1123static PyObject *\r
1124textiowrapper_closed_get(textio *self, void *context);\r
1125\r
1126/* This macro takes some shortcuts to make the common case faster. */\r
1127#define CHECK_CLOSED(self) \\r
1128 do { \\r
1129 int r; \\r
1130 PyObject *_res; \\r
1131 if (Py_TYPE(self) == &PyTextIOWrapper_Type) { \\r
1132 if (self->raw != NULL) \\r
1133 r = _PyFileIO_closed(self->raw); \\r
1134 else { \\r
1135 _res = textiowrapper_closed_get(self, NULL); \\r
1136 if (_res == NULL) \\r
1137 return NULL; \\r
1138 r = PyObject_IsTrue(_res); \\r
1139 Py_DECREF(_res); \\r
1140 if (r < 0) \\r
1141 return NULL; \\r
1142 } \\r
1143 if (r > 0) { \\r
1144 PyErr_SetString(PyExc_ValueError, \\r
1145 "I/O operation on closed file."); \\r
1146 return NULL; \\r
1147 } \\r
1148 } \\r
1149 else if (_PyIOBase_check_closed((PyObject *)self, Py_True) == NULL) \\r
1150 return NULL; \\r
1151 } while (0)\r
1152\r
1153#define CHECK_INITIALIZED(self) \\r
1154 if (self->ok <= 0) { \\r
1155 PyErr_SetString(PyExc_ValueError, \\r
1156 "I/O operation on uninitialized object"); \\r
1157 return NULL; \\r
1158 }\r
1159\r
1160#define CHECK_ATTACHED(self) \\r
1161 CHECK_INITIALIZED(self); \\r
1162 if (self->detached) { \\r
1163 PyErr_SetString(PyExc_ValueError, \\r
1164 "underlying buffer has been detached"); \\r
1165 return NULL; \\r
1166 }\r
1167\r
1168#define CHECK_ATTACHED_INT(self) \\r
1169 if (self->ok <= 0) { \\r
1170 PyErr_SetString(PyExc_ValueError, \\r
1171 "I/O operation on uninitialized object"); \\r
1172 return -1; \\r
1173 } else if (self->detached) { \\r
1174 PyErr_SetString(PyExc_ValueError, \\r
1175 "underlying buffer has been detached"); \\r
1176 return -1; \\r
1177 }\r
1178\r
1179\r
1180static PyObject *\r
1181textiowrapper_detach(textio *self)\r
1182{\r
1183 PyObject *buffer, *res;\r
1184 CHECK_ATTACHED(self);\r
1185 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);\r
1186 if (res == NULL)\r
1187 return NULL;\r
1188 Py_DECREF(res);\r
1189 buffer = self->buffer;\r
1190 self->buffer = NULL;\r
1191 self->detached = 1;\r
1192 return buffer;\r
1193}\r
1194\r
1195Py_LOCAL_INLINE(const Py_UNICODE *)\r
1196findchar(const Py_UNICODE *s, Py_ssize_t size, Py_UNICODE ch)\r
1197{\r
1198 /* like wcschr, but doesn't stop at NULL characters */\r
1199 while (size-- > 0) {\r
1200 if (*s == ch)\r
1201 return s;\r
1202 s++;\r
1203 }\r
1204 return NULL;\r
1205}\r
1206\r
1207/* Flush the internal write buffer. This doesn't explicitly flush the\r
1208 underlying buffered object, though. */\r
1209static int\r
1210_textiowrapper_writeflush(textio *self)\r
1211{\r
1212 PyObject *pending, *b, *ret;\r
1213\r
1214 if (self->pending_bytes == NULL)\r
1215 return 0;\r
1216\r
1217 pending = self->pending_bytes;\r
1218 Py_INCREF(pending);\r
1219 self->pending_bytes_count = 0;\r
1220 Py_CLEAR(self->pending_bytes);\r
1221\r
1222 b = _PyBytes_Join(_PyIO_empty_bytes, pending);\r
1223 Py_DECREF(pending);\r
1224 if (b == NULL)\r
1225 return -1;\r
1226 ret = NULL;\r
1227 do {\r
1228 ret = PyObject_CallMethodObjArgs(self->buffer,\r
1229 _PyIO_str_write, b, NULL);\r
1230 } while (ret == NULL && _PyIO_trap_eintr());\r
1231 Py_DECREF(b);\r
1232 if (ret == NULL)\r
1233 return -1;\r
1234 Py_DECREF(ret);\r
1235 return 0;\r
1236}\r
1237\r
1238static PyObject *\r
1239textiowrapper_write(textio *self, PyObject *args)\r
1240{\r
1241 PyObject *ret;\r
1242 PyObject *text; /* owned reference */\r
1243 PyObject *b;\r
1244 Py_ssize_t textlen;\r
1245 int haslf = 0;\r
1246 int needflush = 0;\r
1247\r
1248 CHECK_ATTACHED(self);\r
1249\r
1250 if (!PyArg_ParseTuple(args, "U:write", &text)) {\r
1251 return NULL;\r
1252 }\r
1253\r
1254 CHECK_CLOSED(self);\r
1255\r
1256 if (self->encoder == NULL) {\r
1257 PyErr_SetString(PyExc_IOError, "not writable");\r
1258 return NULL;\r
1259 }\r
1260\r
1261 Py_INCREF(text);\r
1262\r
1263 textlen = PyUnicode_GetSize(text);\r
1264\r
1265 if ((self->writetranslate && self->writenl != NULL) || self->line_buffering)\r
1266 if (findchar(PyUnicode_AS_UNICODE(text),\r
1267 PyUnicode_GET_SIZE(text), '\n'))\r
1268 haslf = 1;\r
1269\r
1270 if (haslf && self->writetranslate && self->writenl != NULL) {\r
1271 PyObject *newtext = PyObject_CallMethod(\r
1272 text, "replace", "ss", "\n", self->writenl);\r
1273 Py_DECREF(text);\r
1274 if (newtext == NULL)\r
1275 return NULL;\r
1276 text = newtext;\r
1277 }\r
1278\r
1279 if (self->line_buffering &&\r
1280 (haslf ||\r
1281 findchar(PyUnicode_AS_UNICODE(text),\r
1282 PyUnicode_GET_SIZE(text), '\r')))\r
1283 needflush = 1;\r
1284\r
1285 /* XXX What if we were just reading? */\r
1286 if (self->encodefunc != NULL) {\r
1287 b = (*self->encodefunc)((PyObject *) self, text);\r
1288 self->encoding_start_of_stream = 0;\r
1289 }\r
1290 else\r
1291 b = PyObject_CallMethodObjArgs(self->encoder,\r
1292 _PyIO_str_encode, text, NULL);\r
1293 Py_DECREF(text);\r
1294 if (b == NULL)\r
1295 return NULL;\r
1296\r
1297 if (self->pending_bytes == NULL) {\r
1298 self->pending_bytes = PyList_New(0);\r
1299 if (self->pending_bytes == NULL) {\r
1300 Py_DECREF(b);\r
1301 return NULL;\r
1302 }\r
1303 self->pending_bytes_count = 0;\r
1304 }\r
1305 if (PyList_Append(self->pending_bytes, b) < 0) {\r
1306 Py_DECREF(b);\r
1307 return NULL;\r
1308 }\r
1309 self->pending_bytes_count += PyBytes_GET_SIZE(b);\r
1310 Py_DECREF(b);\r
1311 if (self->pending_bytes_count > self->chunk_size || needflush) {\r
1312 if (_textiowrapper_writeflush(self) < 0)\r
1313 return NULL;\r
1314 }\r
1315\r
1316 if (needflush) {\r
1317 ret = PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_flush, NULL);\r
1318 if (ret == NULL)\r
1319 return NULL;\r
1320 Py_DECREF(ret);\r
1321 }\r
1322\r
1323 Py_CLEAR(self->snapshot);\r
1324\r
1325 if (self->decoder) {\r
1326 ret = PyObject_CallMethod(self->decoder, "reset", NULL);\r
1327 if (ret == NULL)\r
1328 return NULL;\r
1329 Py_DECREF(ret);\r
1330 }\r
1331\r
1332 return PyLong_FromSsize_t(textlen);\r
1333}\r
1334\r
1335/* Steal a reference to chars and store it in the decoded_char buffer;\r
1336 */\r
1337static void\r
1338textiowrapper_set_decoded_chars(textio *self, PyObject *chars)\r
1339{\r
1340 Py_CLEAR(self->decoded_chars);\r
1341 self->decoded_chars = chars;\r
1342 self->decoded_chars_used = 0;\r
1343}\r
1344\r
1345static PyObject *\r
1346textiowrapper_get_decoded_chars(textio *self, Py_ssize_t n)\r
1347{\r
1348 PyObject *chars;\r
1349 Py_ssize_t avail;\r
1350\r
1351 if (self->decoded_chars == NULL)\r
1352 return PyUnicode_FromStringAndSize(NULL, 0);\r
1353\r
1354 avail = (PyUnicode_GET_SIZE(self->decoded_chars)\r
1355 - self->decoded_chars_used);\r
1356\r
1357 assert(avail >= 0);\r
1358\r
1359 if (n < 0 || n > avail)\r
1360 n = avail;\r
1361\r
1362 if (self->decoded_chars_used > 0 || n < avail) {\r
1363 chars = PyUnicode_FromUnicode(\r
1364 PyUnicode_AS_UNICODE(self->decoded_chars)\r
1365 + self->decoded_chars_used, n);\r
1366 if (chars == NULL)\r
1367 return NULL;\r
1368 }\r
1369 else {\r
1370 chars = self->decoded_chars;\r
1371 Py_INCREF(chars);\r
1372 }\r
1373\r
1374 self->decoded_chars_used += n;\r
1375 return chars;\r
1376}\r
1377\r
1378/* Read and decode the next chunk of data from the BufferedReader.\r
1379 */\r
1380static int\r
1381textiowrapper_read_chunk(textio *self)\r
1382{\r
1383 PyObject *dec_buffer = NULL;\r
1384 PyObject *dec_flags = NULL;\r
1385 PyObject *input_chunk = NULL;\r
1386 PyObject *decoded_chars, *chunk_size;\r
1387 int eof;\r
1388\r
1389 /* The return value is True unless EOF was reached. The decoded string is\r
1390 * placed in self._decoded_chars (replacing its previous value). The\r
1391 * entire input chunk is sent to the decoder, though some of it may remain\r
1392 * buffered in the decoder, yet to be converted.\r
1393 */\r
1394\r
1395 if (self->decoder == NULL) {\r
1396 PyErr_SetString(PyExc_IOError, "not readable");\r
1397 return -1;\r
1398 }\r
1399\r
1400 if (self->telling) {\r
1401 /* To prepare for tell(), we need to snapshot a point in the file\r
1402 * where the decoder's input buffer is empty.\r
1403 */\r
1404\r
1405 PyObject *state = PyObject_CallMethodObjArgs(self->decoder,\r
1406 _PyIO_str_getstate, NULL);\r
1407 if (state == NULL)\r
1408 return -1;\r
1409 /* Given this, we know there was a valid snapshot point\r
1410 * len(dec_buffer) bytes ago with decoder state (b'', dec_flags).\r
1411 */\r
1412 if (PyArg_Parse(state, "(OO)", &dec_buffer, &dec_flags) < 0) {\r
1413 Py_DECREF(state);\r
1414 return -1;\r
1415 }\r
1416 Py_INCREF(dec_buffer);\r
1417 Py_INCREF(dec_flags);\r
1418 Py_DECREF(state);\r
1419 }\r
1420\r
1421 /* Read a chunk, decode it, and put the result in self._decoded_chars. */\r
1422 chunk_size = PyLong_FromSsize_t(self->chunk_size);\r
1423 if (chunk_size == NULL)\r
1424 goto fail;\r
1425 input_chunk = PyObject_CallMethodObjArgs(self->buffer,\r
1426 _PyIO_str_read1, chunk_size, NULL);\r
1427 Py_DECREF(chunk_size);\r
1428 if (input_chunk == NULL)\r
1429 goto fail;\r
1430 if (!PyBytes_Check(input_chunk)) {\r
1431 PyErr_Format(PyExc_TypeError,\r
1432 "underlying read1() should have returned a bytes object, "\r
1433 "not '%.200s'", Py_TYPE(input_chunk)->tp_name);\r
1434 goto fail;\r
1435 }\r
1436\r
1437 eof = (PyBytes_Size(input_chunk) == 0);\r
1438\r
1439 if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) {\r
1440 decoded_chars = _PyIncrementalNewlineDecoder_decode(\r
1441 self->decoder, input_chunk, eof);\r
1442 }\r
1443 else {\r
1444 decoded_chars = PyObject_CallMethodObjArgs(self->decoder,\r
1445 _PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL);\r
1446 }\r
1447\r
1448 if (check_decoded(decoded_chars) < 0)\r
1449 goto fail;\r
1450 textiowrapper_set_decoded_chars(self, decoded_chars);\r
1451 if (PyUnicode_GET_SIZE(decoded_chars) > 0)\r
1452 eof = 0;\r
1453\r
1454 if (self->telling) {\r
1455 /* At the snapshot point, len(dec_buffer) bytes before the read, the\r
1456 * next input to be decoded is dec_buffer + input_chunk.\r
1457 */\r
1458 PyObject *next_input = PyNumber_Add(dec_buffer, input_chunk);\r
1459 if (next_input == NULL)\r
1460 goto fail;\r
1461 if (!PyBytes_Check(next_input)) {\r
1462 PyErr_Format(PyExc_TypeError,\r
1463 "decoder getstate() should have returned a bytes "\r
1464 "object, not '%.200s'",\r
1465 Py_TYPE(next_input)->tp_name);\r
1466 Py_DECREF(next_input);\r
1467 goto fail;\r
1468 }\r
1469 Py_DECREF(dec_buffer);\r
1470 Py_CLEAR(self->snapshot);\r
1471 self->snapshot = Py_BuildValue("NN", dec_flags, next_input);\r
1472 }\r
1473 Py_DECREF(input_chunk);\r
1474\r
1475 return (eof == 0);\r
1476\r
1477 fail:\r
1478 Py_XDECREF(dec_buffer);\r
1479 Py_XDECREF(dec_flags);\r
1480 Py_XDECREF(input_chunk);\r
1481 return -1;\r
1482}\r
1483\r
1484static PyObject *\r
1485textiowrapper_read(textio *self, PyObject *args)\r
1486{\r
1487 Py_ssize_t n = -1;\r
1488 PyObject *result = NULL, *chunks = NULL;\r
1489\r
1490 CHECK_ATTACHED(self);\r
1491\r
1492 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n))\r
1493 return NULL;\r
1494\r
1495 CHECK_CLOSED(self);\r
1496\r
1497 if (self->decoder == NULL) {\r
1498 PyErr_SetString(PyExc_IOError, "not readable");\r
1499 return NULL;\r
1500 }\r
1501\r
1502 if (_textiowrapper_writeflush(self) < 0)\r
1503 return NULL;\r
1504\r
1505 if (n < 0) {\r
1506 /* Read everything */\r
1507 PyObject *bytes = PyObject_CallMethod(self->buffer, "read", NULL);\r
1508 PyObject *decoded, *final;\r
1509 if (bytes == NULL)\r
1510 goto fail;\r
1511 decoded = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_decode,\r
1512 bytes, Py_True, NULL);\r
1513 Py_DECREF(bytes);\r
1514 if (check_decoded(decoded) < 0)\r
1515 goto fail;\r
1516\r
1517 result = textiowrapper_get_decoded_chars(self, -1);\r
1518\r
1519 if (result == NULL) {\r
1520 Py_DECREF(decoded);\r
1521 return NULL;\r
1522 }\r
1523\r
1524 final = PyUnicode_Concat(result, decoded);\r
1525 Py_DECREF(result);\r
1526 Py_DECREF(decoded);\r
1527 if (final == NULL)\r
1528 goto fail;\r
1529\r
1530 Py_CLEAR(self->snapshot);\r
1531 return final;\r
1532 }\r
1533 else {\r
1534 int res = 1;\r
1535 Py_ssize_t remaining = n;\r
1536\r
1537 result = textiowrapper_get_decoded_chars(self, n);\r
1538 if (result == NULL)\r
1539 goto fail;\r
1540 remaining -= PyUnicode_GET_SIZE(result);\r
1541\r
1542 /* Keep reading chunks until we have n characters to return */\r
1543 while (remaining > 0) {\r
1544 res = textiowrapper_read_chunk(self);\r
1545 if (res < 0) {\r
1546 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()\r
1547 when EINTR occurs so we needn't do it ourselves. */\r
1548 if (_PyIO_trap_eintr()) {\r
1549 continue;\r
1550 }\r
1551 goto fail;\r
1552 }\r
1553 if (res == 0) /* EOF */\r
1554 break;\r
1555 if (chunks == NULL) {\r
1556 chunks = PyList_New(0);\r
1557 if (chunks == NULL)\r
1558 goto fail;\r
1559 }\r
1560 if (PyList_Append(chunks, result) < 0)\r
1561 goto fail;\r
1562 Py_DECREF(result);\r
1563 result = textiowrapper_get_decoded_chars(self, remaining);\r
1564 if (result == NULL)\r
1565 goto fail;\r
1566 remaining -= PyUnicode_GET_SIZE(result);\r
1567 }\r
1568 if (chunks != NULL) {\r
1569 if (result != NULL && PyList_Append(chunks, result) < 0)\r
1570 goto fail;\r
1571 Py_CLEAR(result);\r
1572 result = PyUnicode_Join(_PyIO_empty_str, chunks);\r
1573 if (result == NULL)\r
1574 goto fail;\r
1575 Py_CLEAR(chunks);\r
1576 }\r
1577 return result;\r
1578 }\r
1579 fail:\r
1580 Py_XDECREF(result);\r
1581 Py_XDECREF(chunks);\r
1582 return NULL;\r
1583}\r
1584\r
1585\r
1586/* NOTE: `end` must point to the real end of the Py_UNICODE storage,\r
1587 that is to the NUL character. Otherwise the function will produce\r
1588 incorrect results. */\r
1589static Py_UNICODE *\r
1590find_control_char(Py_UNICODE *start, Py_UNICODE *end, Py_UNICODE ch)\r
1591{\r
1592 Py_UNICODE *s = start;\r
1593 for (;;) {\r
1594 while (*s > ch)\r
1595 s++;\r
1596 if (*s == ch)\r
1597 return s;\r
1598 if (s == end)\r
1599 return NULL;\r
1600 s++;\r
1601 }\r
1602}\r
1603\r
1604Py_ssize_t\r
1605_PyIO_find_line_ending(\r
1606 int translated, int universal, PyObject *readnl,\r
1607 Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed)\r
1608{\r
1609 Py_ssize_t len = end - start;\r
1610\r
1611 if (translated) {\r
1612 /* Newlines are already translated, only search for \n */\r
1613 Py_UNICODE *pos = find_control_char(start, end, '\n');\r
1614 if (pos != NULL)\r
1615 return pos - start + 1;\r
1616 else {\r
1617 *consumed = len;\r
1618 return -1;\r
1619 }\r
1620 }\r
1621 else if (universal) {\r
1622 /* Universal newline search. Find any of \r, \r\n, \n\r
1623 * The decoder ensures that \r\n are not split in two pieces\r
1624 */\r
1625 Py_UNICODE *s = start;\r
1626 for (;;) {\r
1627 Py_UNICODE ch;\r
1628 /* Fast path for non-control chars. The loop always ends\r
1629 since the Py_UNICODE storage is NUL-terminated. */\r
1630 while (*s > '\r')\r
1631 s++;\r
1632 if (s >= end) {\r
1633 *consumed = len;\r
1634 return -1;\r
1635 }\r
1636 ch = *s++;\r
1637 if (ch == '\n')\r
1638 return s - start;\r
1639 if (ch == '\r') {\r
1640 if (*s == '\n')\r
1641 return s - start + 1;\r
1642 else\r
1643 return s - start;\r
1644 }\r
1645 }\r
1646 }\r
1647 else {\r
1648 /* Non-universal mode. */\r
1649 Py_ssize_t readnl_len = PyString_GET_SIZE(readnl);\r
1650 unsigned char *nl = (unsigned char *) PyString_AS_STRING(readnl);\r
1651 if (readnl_len == 1) {\r
1652 Py_UNICODE *pos = find_control_char(start, end, nl[0]);\r
1653 if (pos != NULL)\r
1654 return pos - start + 1;\r
1655 *consumed = len;\r
1656 return -1;\r
1657 }\r
1658 else {\r
1659 Py_UNICODE *s = start;\r
1660 Py_UNICODE *e = end - readnl_len + 1;\r
1661 Py_UNICODE *pos;\r
1662 if (e < s)\r
1663 e = s;\r
1664 while (s < e) {\r
1665 Py_ssize_t i;\r
1666 Py_UNICODE *pos = find_control_char(s, end, nl[0]);\r
1667 if (pos == NULL || pos >= e)\r
1668 break;\r
1669 for (i = 1; i < readnl_len; i++) {\r
1670 if (pos[i] != nl[i])\r
1671 break;\r
1672 }\r
1673 if (i == readnl_len)\r
1674 return pos - start + readnl_len;\r
1675 s = pos + 1;\r
1676 }\r
1677 pos = find_control_char(e, end, nl[0]);\r
1678 if (pos == NULL)\r
1679 *consumed = len;\r
1680 else\r
1681 *consumed = pos - start;\r
1682 return -1;\r
1683 }\r
1684 }\r
1685}\r
1686\r
1687static PyObject *\r
1688_textiowrapper_readline(textio *self, Py_ssize_t limit)\r
1689{\r
1690 PyObject *line = NULL, *chunks = NULL, *remaining = NULL;\r
1691 Py_ssize_t start, endpos, chunked, offset_to_buffer;\r
1692 int res;\r
1693\r
1694 CHECK_CLOSED(self);\r
1695\r
1696 if (_textiowrapper_writeflush(self) < 0)\r
1697 return NULL;\r
1698\r
1699 chunked = 0;\r
1700\r
1701 while (1) {\r
1702 Py_UNICODE *ptr;\r
1703 Py_ssize_t line_len;\r
1704 Py_ssize_t consumed = 0;\r
1705\r
1706 /* First, get some data if necessary */\r
1707 res = 1;\r
1708 while (!self->decoded_chars ||\r
1709 !PyUnicode_GET_SIZE(self->decoded_chars)) {\r
1710 res = textiowrapper_read_chunk(self);\r
1711 if (res < 0) {\r
1712 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()\r
1713 when EINTR occurs so we needn't do it ourselves. */\r
1714 if (_PyIO_trap_eintr()) {\r
1715 continue;\r
1716 }\r
1717 goto error;\r
1718 }\r
1719 if (res == 0)\r
1720 break;\r
1721 }\r
1722 if (res == 0) {\r
1723 /* end of file */\r
1724 textiowrapper_set_decoded_chars(self, NULL);\r
1725 Py_CLEAR(self->snapshot);\r
1726 start = endpos = offset_to_buffer = 0;\r
1727 break;\r
1728 }\r
1729\r
1730 if (remaining == NULL) {\r
1731 line = self->decoded_chars;\r
1732 start = self->decoded_chars_used;\r
1733 offset_to_buffer = 0;\r
1734 Py_INCREF(line);\r
1735 }\r
1736 else {\r
1737 assert(self->decoded_chars_used == 0);\r
1738 line = PyUnicode_Concat(remaining, self->decoded_chars);\r
1739 start = 0;\r
1740 offset_to_buffer = PyUnicode_GET_SIZE(remaining);\r
1741 Py_CLEAR(remaining);\r
1742 if (line == NULL)\r
1743 goto error;\r
1744 }\r
1745\r
1746 ptr = PyUnicode_AS_UNICODE(line);\r
1747 line_len = PyUnicode_GET_SIZE(line);\r
1748\r
1749 endpos = _PyIO_find_line_ending(\r
1750 self->readtranslate, self->readuniversal, self->readnl,\r
1751 ptr + start, ptr + line_len, &consumed);\r
1752 if (endpos >= 0) {\r
1753 endpos += start;\r
1754 if (limit >= 0 && (endpos - start) + chunked >= limit)\r
1755 endpos = start + limit - chunked;\r
1756 break;\r
1757 }\r
1758\r
1759 /* We can put aside up to `endpos` */\r
1760 endpos = consumed + start;\r
1761 if (limit >= 0 && (endpos - start) + chunked >= limit) {\r
1762 /* Didn't find line ending, but reached length limit */\r
1763 endpos = start + limit - chunked;\r
1764 break;\r
1765 }\r
1766\r
1767 if (endpos > start) {\r
1768 /* No line ending seen yet - put aside current data */\r
1769 PyObject *s;\r
1770 if (chunks == NULL) {\r
1771 chunks = PyList_New(0);\r
1772 if (chunks == NULL)\r
1773 goto error;\r
1774 }\r
1775 s = PyUnicode_FromUnicode(ptr + start, endpos - start);\r
1776 if (s == NULL)\r
1777 goto error;\r
1778 if (PyList_Append(chunks, s) < 0) {\r
1779 Py_DECREF(s);\r
1780 goto error;\r
1781 }\r
1782 chunked += PyUnicode_GET_SIZE(s);\r
1783 Py_DECREF(s);\r
1784 }\r
1785 /* There may be some remaining bytes we'll have to prepend to the\r
1786 next chunk of data */\r
1787 if (endpos < line_len) {\r
1788 remaining = PyUnicode_FromUnicode(\r
1789 ptr + endpos, line_len - endpos);\r
1790 if (remaining == NULL)\r
1791 goto error;\r
1792 }\r
1793 Py_CLEAR(line);\r
1794 /* We have consumed the buffer */\r
1795 textiowrapper_set_decoded_chars(self, NULL);\r
1796 }\r
1797\r
1798 if (line != NULL) {\r
1799 /* Our line ends in the current buffer */\r
1800 self->decoded_chars_used = endpos - offset_to_buffer;\r
1801 if (start > 0 || endpos < PyUnicode_GET_SIZE(line)) {\r
1802 if (start == 0 && Py_REFCNT(line) == 1) {\r
1803 if (PyUnicode_Resize(&line, endpos) < 0)\r
1804 goto error;\r
1805 }\r
1806 else {\r
1807 PyObject *s = PyUnicode_FromUnicode(\r
1808 PyUnicode_AS_UNICODE(line) + start, endpos - start);\r
1809 Py_CLEAR(line);\r
1810 if (s == NULL)\r
1811 goto error;\r
1812 line = s;\r
1813 }\r
1814 }\r
1815 }\r
1816 if (remaining != NULL) {\r
1817 if (chunks == NULL) {\r
1818 chunks = PyList_New(0);\r
1819 if (chunks == NULL)\r
1820 goto error;\r
1821 }\r
1822 if (PyList_Append(chunks, remaining) < 0)\r
1823 goto error;\r
1824 Py_CLEAR(remaining);\r
1825 }\r
1826 if (chunks != NULL) {\r
1827 if (line != NULL && PyList_Append(chunks, line) < 0)\r
1828 goto error;\r
1829 Py_CLEAR(line);\r
1830 line = PyUnicode_Join(_PyIO_empty_str, chunks);\r
1831 if (line == NULL)\r
1832 goto error;\r
1833 Py_DECREF(chunks);\r
1834 }\r
1835 if (line == NULL)\r
1836 line = PyUnicode_FromStringAndSize(NULL, 0);\r
1837\r
1838 return line;\r
1839\r
1840 error:\r
1841 Py_XDECREF(chunks);\r
1842 Py_XDECREF(remaining);\r
1843 Py_XDECREF(line);\r
1844 return NULL;\r
1845}\r
1846\r
1847static PyObject *\r
1848textiowrapper_readline(textio *self, PyObject *args)\r
1849{\r
1850 PyObject *limitobj = NULL;\r
1851 Py_ssize_t limit = -1;\r
1852\r
1853 CHECK_ATTACHED(self);\r
1854 if (!PyArg_ParseTuple(args, "|O:readline", &limitobj)) {\r
1855 return NULL;\r
1856 }\r
1857 if (limitobj) {\r
1858 if (!PyNumber_Check(limitobj)) {\r
1859 PyErr_Format(PyExc_TypeError,\r
1860 "integer argument expected, got '%.200s'",\r
1861 Py_TYPE(limitobj)->tp_name);\r
1862 return NULL;\r
1863 }\r
1864 limit = PyNumber_AsSsize_t(limitobj, PyExc_OverflowError);\r
1865 if (limit == -1 && PyErr_Occurred())\r
1866 return NULL;\r
1867 }\r
1868 return _textiowrapper_readline(self, limit);\r
1869}\r
1870\r
1871/* Seek and Tell */\r
1872\r
1873typedef struct {\r
1874 Py_off_t start_pos;\r
1875 int dec_flags;\r
1876 int bytes_to_feed;\r
1877 int chars_to_skip;\r
1878 char need_eof;\r
1879} cookie_type;\r
1880\r
1881/*\r
1882 To speed up cookie packing/unpacking, we store the fields in a temporary\r
1883 string and call _PyLong_FromByteArray() or _PyLong_AsByteArray (resp.).\r
1884 The following macros define at which offsets in the intermediary byte\r
1885 string the various CookieStruct fields will be stored.\r
1886 */\r
1887\r
1888#define COOKIE_BUF_LEN (sizeof(Py_off_t) + 3 * sizeof(int) + sizeof(char))\r
1889\r
1890#if defined(WORDS_BIGENDIAN)\r
1891\r
1892# define IS_LITTLE_ENDIAN 0\r
1893\r
1894/* We want the least significant byte of start_pos to also be the least\r
1895 significant byte of the cookie, which means that in big-endian mode we\r
1896 must copy the fields in reverse order. */\r
1897\r
1898# define OFF_START_POS (sizeof(char) + 3 * sizeof(int))\r
1899# define OFF_DEC_FLAGS (sizeof(char) + 2 * sizeof(int))\r
1900# define OFF_BYTES_TO_FEED (sizeof(char) + sizeof(int))\r
1901# define OFF_CHARS_TO_SKIP (sizeof(char))\r
1902# define OFF_NEED_EOF 0\r
1903\r
1904#else\r
1905\r
1906# define IS_LITTLE_ENDIAN 1\r
1907\r
1908/* Little-endian mode: the least significant byte of start_pos will\r
1909 naturally end up the least significant byte of the cookie. */\r
1910\r
1911# define OFF_START_POS 0\r
1912# define OFF_DEC_FLAGS (sizeof(Py_off_t))\r
1913# define OFF_BYTES_TO_FEED (sizeof(Py_off_t) + sizeof(int))\r
1914# define OFF_CHARS_TO_SKIP (sizeof(Py_off_t) + 2 * sizeof(int))\r
1915# define OFF_NEED_EOF (sizeof(Py_off_t) + 3 * sizeof(int))\r
1916\r
1917#endif\r
1918\r
1919static int\r
1920textiowrapper_parse_cookie(cookie_type *cookie, PyObject *cookieObj)\r
1921{\r
1922 unsigned char buffer[COOKIE_BUF_LEN];\r
1923 PyLongObject *cookieLong = (PyLongObject *)PyNumber_Long(cookieObj);\r
1924 if (cookieLong == NULL)\r
1925 return -1;\r
1926\r
1927 if (_PyLong_AsByteArray(cookieLong, buffer, sizeof(buffer),\r
1928 IS_LITTLE_ENDIAN, 0) < 0) {\r
1929 Py_DECREF(cookieLong);\r
1930 return -1;\r
1931 }\r
1932 Py_DECREF(cookieLong);\r
1933\r
1934 memcpy(&cookie->start_pos, buffer + OFF_START_POS, sizeof(cookie->start_pos));\r
1935 memcpy(&cookie->dec_flags, buffer + OFF_DEC_FLAGS, sizeof(cookie->dec_flags));\r
1936 memcpy(&cookie->bytes_to_feed, buffer + OFF_BYTES_TO_FEED, sizeof(cookie->bytes_to_feed));\r
1937 memcpy(&cookie->chars_to_skip, buffer + OFF_CHARS_TO_SKIP, sizeof(cookie->chars_to_skip));\r
1938 memcpy(&cookie->need_eof, buffer + OFF_NEED_EOF, sizeof(cookie->need_eof));\r
1939\r
1940 return 0;\r
1941}\r
1942\r
1943static PyObject *\r
1944textiowrapper_build_cookie(cookie_type *cookie)\r
1945{\r
1946 unsigned char buffer[COOKIE_BUF_LEN];\r
1947\r
1948 memcpy(buffer + OFF_START_POS, &cookie->start_pos, sizeof(cookie->start_pos));\r
1949 memcpy(buffer + OFF_DEC_FLAGS, &cookie->dec_flags, sizeof(cookie->dec_flags));\r
1950 memcpy(buffer + OFF_BYTES_TO_FEED, &cookie->bytes_to_feed, sizeof(cookie->bytes_to_feed));\r
1951 memcpy(buffer + OFF_CHARS_TO_SKIP, &cookie->chars_to_skip, sizeof(cookie->chars_to_skip));\r
1952 memcpy(buffer + OFF_NEED_EOF, &cookie->need_eof, sizeof(cookie->need_eof));\r
1953\r
1954 return _PyLong_FromByteArray(buffer, sizeof(buffer), IS_LITTLE_ENDIAN, 0);\r
1955}\r
1956#undef IS_LITTLE_ENDIAN\r
1957\r
1958static int\r
1959_textiowrapper_decoder_setstate(textio *self, cookie_type *cookie)\r
1960{\r
1961 PyObject *res;\r
1962 /* When seeking to the start of the stream, we call decoder.reset()\r
1963 rather than decoder.getstate().\r
1964 This is for a few decoders such as utf-16 for which the state value\r
1965 at start is not (b"", 0) but e.g. (b"", 2) (meaning, in the case of\r
1966 utf-16, that we are expecting a BOM).\r
1967 */\r
1968 if (cookie->start_pos == 0 && cookie->dec_flags == 0)\r
1969 res = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL);\r
1970 else\r
1971 res = PyObject_CallMethod(self->decoder, "setstate",\r
1972 "((si))", "", cookie->dec_flags);\r
1973 if (res == NULL)\r
1974 return -1;\r
1975 Py_DECREF(res);\r
1976 return 0;\r
1977}\r
1978\r
1979static int\r
1980_textiowrapper_encoder_setstate(textio *self, cookie_type *cookie)\r
1981{\r
1982 PyObject *res;\r
1983 /* Same as _textiowrapper_decoder_setstate() above. */\r
1984 if (cookie->start_pos == 0 && cookie->dec_flags == 0) {\r
1985 res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_reset, NULL);\r
1986 self->encoding_start_of_stream = 1;\r
1987 }\r
1988 else {\r
1989 res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,\r
1990 _PyIO_zero, NULL);\r
1991 self->encoding_start_of_stream = 0;\r
1992 }\r
1993 if (res == NULL)\r
1994 return -1;\r
1995 Py_DECREF(res);\r
1996 return 0;\r
1997}\r
1998\r
1999static PyObject *\r
2000textiowrapper_seek(textio *self, PyObject *args)\r
2001{\r
2002 PyObject *cookieObj, *posobj;\r
2003 cookie_type cookie;\r
2004 int whence = 0;\r
2005 PyObject *res;\r
2006 int cmp;\r
2007\r
2008 CHECK_ATTACHED(self);\r
2009\r
2010 if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence))\r
2011 return NULL;\r
2012 CHECK_CLOSED(self);\r
2013\r
2014 Py_INCREF(cookieObj);\r
2015\r
2016 if (!self->seekable) {\r
2017 PyErr_SetString(PyExc_IOError,\r
2018 "underlying stream is not seekable");\r
2019 goto fail;\r
2020 }\r
2021\r
2022 if (whence == 1) {\r
2023 /* seek relative to current position */\r
2024 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);\r
2025 if (cmp < 0)\r
2026 goto fail;\r
2027\r
2028 if (cmp == 0) {\r
2029 PyErr_SetString(PyExc_IOError,\r
2030 "can't do nonzero cur-relative seeks");\r
2031 goto fail;\r
2032 }\r
2033\r
2034 /* Seeking to the current position should attempt to\r
2035 * sync the underlying buffer with the current position.\r
2036 */\r
2037 Py_DECREF(cookieObj);\r
2038 cookieObj = PyObject_CallMethod((PyObject *)self, "tell", NULL);\r
2039 if (cookieObj == NULL)\r
2040 goto fail;\r
2041 }\r
2042 else if (whence == 2) {\r
2043 /* seek relative to end of file */\r
2044\r
2045 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);\r
2046 if (cmp < 0)\r
2047 goto fail;\r
2048\r
2049 if (cmp == 0) {\r
2050 PyErr_SetString(PyExc_IOError,\r
2051 "can't do nonzero end-relative seeks");\r
2052 goto fail;\r
2053 }\r
2054\r
2055 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);\r
2056 if (res == NULL)\r
2057 goto fail;\r
2058 Py_DECREF(res);\r
2059\r
2060 textiowrapper_set_decoded_chars(self, NULL);\r
2061 Py_CLEAR(self->snapshot);\r
2062 if (self->decoder) {\r
2063 res = PyObject_CallMethod(self->decoder, "reset", NULL);\r
2064 if (res == NULL)\r
2065 goto fail;\r
2066 Py_DECREF(res);\r
2067 }\r
2068\r
2069 res = PyObject_CallMethod(self->buffer, "seek", "ii", 0, 2);\r
2070 Py_XDECREF(cookieObj);\r
2071 return res;\r
2072 }\r
2073 else if (whence != 0) {\r
2074 PyErr_Format(PyExc_ValueError,\r
2075 "invalid whence (%d, should be 0, 1 or 2)", whence);\r
2076 goto fail;\r
2077 }\r
2078\r
2079 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_LT);\r
2080 if (cmp < 0)\r
2081 goto fail;\r
2082\r
2083 if (cmp == 1) {\r
2084 PyObject *repr = PyObject_Repr(cookieObj);\r
2085 if (repr != NULL) {\r
2086 PyErr_Format(PyExc_ValueError,\r
2087 "negative seek position %s",\r
2088 PyString_AS_STRING(repr));\r
2089 Py_DECREF(repr);\r
2090 }\r
2091 goto fail;\r
2092 }\r
2093\r
2094 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);\r
2095 if (res == NULL)\r
2096 goto fail;\r
2097 Py_DECREF(res);\r
2098\r
2099 /* The strategy of seek() is to go back to the safe start point\r
2100 * and replay the effect of read(chars_to_skip) from there.\r
2101 */\r
2102 if (textiowrapper_parse_cookie(&cookie, cookieObj) < 0)\r
2103 goto fail;\r
2104\r
2105 /* Seek back to the safe start point. */\r
2106 posobj = PyLong_FromOff_t(cookie.start_pos);\r
2107 if (posobj == NULL)\r
2108 goto fail;\r
2109 res = PyObject_CallMethodObjArgs(self->buffer,\r
2110 _PyIO_str_seek, posobj, NULL);\r
2111 Py_DECREF(posobj);\r
2112 if (res == NULL)\r
2113 goto fail;\r
2114 Py_DECREF(res);\r
2115\r
2116 textiowrapper_set_decoded_chars(self, NULL);\r
2117 Py_CLEAR(self->snapshot);\r
2118\r
2119 /* Restore the decoder to its state from the safe start point. */\r
2120 if (self->decoder) {\r
2121 if (_textiowrapper_decoder_setstate(self, &cookie) < 0)\r
2122 goto fail;\r
2123 }\r
2124\r
2125 if (cookie.chars_to_skip) {\r
2126 /* Just like _read_chunk, feed the decoder and save a snapshot. */\r
2127 PyObject *input_chunk = PyObject_CallMethod(\r
2128 self->buffer, "read", "i", cookie.bytes_to_feed);\r
2129 PyObject *decoded;\r
2130\r
2131 if (input_chunk == NULL)\r
2132 goto fail;\r
2133\r
2134 if (!PyBytes_Check(input_chunk)) {\r
2135 PyErr_Format(PyExc_TypeError,\r
2136 "underlying read() should have returned a bytes "\r
2137 "object, not '%.200s'",\r
2138 Py_TYPE(input_chunk)->tp_name);\r
2139 Py_DECREF(input_chunk);\r
2140 goto fail;\r
2141 }\r
2142\r
2143 self->snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk);\r
2144 if (self->snapshot == NULL) {\r
2145 Py_DECREF(input_chunk);\r
2146 goto fail;\r
2147 }\r
2148\r
2149 decoded = PyObject_CallMethod(self->decoder, "decode",\r
2150 "Oi", input_chunk, (int)cookie.need_eof);\r
2151\r
2152 if (check_decoded(decoded) < 0)\r
2153 goto fail;\r
2154\r
2155 textiowrapper_set_decoded_chars(self, decoded);\r
2156\r
2157 /* Skip chars_to_skip of the decoded characters. */\r
2158 if (PyUnicode_GetSize(self->decoded_chars) < cookie.chars_to_skip) {\r
2159 PyErr_SetString(PyExc_IOError, "can't restore logical file position");\r
2160 goto fail;\r
2161 }\r
2162 self->decoded_chars_used = cookie.chars_to_skip;\r
2163 }\r
2164 else {\r
2165 self->snapshot = Py_BuildValue("is", cookie.dec_flags, "");\r
2166 if (self->snapshot == NULL)\r
2167 goto fail;\r
2168 }\r
2169\r
2170 /* Finally, reset the encoder (merely useful for proper BOM handling) */\r
2171 if (self->encoder) {\r
2172 if (_textiowrapper_encoder_setstate(self, &cookie) < 0)\r
2173 goto fail;\r
2174 }\r
2175 return cookieObj;\r
2176 fail:\r
2177 Py_XDECREF(cookieObj);\r
2178 return NULL;\r
2179\r
2180}\r
2181\r
2182static PyObject *\r
2183textiowrapper_tell(textio *self, PyObject *args)\r
2184{\r
2185 PyObject *res;\r
2186 PyObject *posobj = NULL;\r
2187 cookie_type cookie = {0,0,0,0,0};\r
2188 PyObject *next_input;\r
2189 Py_ssize_t chars_to_skip, chars_decoded;\r
2190 PyObject *saved_state = NULL;\r
2191 char *input, *input_end;\r
2192\r
2193 CHECK_ATTACHED(self);\r
2194 CHECK_CLOSED(self);\r
2195\r
2196 if (!self->seekable) {\r
2197 PyErr_SetString(PyExc_IOError,\r
2198 "underlying stream is not seekable");\r
2199 goto fail;\r
2200 }\r
2201 if (!self->telling) {\r
2202 PyErr_SetString(PyExc_IOError,\r
2203 "telling position disabled by next() call");\r
2204 goto fail;\r
2205 }\r
2206\r
2207 if (_textiowrapper_writeflush(self) < 0)\r
2208 return NULL;\r
2209 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);\r
2210 if (res == NULL)\r
2211 goto fail;\r
2212 Py_DECREF(res);\r
2213\r
2214 posobj = PyObject_CallMethod(self->buffer, "tell", NULL);\r
2215 if (posobj == NULL)\r
2216 goto fail;\r
2217\r
2218 if (self->decoder == NULL || self->snapshot == NULL) {\r
2219 assert (self->decoded_chars == NULL || PyUnicode_GetSize(self->decoded_chars) == 0);\r
2220 return posobj;\r
2221 }\r
2222\r
2223#if defined(HAVE_LARGEFILE_SUPPORT)\r
2224 cookie.start_pos = PyLong_AsLongLong(posobj);\r
2225#else\r
2226 cookie.start_pos = PyLong_AsLong(posobj);\r
2227#endif\r
2228 if (PyErr_Occurred())\r
2229 goto fail;\r
2230\r
2231 /* Skip backward to the snapshot point (see _read_chunk). */\r
2232 if (!PyArg_Parse(self->snapshot, "(iO)", &cookie.dec_flags, &next_input))\r
2233 goto fail;\r
2234\r
2235 assert (PyBytes_Check(next_input));\r
2236\r
2237 cookie.start_pos -= PyBytes_GET_SIZE(next_input);\r
2238\r
2239 /* How many decoded characters have been used up since the snapshot? */\r
2240 if (self->decoded_chars_used == 0) {\r
2241 /* We haven't moved from the snapshot point. */\r
2242 Py_DECREF(posobj);\r
2243 return textiowrapper_build_cookie(&cookie);\r
2244 }\r
2245\r
2246 chars_to_skip = self->decoded_chars_used;\r
2247\r
2248 /* Starting from the snapshot position, we will walk the decoder\r
2249 * forward until it gives us enough decoded characters.\r
2250 */\r
2251 saved_state = PyObject_CallMethodObjArgs(self->decoder,\r
2252 _PyIO_str_getstate, NULL);\r
2253 if (saved_state == NULL)\r
2254 goto fail;\r
2255\r
2256 /* Note our initial start point. */\r
2257 if (_textiowrapper_decoder_setstate(self, &cookie) < 0)\r
2258 goto fail;\r
2259\r
2260 /* Feed the decoder one byte at a time. As we go, note the\r
2261 * nearest "safe start point" before the current location\r
2262 * (a point where the decoder has nothing buffered, so seek()\r
2263 * can safely start from there and advance to this location).\r
2264 */\r
2265 chars_decoded = 0;\r
2266 input = PyBytes_AS_STRING(next_input);\r
2267 input_end = input + PyBytes_GET_SIZE(next_input);\r
2268 while (input < input_end) {\r
2269 PyObject *state;\r
2270 char *dec_buffer;\r
2271 Py_ssize_t dec_buffer_len;\r
2272 int dec_flags;\r
2273\r
2274 PyObject *decoded = PyObject_CallMethod(\r
2275 self->decoder, "decode", "s#", input, (Py_ssize_t)1);\r
2276 if (check_decoded(decoded) < 0)\r
2277 goto fail;\r
2278 chars_decoded += PyUnicode_GET_SIZE(decoded);\r
2279 Py_DECREF(decoded);\r
2280\r
2281 cookie.bytes_to_feed += 1;\r
2282\r
2283 state = PyObject_CallMethodObjArgs(self->decoder,\r
2284 _PyIO_str_getstate, NULL);\r
2285 if (state == NULL)\r
2286 goto fail;\r
2287 if (!PyArg_Parse(state, "(s#i)", &dec_buffer, &dec_buffer_len, &dec_flags)) {\r
2288 Py_DECREF(state);\r
2289 goto fail;\r
2290 }\r
2291 Py_DECREF(state);\r
2292\r
2293 if (dec_buffer_len == 0 && chars_decoded <= chars_to_skip) {\r
2294 /* Decoder buffer is empty, so this is a safe start point. */\r
2295 cookie.start_pos += cookie.bytes_to_feed;\r
2296 chars_to_skip -= chars_decoded;\r
2297 cookie.dec_flags = dec_flags;\r
2298 cookie.bytes_to_feed = 0;\r
2299 chars_decoded = 0;\r
2300 }\r
2301 if (chars_decoded >= chars_to_skip)\r
2302 break;\r
2303 input++;\r
2304 }\r
2305 if (input == input_end) {\r
2306 /* We didn't get enough decoded data; signal EOF to get more. */\r
2307 PyObject *decoded = PyObject_CallMethod(\r
2308 self->decoder, "decode", "si", "", /* final = */ 1);\r
2309 if (check_decoded(decoded) < 0)\r
2310 goto fail;\r
2311 chars_decoded += PyUnicode_GET_SIZE(decoded);\r
2312 Py_DECREF(decoded);\r
2313 cookie.need_eof = 1;\r
2314\r
2315 if (chars_decoded < chars_to_skip) {\r
2316 PyErr_SetString(PyExc_IOError,\r
2317 "can't reconstruct logical file position");\r
2318 goto fail;\r
2319 }\r
2320 }\r
2321\r
2322 /* finally */\r
2323 Py_XDECREF(posobj);\r
2324 res = PyObject_CallMethod(self->decoder, "setstate", "(O)", saved_state);\r
2325 Py_DECREF(saved_state);\r
2326 if (res == NULL)\r
2327 return NULL;\r
2328 Py_DECREF(res);\r
2329\r
2330 /* The returned cookie corresponds to the last safe start point. */\r
2331 cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int);\r
2332 return textiowrapper_build_cookie(&cookie);\r
2333\r
2334 fail:\r
2335 Py_XDECREF(posobj);\r
2336 if (saved_state) {\r
2337 PyObject *type, *value, *traceback;\r
2338 PyErr_Fetch(&type, &value, &traceback);\r
2339\r
2340 res = PyObject_CallMethod(self->decoder, "setstate", "(O)", saved_state);\r
2341 _PyErr_ReplaceException(type, value, traceback);\r
2342 Py_DECREF(saved_state);\r
2343 Py_XDECREF(res);\r
2344 }\r
2345 return NULL;\r
2346}\r
2347\r
2348static PyObject *\r
2349textiowrapper_truncate(textio *self, PyObject *args)\r
2350{\r
2351 PyObject *pos = Py_None;\r
2352 PyObject *res;\r
2353\r
2354 CHECK_ATTACHED(self)\r
2355 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {\r
2356 return NULL;\r
2357 }\r
2358\r
2359 res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_flush, NULL);\r
2360 if (res == NULL)\r
2361 return NULL;\r
2362 Py_DECREF(res);\r
2363\r
2364 return PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_truncate, pos, NULL);\r
2365}\r
2366\r
2367static PyObject *\r
2368textiowrapper_repr(textio *self)\r
2369{\r
2370 PyObject *nameobj, *res;\r
2371 PyObject *namerepr = NULL, *encrepr = NULL;\r
2372\r
2373 CHECK_INITIALIZED(self);\r
2374\r
2375 nameobj = PyObject_GetAttrString((PyObject *) self, "name");\r
2376 if (nameobj == NULL) {\r
2377 if (PyErr_ExceptionMatches(PyExc_Exception))\r
2378 PyErr_Clear();\r
2379 else\r
2380 goto error;\r
2381 encrepr = PyObject_Repr(self->encoding);\r
2382 res = PyString_FromFormat("<_io.TextIOWrapper encoding=%s>",\r
2383 PyString_AS_STRING(encrepr));\r
2384 }\r
2385 else {\r
2386 encrepr = PyObject_Repr(self->encoding);\r
2387 namerepr = PyObject_Repr(nameobj);\r
2388 res = PyString_FromFormat("<_io.TextIOWrapper name=%s encoding=%s>",\r
2389 PyString_AS_STRING(namerepr),\r
2390 PyString_AS_STRING(encrepr));\r
2391 Py_DECREF(nameobj);\r
2392 }\r
2393 Py_XDECREF(namerepr);\r
2394 Py_XDECREF(encrepr);\r
2395 return res;\r
2396\r
2397error:\r
2398 Py_XDECREF(namerepr);\r
2399 Py_XDECREF(encrepr);\r
2400 return NULL;\r
2401}\r
2402\r
2403\r
2404/* Inquiries */\r
2405\r
2406static PyObject *\r
2407textiowrapper_fileno(textio *self, PyObject *args)\r
2408{\r
2409 CHECK_ATTACHED(self);\r
2410 return PyObject_CallMethod(self->buffer, "fileno", NULL);\r
2411}\r
2412\r
2413static PyObject *\r
2414textiowrapper_seekable(textio *self, PyObject *args)\r
2415{\r
2416 CHECK_ATTACHED(self);\r
2417 return PyObject_CallMethod(self->buffer, "seekable", NULL);\r
2418}\r
2419\r
2420static PyObject *\r
2421textiowrapper_readable(textio *self, PyObject *args)\r
2422{\r
2423 CHECK_ATTACHED(self);\r
2424 return PyObject_CallMethod(self->buffer, "readable", NULL);\r
2425}\r
2426\r
2427static PyObject *\r
2428textiowrapper_writable(textio *self, PyObject *args)\r
2429{\r
2430 CHECK_ATTACHED(self);\r
2431 return PyObject_CallMethod(self->buffer, "writable", NULL);\r
2432}\r
2433\r
2434static PyObject *\r
2435textiowrapper_isatty(textio *self, PyObject *args)\r
2436{\r
2437 CHECK_ATTACHED(self);\r
2438 return PyObject_CallMethod(self->buffer, "isatty", NULL);\r
2439}\r
2440\r
2441static PyObject *\r
2442textiowrapper_flush(textio *self, PyObject *args)\r
2443{\r
2444 CHECK_ATTACHED(self);\r
2445 CHECK_CLOSED(self);\r
2446 self->telling = self->seekable;\r
2447 if (_textiowrapper_writeflush(self) < 0)\r
2448 return NULL;\r
2449 return PyObject_CallMethod(self->buffer, "flush", NULL);\r
2450}\r
2451\r
2452static PyObject *\r
2453textiowrapper_close(textio *self, PyObject *args)\r
2454{\r
2455 PyObject *res;\r
2456 int r;\r
2457 CHECK_ATTACHED(self);\r
2458\r
2459 res = textiowrapper_closed_get(self, NULL);\r
2460 if (res == NULL)\r
2461 return NULL;\r
2462 r = PyObject_IsTrue(res);\r
2463 Py_DECREF(res);\r
2464 if (r < 0)\r
2465 return NULL;\r
2466\r
2467 if (r > 0) {\r
2468 Py_RETURN_NONE; /* stream already closed */\r
2469 }\r
2470 else {\r
2471 PyObject *exc = NULL, *val, *tb;\r
2472 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);\r
2473 if (res == NULL)\r
2474 PyErr_Fetch(&exc, &val, &tb);\r
2475 else\r
2476 Py_DECREF(res);\r
2477\r
2478 res = PyObject_CallMethod(self->buffer, "close", NULL);\r
2479 if (exc != NULL) {\r
2480 _PyErr_ReplaceException(exc, val, tb);\r
2481 Py_CLEAR(res);\r
2482 }\r
2483 return res;\r
2484 }\r
2485}\r
2486\r
2487static PyObject *\r
2488textiowrapper_iternext(textio *self)\r
2489{\r
2490 PyObject *line;\r
2491\r
2492 CHECK_ATTACHED(self);\r
2493\r
2494 self->telling = 0;\r
2495 if (Py_TYPE(self) == &PyTextIOWrapper_Type) {\r
2496 /* Skip method call overhead for speed */\r
2497 line = _textiowrapper_readline(self, -1);\r
2498 }\r
2499 else {\r
2500 line = PyObject_CallMethodObjArgs((PyObject *)self,\r
2501 _PyIO_str_readline, NULL);\r
2502 if (line && !PyUnicode_Check(line)) {\r
2503 PyErr_Format(PyExc_IOError,\r
2504 "readline() should have returned an str object, "\r
2505 "not '%.200s'", Py_TYPE(line)->tp_name);\r
2506 Py_DECREF(line);\r
2507 return NULL;\r
2508 }\r
2509 }\r
2510\r
2511 if (line == NULL)\r
2512 return NULL;\r
2513\r
2514 if (PyUnicode_GET_SIZE(line) == 0) {\r
2515 /* Reached EOF or would have blocked */\r
2516 Py_DECREF(line);\r
2517 Py_CLEAR(self->snapshot);\r
2518 self->telling = self->seekable;\r
2519 return NULL;\r
2520 }\r
2521\r
2522 return line;\r
2523}\r
2524\r
2525static PyObject *\r
2526textiowrapper_name_get(textio *self, void *context)\r
2527{\r
2528 CHECK_ATTACHED(self);\r
2529 return PyObject_GetAttrString(self->buffer, "name");\r
2530}\r
2531\r
2532static PyObject *\r
2533textiowrapper_closed_get(textio *self, void *context)\r
2534{\r
2535 CHECK_ATTACHED(self);\r
2536 return PyObject_GetAttr(self->buffer, _PyIO_str_closed);\r
2537}\r
2538\r
2539static PyObject *\r
2540textiowrapper_newlines_get(textio *self, void *context)\r
2541{\r
2542 PyObject *res;\r
2543 CHECK_ATTACHED(self);\r
2544 if (self->decoder == NULL)\r
2545 Py_RETURN_NONE;\r
2546 res = PyObject_GetAttr(self->decoder, _PyIO_str_newlines);\r
2547 if (res == NULL) {\r
2548 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {\r
2549 PyErr_Clear();\r
2550 Py_RETURN_NONE;\r
2551 }\r
2552 else {\r
2553 return NULL;\r
2554 }\r
2555 }\r
2556 return res;\r
2557}\r
2558\r
2559static PyObject *\r
2560textiowrapper_errors_get(textio *self, void *context)\r
2561{\r
2562 CHECK_INITIALIZED(self);\r
2563 Py_INCREF(self->errors);\r
2564 return self->errors;\r
2565}\r
2566\r
2567static PyObject *\r
2568textiowrapper_chunk_size_get(textio *self, void *context)\r
2569{\r
2570 CHECK_ATTACHED(self);\r
2571 return PyLong_FromSsize_t(self->chunk_size);\r
2572}\r
2573\r
2574static int\r
2575textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)\r
2576{\r
2577 Py_ssize_t n;\r
2578 CHECK_ATTACHED_INT(self);\r
2579 n = PyNumber_AsSsize_t(arg, PyExc_TypeError);\r
2580 if (n == -1 && PyErr_Occurred())\r
2581 return -1;\r
2582 if (n <= 0) {\r
2583 PyErr_SetString(PyExc_ValueError,\r
2584 "a strictly positive integer is required");\r
2585 return -1;\r
2586 }\r
2587 self->chunk_size = n;\r
2588 return 0;\r
2589}\r
2590\r
2591static PyMethodDef textiowrapper_methods[] = {\r
2592 {"detach", (PyCFunction)textiowrapper_detach, METH_NOARGS},\r
2593 {"write", (PyCFunction)textiowrapper_write, METH_VARARGS},\r
2594 {"read", (PyCFunction)textiowrapper_read, METH_VARARGS},\r
2595 {"readline", (PyCFunction)textiowrapper_readline, METH_VARARGS},\r
2596 {"flush", (PyCFunction)textiowrapper_flush, METH_NOARGS},\r
2597 {"close", (PyCFunction)textiowrapper_close, METH_NOARGS},\r
2598\r
2599 {"fileno", (PyCFunction)textiowrapper_fileno, METH_NOARGS},\r
2600 {"seekable", (PyCFunction)textiowrapper_seekable, METH_NOARGS},\r
2601 {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS},\r
2602 {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS},\r
2603 {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS},\r
2604\r
2605 {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS},\r
2606 {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS},\r
2607 {"truncate", (PyCFunction)textiowrapper_truncate, METH_VARARGS},\r
2608 {NULL, NULL}\r
2609};\r
2610\r
2611static PyMemberDef textiowrapper_members[] = {\r
2612 {"encoding", T_OBJECT, offsetof(textio, encoding), READONLY},\r
2613 {"buffer", T_OBJECT, offsetof(textio, buffer), READONLY},\r
2614 {"line_buffering", T_BOOL, offsetof(textio, line_buffering), READONLY},\r
2615 {NULL}\r
2616};\r
2617\r
2618static PyGetSetDef textiowrapper_getset[] = {\r
2619 {"name", (getter)textiowrapper_name_get, NULL, NULL},\r
2620 {"closed", (getter)textiowrapper_closed_get, NULL, NULL},\r
2621/* {"mode", (getter)TextIOWrapper_mode_get, NULL, NULL},\r
2622*/\r
2623 {"newlines", (getter)textiowrapper_newlines_get, NULL, NULL},\r
2624 {"errors", (getter)textiowrapper_errors_get, NULL, NULL},\r
2625 {"_CHUNK_SIZE", (getter)textiowrapper_chunk_size_get,\r
2626 (setter)textiowrapper_chunk_size_set, NULL},\r
2627 {NULL}\r
2628};\r
2629\r
2630PyTypeObject PyTextIOWrapper_Type = {\r
2631 PyVarObject_HEAD_INIT(NULL, 0)\r
2632 "_io.TextIOWrapper", /*tp_name*/\r
2633 sizeof(textio), /*tp_basicsize*/\r
2634 0, /*tp_itemsize*/\r
2635 (destructor)textiowrapper_dealloc, /*tp_dealloc*/\r
2636 0, /*tp_print*/\r
2637 0, /*tp_getattr*/\r
2638 0, /*tps_etattr*/\r
2639 0, /*tp_compare */\r
2640 (reprfunc)textiowrapper_repr,/*tp_repr*/\r
2641 0, /*tp_as_number*/\r
2642 0, /*tp_as_sequence*/\r
2643 0, /*tp_as_mapping*/\r
2644 0, /*tp_hash */\r
2645 0, /*tp_call*/\r
2646 0, /*tp_str*/\r
2647 0, /*tp_getattro*/\r
2648 0, /*tp_setattro*/\r
2649 0, /*tp_as_buffer*/\r
2650 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE\r
2651 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/\r
2652 textiowrapper_doc, /* tp_doc */\r
2653 (traverseproc)textiowrapper_traverse, /* tp_traverse */\r
2654 (inquiry)textiowrapper_clear, /* tp_clear */\r
2655 0, /* tp_richcompare */\r
2656 offsetof(textio, weakreflist), /*tp_weaklistoffset*/\r
2657 0, /* tp_iter */\r
2658 (iternextfunc)textiowrapper_iternext, /* tp_iternext */\r
2659 textiowrapper_methods, /* tp_methods */\r
2660 textiowrapper_members, /* tp_members */\r
2661 textiowrapper_getset, /* tp_getset */\r
2662 0, /* tp_base */\r
2663 0, /* tp_dict */\r
2664 0, /* tp_descr_get */\r
2665 0, /* tp_descr_set */\r
2666 offsetof(textio, dict), /*tp_dictoffset*/\r
2667 (initproc)textiowrapper_init, /* tp_init */\r
2668 0, /* tp_alloc */\r
2669 PyType_GenericNew, /* tp_new */\r
2670};\r